From f743468ec7174088dffde0fd1a61d3afcf78280b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 8 Jun 2010 09:36:27 +0000 Subject: SCI: if song isn't playing, set signal and don't set fadeout/fadein variables - fixes lsl3 music lost after entering/exiting tv room (bug #3007406) svn-id: r49500 --- engines/sci/sound/soundcmd.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index ece4c1430c..4711fe385d 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -666,6 +666,13 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { int volume = musicSlot->volume; + // If sound is not playing currently, set signal directly + if (musicSlot->status != kSoundPlaying) { + warning("cmdFadeSound: fading requested, but sound is currently not playing"); + writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); + return; + } + switch (_argc) { case 2: // SCI0 // SCI0 fades out all the time and when fadeout is done it will also stop the music from playing @@ -688,12 +695,6 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { error("cmdFadeSound: unsupported argc %d", _argc); } - // If sound is not playing currently, set signal directly - if (musicSlot->status != kSoundPlaying) { - warning("cmdFadeSound: fading requested, but sound is currently not playing"); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } - debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); #endif } -- cgit v1.2.3 From 707ccdbac78510a5861d9460d1503e25f6634947 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 13:15:05 +0000 Subject: Add a version check for base36 encoded patches - they were introduced in SCI2 svn-id: r49501 --- engines/sci/resource.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 400f0b1e67..fd81c8d92f 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -621,7 +621,9 @@ void ResourceManager::scanNewSources() { case kSourceDirectory: readResourcePatches(source); #ifdef ENABLE_SCI32 - readResourcePatchesBase36(source); + // We can't use getSciVersion() at this point, thus using _volVersion + if (_volVersion == kResVersionSci32) // SCI2+ + readResourcePatchesBase36(source); #endif readWaveAudioPatches(); break; @@ -1180,6 +1182,8 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { inputName.toUppercase(); if (inputName.hasPrefix("BOOT")) // skip bootdisk.* continue; + if (inputName.hasSuffix("DRV")) // skip AUD*.DRV + continue; inputName.deleteChar(0); // delete the first character (type) inputName.deleteChar(7); // delete the dot -- cgit v1.2.3 From 5ba761a687d9b908f09b218cc22aec548d98c3f6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 13:16:30 +0000 Subject: Made reconstruct_stack() a member of SegManager svn-id: r49503 --- engines/sci/engine/savegame.cpp | 20 +++++++++----------- engines/sci/engine/seg_manager.h | 5 +++++ 2 files changed, 14 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 9bf23dedf5..17dbbc94d9 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -739,15 +739,6 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename return 0; } -// TODO: This should probably be turned into an EngineState or DataStack method. -static void reconstruct_stack(EngineState *retval) { - SegmentId stack_seg = retval->_segMan->findSegmentByType(SEG_TYPE_STACK); - DataStack *stack = (DataStack *)(retval->_segMan->_heap[stack_seg]); - - retval->stack_base = stack->_entries; - retval->stack_top = stack->_entries + stack->_capacity; -} - // TODO: Move thie function to a more appropriate place, such as vm.cpp or script.cpp void SegManager::reconstructScripts(EngineState *s) { uint i; @@ -784,6 +775,14 @@ void SegManager::reconstructScripts(EngineState *s) { } } +void SegManager::reconstructStack(EngineState *s) { + SegmentId stack_seg = findSegmentByType(SEG_TYPE_STACK); + DataStack *stack = (DataStack *)(_heap[stack_seg]); + + s->stack_base = stack->_entries; + s->stack_top = stack->_entries + stack->_capacity; +} + #ifdef USE_OLD_MUSIC_FUNCTIONS static void reconstruct_sounds(EngineState *s) { Song *seeker; @@ -876,10 +875,9 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->_soundCmd->updateSfxState(&retval->_sound); #endif - reconstruct_stack(s); + s->_segMan->reconstructStack(s); s->_segMan->reconstructScripts(s); s->_segMan->reconstructClones(); - s->_gameObj = s->_gameObj; s->script_000 = s->_segMan->getScript(s->_segMan->getScriptSegment(0, SCRIPT_GET_DONT_LOAD)); s->gc_countdown = GC_INTERVAL - 1; diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9312f51f9d..9bcdd80a62 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -95,6 +95,11 @@ public: */ void reconstructScripts(EngineState *s); + /** + * Reconstructs the stack. Used when restoring saved games + */ + void reconstructStack(EngineState *s); + /** * Determines the segment occupied by a certain script, if any. * @param script_nr Number of the script to look up -- cgit v1.2.3 From 12ca735cebcad417e995566e446142ffd41e6323 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 8 Jun 2010 15:08:45 +0000 Subject: SCI: use base36 sync/audio patches for sci1.1 as well and also check if patch filenames make sense, otherwise skip them - also remove hack for excluding bootdisk.* and aud*.drv svn-id: r49509 --- engines/sci/resource.cpp | 47 ++++++++++++++++++++++------------------------- 1 file changed, 22 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index fd81c8d92f..21ffcb4128 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -620,11 +620,9 @@ void ResourceManager::scanNewSources() { switch (source->source_type) { case kSourceDirectory: readResourcePatches(source); -#ifdef ENABLE_SCI32 // We can't use getSciVersion() at this point, thus using _volVersion - if (_volVersion == kResVersionSci32) // SCI2+ + if (_volVersion >= kResVersionSci11) // SCI1.1+ readResourcePatchesBase36(source); -#endif readWaveAudioPatches(); break; case kSourceExtMap: @@ -1180,10 +1178,6 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { name = (*x)->getName(); inputName = (*x)->getName(); inputName.toUppercase(); - if (inputName.hasPrefix("BOOT")) // skip bootdisk.* - continue; - if (inputName.hasSuffix("DRV")) // skip AUD*.DRV - continue; inputName.deleteChar(0); // delete the first character (type) inputName.deleteChar(7); // delete the dot @@ -1191,24 +1185,27 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { // The base36 encoded resource contains the following: // uint16 resourceId, byte noun, byte verb, byte cond, byte seq uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters - byte noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters - byte verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters - byte cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters - byte seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character - ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); - - /* - if (i == kResourceTypeAudio36) - debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); - else - debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); - */ - - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->location_name = name; - psrcPatch->resourceFile = 0; - processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); + uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters + uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters + uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters + uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + // Check, if we got valid results + if ((noun <= 255) && (verb <= 255) && (cond <= 255) && (seq <= 255)) { + ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); + + /* + if (i == kResourceTypeAudio36) + debug("audio36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); + else + debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); + */ + + psrcPatch = new ResourceSource; + psrcPatch->source_type = kSourcePatch; + psrcPatch->location_name = name; + psrcPatch->resourceFile = 0; + processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); + } } } } -- cgit v1.2.3 From 3d0ac2a676bd726a1f390b83812f8f5ac7a52d4a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 18:23:38 +0000 Subject: Merged sync_SegManagerPtr() inside EngineState::saveLoadWithSerializer() svn-id: r49512 --- engines/sci/engine/savegame.cpp | 17 ++++++----------- 1 file changed, 6 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 17dbbc94d9..835ae5b966 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -293,16 +293,6 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(Nodes_seg_id); } -static void sync_SegManagerPtr(Common::Serializer &s, SegManager *&obj) { - s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not - - if (s.isLoading()) - obj->resetSegMan(); - - obj->saveLoadWithSerializer(s); -} - - template <> void syncWithSerializer(Common::Serializer &s, Class &obj) { @@ -381,7 +371,12 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint16LE(picPortLeft); } - sync_SegManagerPtr(s, _segMan); + s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not + + if (s.isLoading()) + _segMan->resetSegMan(); + + _segMan->saveLoadWithSerializer(s); syncArray(s, _segMan->_classTable); -- cgit v1.2.3 From 67690e89a37a27ff34ab515c934edbce887fa897 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 18:44:27 +0000 Subject: Merged _game_run() inside game_run(). Some cleanup svn-id: r49513 --- engines/sci/engine/kevent.cpp | 4 +++- engines/sci/engine/vm.cpp | 52 ++++++++++++++++--------------------------- engines/sci/engine/vm.h | 10 ++------- 3 files changed, 24 insertions(+), 42 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index fd7711f196..519a4bcc8f 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -79,7 +79,9 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { switch (curEvent.type) { case SCI_EVENT_QUIT: - quit_vm(s); + s->script_abort_flag = 1; // Terminate VM + g_debugState.seeking = kDebugSeekNothing; + g_debugState.runningStep = 0; break; case SCI_EVENT_KEYBOARD: diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 1dcdf450ba..9ee2db71b4 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1687,17 +1687,31 @@ static void _init_stack_base_with_selector(EngineState *s, Selector selector) { s->stack_base[1] = NULL_REG; } -static EngineState *_game_run(EngineState *&s) { - bool restoring = false; +void game_run(EngineState **_s) { + EngineState *s = *_s; + + debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID()); + _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector + + // Now: Register the first element on the execution stack + if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) { + g_sci->getSciDebugger()->printObject(s->_gameObj); + error("Failed to run the game! Aborting..."); + return; + } + // and ENGAGE! + + // Attach the debug console on game startup, if requested if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) g_sci->getSciDebugger()->attach(); do { s->_executionStackPosChanged = false; - run_vm(s, restoring); + run_vm(s, s->restoring); + if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested? - restoring = false; + s->restoring = false; s->_executionStack.clear(); s->_executionStackPosChanged = false; @@ -1715,8 +1729,7 @@ static EngineState *_game_run(EngineState *&s) { s->restarting_flags = SCI_GAME_WAS_RESTARTED; } else { - restoring = s->restoring; - if (restoring) { + if (s->restoring) { game_exit(s); s->restoring = false; if (s->script_abort_flag == 2) { @@ -1735,34 +1748,7 @@ static EngineState *_game_run(EngineState *&s) { } } while (true); - return s; -} - -int game_run(EngineState **_s) { - EngineState *s = *_s; - - debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID()); - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector - - // Now: Register the first element on the execution stack- - if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) { - Console *con = g_sci->getSciDebugger(); - con->printObject(s->_gameObj); - warning("Failed to run the game! Aborting..."); - return 1; - } - // and ENGAGE! - _game_run(*_s); - debugC(2, kDebugLevelVM, "Game::play() finished."); - - return 0; -} - -void quit_vm(EngineState *s) { - s->script_abort_flag = 1; // Terminate VM - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; } reg_t *ObjVarRef::getPointer(SegManager *segMan) const { diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 67a6bd0dc3..8c84587284 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -375,9 +375,8 @@ int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion); * Note that, EngineState *s may be changed during the game, e.g. if a game * state is restored. * @param[in] s Pointer to the pointer of the state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_run(EngineState **s); + */ +void game_run(EngineState **s); /** * Restores an SCI game state and runs the game @@ -397,11 +396,6 @@ int game_restore(EngineState **s, char *savegame_name); */ int game_exit(EngineState *s); -/** - * Instructs the virtual machine to abort - */ -void quit_vm(EngineState *s); - /** * Read a PMachine instruction from a memory buffer and return its length. * -- cgit v1.2.3 From 73010518b22c8c24cf09b07bbd6c17655aa1d331 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 19:36:33 +0000 Subject: Fixed compilation when the SCI32 code is disabled svn-id: r49514 --- engines/sci/resource.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 21ffcb4128..dda03e6063 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -620,9 +620,11 @@ void ResourceManager::scanNewSources() { switch (source->source_type) { case kSourceDirectory: readResourcePatches(source); +#ifdef ENABLE_SCI32 // We can't use getSciVersion() at this point, thus using _volVersion if (_volVersion >= kResVersionSci11) // SCI1.1+ readResourcePatchesBase36(source); +#endif readWaveAudioPatches(); break; case kSourceExtMap: -- cgit v1.2.3 From 641ffa5ee3b8036c1a03fc557d0f9705c824eb3e Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 8 Jun 2010 20:29:33 +0000 Subject: Modification to remove false positive "Possible divide by zero" warnings given by cppcheck-1.43. These are incorrect as '/' operator has precedence over >>, but this does improve readability anyway. This bug in cppcheck has already been corrected: http://sourceforge.net/apps/trac/cppcheck/ticket/1714 svn-id: r49517 --- engines/scumm/sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/sound.cpp b/engines/scumm/sound.cpp index 65c50aff14..a845f623c2 100644 --- a/engines/scumm/sound.cpp +++ b/engines/scumm/sound.cpp @@ -1789,7 +1789,7 @@ static void convertADResource(ResourceManager *res, const GameSettings& game, in // There is a constant delay of ppqn/3 before the music starts. if (ppqn / 3 >= 128) - *ptr++ = (ppqn / 3 >> 7) | 0x80; + *ptr++ = ((ppqn / 3) >> 7) | 0x80; *ptr++ = ppqn / 3 & 0x7f; // Now copy the actual music data -- cgit v1.2.3 From 9304b5fbeb4cb3d181d96be6da34073fc5851939 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 21:05:46 +0000 Subject: Merged the restarting_flags, script_abort_flag, and restoring members of the EngineState class into one variable, abortScriptProcessing. The flag kept to signify a game restart has been placed in a boolean, gameWasRestarted svn-id: r49518 --- engines/sci/console.cpp | 7 +++---- engines/sci/engine/game.cpp | 8 +++----- engines/sci/engine/kevent.cpp | 2 +- engines/sci/engine/kmisc.cpp | 8 +++----- engines/sci/engine/savegame.cpp | 6 +----- engines/sci/engine/state.cpp | 6 +----- engines/sci/engine/state.h | 20 ++++++++++---------- engines/sci/engine/vm.cpp | 34 +++++++++++++--------------------- engines/sci/sci.cpp | 4 ++-- 9 files changed, 37 insertions(+), 58 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 814fbff636..e7c70a2aed 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -78,7 +78,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DVar_Register("gc_interval", &engine->_gamestate->script_gc_interval, DVAR_INT, 0); DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); - DVar_Register("script_abort_flag", &_engine->_gamestate->script_abort_flag, DVAR_INT, 0); + DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0); // General DCmd_Register("help", WRAP_METHOD(Console, cmdHelp)); @@ -957,8 +957,7 @@ bool Console::cmdRestoreGame(int argc, const char **argv) { } bool Console::cmdRestartGame(int argc, const char **argv) { - _engine->_gamestate->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; - _engine->_gamestate->script_abort_flag = 1; + _engine->_gamestate->abortScriptProcessing = kAbortRestartGame;; return false; } @@ -2731,7 +2730,7 @@ bool Console::cmdQuit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully - _engine->_gamestate->script_abort_flag = 1; // Terminate VM + _engine->_gamestate->abortScriptProcessing = kAbortQuitGame; // Terminate VM g_debugState.seeking = kDebugSeekNothing; g_debugState.runningStep = 0; diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index bc10099e52..5fa1fc0558 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -75,7 +75,7 @@ int script_init_engine(EngineState *s) { s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet - s->restarting_flags = SCI_GAME_IS_NOT_RESTARTING; + s->gameWasRestarted = false; debug(2, "Engine initialized"); @@ -111,8 +111,6 @@ int game_init(EngineState *s) { if (g_sci->_gfxMenu) g_sci->_gfxMenu->reset(); - s->restoring = false; - s->game_start_time = g_system->getMillis(); s->last_wait_time = s->game_start_time; @@ -134,7 +132,7 @@ int game_init(EngineState *s) { } int game_exit(EngineState *s) { - if (!s->restoring) { + if (s->abortScriptProcessing != kAbortLoadGame) { s->_executionStack.clear(); #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound.sfx_exit(); @@ -152,7 +150,7 @@ int game_exit(EngineState *s) { // the segment manager has already been initialized from the // save game. Deleting or resetting it here will result in // invalidating the loaded save state - if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) + if (s->abortScriptProcessing == kAbortRestartGame) s->_segMan->resetSegMan(); // TODO Free parser segment here diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 519a4bcc8f..4b4d605c68 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -79,7 +79,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { switch (curEvent.type) { case SCI_EVENT_QUIT: - s->script_abort_flag = 1; // Terminate VM + s->abortScriptProcessing = kAbortQuitGame; // Terminate VM g_debugState.seeking = kDebugSeekNothing; g_debugState.runningStep = 0; break; diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index f91ba0fd82..d90255ab41 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -37,11 +37,9 @@ namespace Sci { reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) { - s->restarting_flags |= SCI_GAME_IS_RESTARTING_NOW; - s->shrinkStackToBase(); - s->script_abort_flag = 1; // Force vm to abort ASAP + s->abortScriptProcessing = kAbortRestartGame; // Force vm to abort ASAP return NULL_REG; } @@ -49,11 +47,11 @@ reg_t kRestartGame(EngineState *s, int argc, reg_t *argv) { ** Returns the restarting_flag in acc */ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { - s->r_acc = make_reg(0, (s->restarting_flags & SCI_GAME_WAS_RESTARTED)); + s->r_acc = make_reg(0, s->gameWasRestarted); if (argc) { // Only happens during replay if (!argv[0].toUint16()) // Set restarting flag - s->restarting_flags &= ~SCI_GAME_WAS_RESTARTED; + s->gameWasRestarted = false; } uint32 neededSleep = 30; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 835ae5b966..d6111146bd 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -880,8 +880,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->last_wait_time = g_system->getMillis(); s->game_start_time = g_system->getMillis(); - s->restoring = false; - #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound._it = NULL; s->_sound._flags = s->_sound._flags; @@ -906,9 +904,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } #endif - - s->restoring = true; - s->script_abort_flag = 2; // Abort current game with replay + s->abortScriptProcessing = kAbortLoadGame; s->shrinkStackToBase(); } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index b4a04f8826..849f1f3c89 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -91,8 +91,6 @@ void EngineState::reset(bool isRestoring) { _memorySegmentSize = 0; _soundCmd = 0; - restarting_flags = 0; - execution_stack_base = 0; _executionStackPosChanged = false; @@ -104,6 +102,7 @@ void EngineState::reset(bool isRestoring) { stack_base = 0; stack_top = 0; + abortScriptProcessing = kAbortNone; } last_wait_time = 0; @@ -114,11 +113,8 @@ void EngineState::reset(bool isRestoring) { _throttleLastTime = 0; _throttleTrigger = false; - script_abort_flag = 0; script_step_counter = 0; script_gc_interval = GC_INTERVAL; - - restoring = false; } void EngineState::wait(int16 ticks) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index bcdf66d6ef..6b7dc54a24 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -52,6 +52,13 @@ class SciEvent; class MessageState; class SoundCommandParser; +enum AbortGameState { + kAbortNone = 0, + kAbortLoadGame = 1, + kAbortRestartGame = 2, + kAbortQuitGame = 3 +}; + class DirSeeker { protected: reg_t _outbuffer; @@ -113,8 +120,6 @@ public: #endif SoundCommandParser *_soundCmd; - byte restarting_flags; /**< Flags used for restarting */ - uint32 game_start_time; /**< The time at which the interpreter was started */ uint32 last_wait_time; /**< The last time the game invoked Wait() */ @@ -160,12 +165,9 @@ public: int loadFromLauncher; - /** - * Set this to 1 to abort script execution immediately. Aborting will - * leave the debug exec stack intact. - * Set it to 2 to force a replay afterwards. - */ - int script_abort_flag; // Set to 1 to abort execution. Set to 2 to force a replay afterwards + AbortGameState abortScriptProcessing; + bool gameWasRestarted; + int script_step_counter; // Counts the number of steps executed int script_gc_interval; // Number of steps in between gcs @@ -197,8 +199,6 @@ public: * Resets the engine state. */ void reset(bool isRestoring); - - bool restoring; /**< A flag to indicate if a game is being restored */ }; } // End of namespace Sci diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9ee2db71b4..5cb333db3c 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -816,7 +816,7 @@ void run_vm(EngineState *s, bool restoring) { } - if (s->script_abort_flag || g_engine->shouldQuit()) + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) return; // Emergency // Debug if this has been requested: @@ -1708,14 +1708,14 @@ void game_run(EngineState **_s) { do { s->_executionStackPosChanged = false; - run_vm(s, s->restoring); + run_vm(s, (s->abortScriptProcessing == kAbortLoadGame)); + game_exit(s); - if (s->restarting_flags & SCI_GAME_IS_RESTARTING_NOW) { // Restart was requested? - s->restoring = false; + if (s->abortScriptProcessing == kAbortRestartGame) { + s->abortScriptProcessing = kAbortNone; s->_executionStack.clear(); s->_executionStackPosChanged = false; - game_exit(s); script_init_engine(s); game_init(s); #ifdef USE_OLD_MUSIC_FUNCTIONS @@ -1725,24 +1725,16 @@ void game_run(EngineState **_s) { send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - s->script_abort_flag = 0; - s->restarting_flags = SCI_GAME_WAS_RESTARTED; + s->gameWasRestarted = true; } else { - if (s->restoring) { - game_exit(s); - s->restoring = false; - if (s->script_abort_flag == 2) { - debugC(2, kDebugLevelVM, "Restarting with replay()"); - s->_executionStack.clear(); // Restart with replay - - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); - - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - } - - s->script_abort_flag = 0; - + if (s->abortScriptProcessing == kAbortLoadGame) { + s->abortScriptProcessing = kAbortNone; + debugC(2, kDebugLevelVM, "Restarting with replay()"); + s->_executionStack.clear(); + // Restart with replay + _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); + send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); } else break; // exit loop } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 929bdf3307..8d23d5481c 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -219,6 +219,8 @@ Common::Error SciEngine::run() { _gfxCache = cache; _gfxCursor = cursor; + _gamestate->abortScriptProcessing = kAbortNone; + if (game_init(_gamestate)) { /* Initialize */ warning("Game initialization failed: Aborting..."); // TODO: Add an "init failed" error? @@ -264,8 +266,6 @@ Common::Error SciEngine::run() { game_run(&_gamestate); // Run the game - game_exit(_gamestate); - ConfMan.flushToDisk(); delete _gamestate->_soundCmd; -- cgit v1.2.3 From 6474eaa1b293b24db51d2a14ef345c7c853a26e1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 8 Jun 2010 21:15:53 +0000 Subject: SCI: check for SOL header in audio36 patches svn-id: r49520 --- engines/sci/resource.cpp | 24 +++++++++++++++++++----- 1 file changed, 19 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index dda03e6063..307b4e888e 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1072,15 +1072,17 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource Common::SeekableReadStream *fileStream = 0; Resource *newrsc; ResourceId resId = ResourceId(resourceType, resourceNr, tuple); + ResourceType checkForType = resourceType; byte patchType, patchDataOffset; int fsize; + uint32 audio36Header = 0; // base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts - if (resourceType == kResourceTypeAudio36) - resourceType = kResourceTypeAudio; + if (checkForType == kResourceTypeAudio36) + checkForType = kResourceTypeAudio; - if (resourceType == kResourceTypeSync36) - resourceType = kResourceTypeSync; + if (checkForType == kResourceTypeSync36) + checkForType = kResourceTypeSync; if (source->resourceFile) { fileStream = source->resourceFile->createReadStream(); @@ -1101,10 +1103,22 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource patchType = fileStream->readByte() & 0x7F; patchDataOffset = fileStream->readByte(); + if (resourceType == kResourceTypeAudio36) { + audio36Header = fileStream->readUint32BE(); + } + delete fileStream; - if (patchType != resourceType) { + if (patchType != checkForType) { debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); + return; + } + + if (resourceType == kResourceTypeAudio36) { + if (audio36Header != MKID_BE('SOL\x00')) { + debug("Patching %s failed - audio36 patch doesn't have SOL header", source->location_name.c_str()); + return; + } } // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly -- cgit v1.2.3 From eafc63e57266d690b177bf34fa593e37d8cf320f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 21:21:19 +0000 Subject: Cleanup svn-id: r49521 --- engines/sci/engine/savegame.cpp | 3 --- engines/sci/engine/state.cpp | 16 +++++++++------- engines/sci/engine/vm.cpp | 18 +++++++----------- 3 files changed, 16 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d6111146bd..8dedf3bae9 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -856,9 +856,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->_sound.sfx_exit(); #endif - // Set exec stack base to zero - s->execution_stack_base = 0; - // Now copy all current state information #ifdef USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 849f1f3c89..0c021863c0 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -91,20 +91,22 @@ void EngineState::reset(bool isRestoring) { _memorySegmentSize = 0; _soundCmd = 0; - execution_stack_base = 0; - _executionStackPosChanged = false; - _fileHandles.resize(5); - r_acc = NULL_REG; - restAdjust = 0; - r_prev = NULL_REG; - stack_base = 0; stack_top = 0; abortScriptProcessing = kAbortNone; } + execution_stack_base = 0; + _executionStackPosChanged = false; + + restAdjust = 0; + restAdjustCur = 0; + + r_acc = NULL_REG; + r_prev = NULL_REG; + last_wait_time = 0; gc_countdown = 0; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 5cb333db3c..d7e3c794b3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1713,7 +1713,6 @@ void game_run(EngineState **_s) { if (s->abortScriptProcessing == kAbortRestartGame) { s->abortScriptProcessing = kAbortNone; - s->_executionStack.clear(); s->_executionStackPosChanged = false; script_init_engine(s); @@ -1726,17 +1725,14 @@ void game_run(EngineState **_s) { send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); s->gameWasRestarted = true; - + } else if (s->abortScriptProcessing == kAbortLoadGame) { + s->abortScriptProcessing = kAbortNone; + debugC(2, kDebugLevelVM, "Restarting with replay()"); + // Restart with replay + _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); + send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); } else { - if (s->abortScriptProcessing == kAbortLoadGame) { - s->abortScriptProcessing = kAbortNone; - debugC(2, kDebugLevelVM, "Restarting with replay()"); - s->_executionStack.clear(); - // Restart with replay - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - } else - break; // exit loop + break; // exit loop } } while (true); -- cgit v1.2.3 From dc8b826f5ea77a0173c5ad64d6508f9ec7ed798a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 8 Jun 2010 22:00:59 +0000 Subject: SCI: set default palette after initializing music driver, fixes palette getting messed up when using mt32 emulation svn-id: r49523 --- engines/sci/graphics/palette.cpp | 20 +++++++++++--------- engines/sci/graphics/palette.h | 3 ++- engines/sci/sci.cpp | 2 ++ 3 files changed, 15 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 3c4cf7e964..f9d320122b 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -36,7 +36,7 @@ namespace Sci { -GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette) +GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) : _resMan(resMan), _screen(screen) { int16 color; @@ -57,19 +57,21 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetP _sysPalette.colors[255].b = 255; _sysPaletteChanged = false; - if (autoSetPalette) { - if (_resMan->getViewType() == kViewEga) - setEGA(); - else if (_resMan->isAmiga32color()) - setAmiga(); - else - kernelSetFromResource(999, true); - } } GfxPalette::~GfxPalette() { } +// meant to get called only once during init of engine +void GfxPalette::setDefault() { + if (_resMan->getViewType() == kViewEga) + setEGA(); + else if (_resMan->isAmiga32color()) + setAmiga(); + else + kernelSetFromResource(999, true); +} + #define SCI_PAL_FORMAT_CONSTANT 1 #define SCI_PAL_FORMAT_VARIABLE 0 diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 46fec48739..d84436d708 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -36,9 +36,10 @@ class Screen; */ class GfxPalette { public: - GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool autoSetPalette = true); + GfxPalette(ResourceManager *resMan, GfxScreen *screen); ~GfxPalette(); + void setDefault(); void createFromData(byte *data, Palette *paletteOut); bool setAmiga(); void modifyAmigaPalette(byte *data); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 8d23d5481c..888e72783c 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -254,6 +254,8 @@ Common::Error SciEngine::run() { else #endif _gui->init(_features->usesOldGfxFunctions()); + // Set default (EGA, amiga or resource 999) palette + _gfxPalette->setDefault(); debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); -- cgit v1.2.3 From 81907a8e6fdefbb173d596763e5ba9d9eacd4363 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 8 Jun 2010 23:29:35 +0000 Subject: Don't shrink the stack after reconstructing it, when loading a saved game. Fixes game restoring in some games (e.g. LSL3), a regression from commit #49376 svn-id: r49525 --- engines/sci/engine/savegame.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 8dedf3bae9..815ffa32a9 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -902,7 +902,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { #endif s->abortScriptProcessing = kAbortLoadGame; - s->shrinkStackToBase(); } bool get_savegame_metadata(Common::SeekableReadStream *stream, SavegameMetadata *meta) { -- cgit v1.2.3 From 10aeb33a4253b5df05f19a9bfabc3cc374db096c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 07:32:17 +0000 Subject: Merged restAdjust and restAdjustCur, as we don't save the restAdjust modifier inside saved games (rightfully so). Also, the segment manager is now reset inside the main loop, when the game is restarted, not in game_exit() svn-id: r49533 --- engines/sci/console.cpp | 2 +- engines/sci/engine/game.cpp | 10 ------ engines/sci/engine/scriptdebug.cpp | 6 ++-- engines/sci/engine/state.cpp | 1 - engines/sci/engine/state.h | 3 +- engines/sci/engine/vm.cpp | 63 ++++++++++++++++++-------------------- 6 files changed, 35 insertions(+), 50 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e7c70a2aed..9f1d03df25 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -597,7 +597,7 @@ bool Console::cmdSetParseNodes(int argc, const char **argv) { bool Console::cmdRegisters(int argc, const char **argv) { EngineState *s = _engine->_gamestate; DebugPrintf("Current register values:\n"); - DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjustCur); + DebugPrintf("acc=%04x:%04x prev=%04x:%04x &rest=%x\n", PRINT_REG(s->r_acc), PRINT_REG(s->r_prev), s->restAdjust); if (!s->_executionStack.empty()) { DebugPrintf("pc=%04x:%04x obj=%04x:%04x fp=ST:%04x sp=ST:%04x\n", diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 5fa1fc0558..4f4ae774e0 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -70,7 +70,6 @@ int script_init_engine(EngineState *s) { s->_segMan->initSysStrings(); s->r_acc = s->r_prev = NULL_REG; - s->restAdjust = 0; s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet @@ -144,15 +143,6 @@ int game_exit(EngineState *s) { #endif } - // Note: It's a bad idea to delete the segment manager here - // when loading a game. - // This function is called right after a game is loaded, and - // the segment manager has already been initialized from the - // save game. Deleting or resetting it here will result in - // invalidating the loaded save state - if (s->abortScriptProcessing == kAbortRestartGame) - s->_segMan->resetSegMan(); - // TODO Free parser segment here // TODO Free scripts here diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index b465ab3d4e..159c278e8c 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -205,12 +205,12 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (pos == s->xs->addr.pc) { // Extra information if debugging the current opcode if (opcode == op_callk) { - int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjustCur); + int stackframe = (scr[pos.offset + 2] >> 1) + (s->restAdjust); int argc = ((s->xs->sp)[- stackframe - 1]).offset; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); if (!oldScriptHeader) - argc += (s->restAdjustCur); + argc += (s->restAdjust); printf(" Kernel params: ("); @@ -221,7 +221,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } printf(")\n"); } else if ((opcode == op_send) || (opcode == op_self)) { - int restmod = s->restAdjustCur; + int restmod = s->restAdjust; int stackframe = (scr[pos.offset + 1] >> 1) + restmod; reg_t *sb = s->xs->sp; uint16 selector; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 0c021863c0..2410b2666d 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -102,7 +102,6 @@ void EngineState::reset(bool isRestoring) { _executionStackPosChanged = false; restAdjust = 0; - restAdjustCur = 0; r_acc = NULL_REG; r_prev = NULL_REG; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 6b7dc54a24..3fcefd80c4 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -147,8 +147,7 @@ public: bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ - int16 restAdjust; /**< &rest register (only used for save games) */ - int16 restAdjustCur; /**< current &rest register (only used for save games) */ + int16 restAdjust; /**< current &rest register (only used for save games) */ reg_t r_prev; /**< previous comparison result */ StackPtr stack_base; /**< Pointer to the least stack element */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d7e3c794b3..71d6672eb4 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -718,7 +718,7 @@ void run_vm(EngineState *s, bool restoring) { StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - s->restAdjustCur = s->restAdjust; + s->restAdjust = 0; // &rest adjusts the parameter count by this value // Current execution data: s->xs = &(s->_executionStack.back()); @@ -1116,17 +1116,17 @@ void run_vm(EngineState *s, bool restoring) { case op_call: { // 0x20 (32) int argc = (opparams[1] >> 1) // Given as offset, but we need count - + 1 + s->restAdjustCur; + + 1 + s->restAdjust; StackPtr call_base = s->xs->sp - argc; - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment, s->xs->addr.pc.offset + opparams[0]), s->xs->sp, s->xs->objp, - (validate_arithmetic(*call_base)) + s->restAdjustCur, + (validate_arithmetic(*call_base)) + s->restAdjust, call_base, NULL_SELECTOR, s->xs->objp, s->_executionStack.size()-1, s->xs->local_segment); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment s->xs->sp = call_base; s->_executionStackPosChanged = true; @@ -1139,20 +1139,18 @@ void run_vm(EngineState *s, bool restoring) { s->xs->sp -= (opparams[1] >> 1) + 1; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - if (!oldScriptHeader) { - s->xs->sp -= s->restAdjustCur; - s->restAdjust = 0; // We just used up the s->restAdjustCur, remember? - } + if (!oldScriptHeader) + s->xs->sp -= s->restAdjust; int argc = validate_arithmetic(s->xs->sp[0]); if (!oldScriptHeader) - argc += s->restAdjustCur; + argc += s->restAdjust; callKernelFunc(s, opparams[0], argc); if (!oldScriptHeader) - s->restAdjustCur = s->restAdjust; + s->restAdjust = 0; // Calculate xs again: The kernel function might // have spawned a new VM @@ -1163,27 +1161,27 @@ void run_vm(EngineState *s, bool restoring) { } case op_callb: // 0x22 (34) - temp = ((opparams[1] >> 1) + s->restAdjustCur + 1); + temp = ((opparams[1] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->restAdjustCur; + s->xs->sp[0].offset += s->restAdjust; xs_new = execute_method(s, 0, opparams[0], s_temp, s->xs->objp, s->xs->sp[0].offset, s->xs->sp); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; break; case op_calle: // 0x23 (35) - temp = ((opparams[2] >> 1) + s->restAdjustCur + 1); + temp = ((opparams[2] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; - s->xs->sp[0].offset += s->restAdjustCur; + s->xs->sp[0].offset += s->restAdjust; xs_new = execute_method(s, opparams[0], opparams[1], s_temp, s->xs->objp, s->xs->sp[0].offset, s->xs->sp); - s->restAdjustCur = 0; // Used up the &rest adjustment + s->restAdjust = 0; // Used up the &rest adjustment if (xs_new) // in case of error, keep old stack s->_executionStackPosChanged = true; @@ -1201,7 +1199,6 @@ void run_vm(EngineState *s, bool restoring) { s->_executionStack.pop_back(); s->_executionStackPosChanged = true; - s->restAdjust = s->restAdjustCur; // Update &rest return; // "Hard" return } @@ -1234,16 +1231,16 @@ void run_vm(EngineState *s, bool restoring) { case op_send: // 0x25 (37) s_temp = s->xs->sp; - s->xs->sp -= ((opparams[0] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, s->r_acc, s->r_acc, s_temp, - (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur, s->xs->sp); + (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; break; @@ -1263,17 +1260,17 @@ void run_vm(EngineState *s, bool restoring) { case op_self: // 0x2a (42) s_temp = s->xs->sp; - s->xs->sp -= ((opparams[0] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, s->xs->objp, s->xs->objp, - s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjustCur, + s_temp, (int)(opparams[0] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; break; case op_super: // 0x2b (43) @@ -1283,24 +1280,24 @@ void run_vm(EngineState *s, bool restoring) { error("[VM]: Invalid superclass in object"); else { s_temp = s->xs->sp; - s->xs->sp -= ((opparams[1] >> 1) + s->restAdjustCur); // Adjust stack + s->xs->sp -= ((opparams[1] >> 1) + s->restAdjust); // Adjust stack - s->xs->sp[1].offset += s->restAdjustCur; + s->xs->sp[1].offset += s->restAdjust; xs_new = send_selector(s, r_temp, s->xs->objp, s_temp, - (int)(opparams[1] >> 1) + (uint16)s->restAdjustCur, + (int)(opparams[1] >> 1) + (uint16)s->restAdjust, s->xs->sp); if (xs_new && xs_new != s->xs) s->_executionStackPosChanged = true; - s->restAdjustCur = 0; + s->restAdjust = 0; } break; case op_rest: // 0x2c (44) temp = (uint16) opparams[0]; // First argument - s->restAdjustCur = MAX(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't + s->restAdjust = MAX(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't for (; temp <= s->xs->argc; temp++) PUSH32(s->xs->variables_argp[temp]); @@ -1715,6 +1712,7 @@ void game_run(EngineState **_s) { s->abortScriptProcessing = kAbortNone; s->_executionStackPosChanged = false; + s->_segMan->resetSegMan(); script_init_engine(s); game_init(s); #ifdef USE_OLD_MUSIC_FUNCTIONS @@ -1727,8 +1725,7 @@ void game_run(EngineState **_s) { s->gameWasRestarted = true; } else if (s->abortScriptProcessing == kAbortLoadGame) { s->abortScriptProcessing = kAbortNone; - debugC(2, kDebugLevelVM, "Restarting with replay()"); - // Restart with replay + // Insert a replay selector _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); } else { -- cgit v1.2.3 From 5cb311ee2c352372e8eb494933e2bc36ffd5c4f5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 07:59:42 +0000 Subject: Renamed the SciEvent class to EventManager, to separate it from the sciEvent structure, and removed it from the engine state svn-id: r49534 --- engines/sci/engine/kevent.cpp | 2 +- engines/sci/engine/state.cpp | 6 ++---- engines/sci/engine/state.h | 4 +--- engines/sci/event.cpp | 14 +++++++------- engines/sci/event.h | 6 +++--- engines/sci/graphics/cursor.cpp | 2 +- engines/sci/graphics/cursor.h | 4 ++-- engines/sci/graphics/gui32.cpp | 2 +- engines/sci/graphics/gui32.h | 2 +- engines/sci/graphics/menu.cpp | 2 +- engines/sci/graphics/menu.h | 4 ++-- engines/sci/graphics/portrait.cpp | 2 +- engines/sci/graphics/portrait.h | 4 ++-- engines/sci/sci.cpp | 6 +++--- engines/sci/sci.h | 3 +++ 15 files changed, 31 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 4b4d605c68..d6cb4ebd8e 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -67,7 +67,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { oldx = mousePos.x; oldy = mousePos.y; - curEvent = s->_event->get(mask); + curEvent = g_sci->getEventManager()->get(mask); if (g_sci->getVocabulary()) g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 2410b2666d..e94be73077 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -119,14 +119,12 @@ void EngineState::reset(bool isRestoring) { } void EngineState::wait(int16 ticks) { - uint32 time; - - time = g_system->getMillis(); + uint32 time = g_system->getMillis(); r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000); last_wait_time = time; ticks *= g_debug_sleeptime_factor; - _event->sleep(ticks * 1000 / 60); + g_sci->getEventManager()->sleep(ticks * 1000 / 60); } uint16 EngineState::currentRoomNumber() const { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 3fcefd80c4..ae81e9393d 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -48,7 +48,7 @@ namespace Common { namespace Sci { -class SciEvent; +class EventManager; class MessageState; class SoundCommandParser; @@ -112,8 +112,6 @@ public: /* Non-VM information */ - SciEvent *_event; // Event handling - #ifdef USE_OLD_MUSIC_FUNCTIONS SfxState _sound; /**< sound subsystem */ int sfx_init_flags; /**< flags the sfx subsystem was initialised with */ diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index c3be22b143..cdddb26ca4 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -36,12 +36,12 @@ namespace Sci { #define SCANCODE_ROWS_NR 3 -SciEvent::SciEvent(ResourceManager *resMan) { +EventManager::EventManager(ResourceManager *resMan) { // Check, if font of current game includes extended chars _fontIsExtended = resMan->detectFontExtended(); } -SciEvent::~SciEvent() { +EventManager::~EventManager() { } struct scancode_row { @@ -53,7 +53,7 @@ struct scancode_row { {0x2c, "ZXCVBNM,./"} }; -int SciEvent::altify (int ch) { +int EventManager::altify (int ch) { // Calculates a PC keyboard scancode from a character */ int row; int c = toupper((char)ch); @@ -74,7 +74,7 @@ int SciEvent::altify (int ch) { return ch; } -int SciEvent::numlockify (int c) { +int EventManager::numlockify (int c) { switch (c) { case SCI_KEY_DELETE: return '.'; @@ -114,7 +114,7 @@ static const byte codepagemap_88591toDOS[0x80] = { '?', 0xa4, 0x95, 0xa2, 0x93, '?', 0x94, '?', '?', 0x97, 0xa3, 0x96, 0x81, '?', '?', 0x98 // 0xFx }; -sciEvent SciEvent::getFromScummVM() { +sciEvent EventManager::getFromScummVM() { static int _modifierStates = 0; // FIXME: Avoid non-const global vars sciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; @@ -315,7 +315,7 @@ sciEvent SciEvent::getFromScummVM() { return input; } -sciEvent SciEvent::get(unsigned int mask) { +sciEvent EventManager::get(unsigned int mask) { //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; sciEvent event = { 0, 0, 0, 0 }; @@ -380,7 +380,7 @@ sciEvent SciEvent::get(unsigned int mask) { return event; } -void SciEvent::sleep(uint32 msecs) { +void EventManager::sleep(uint32 msecs) { uint32 time; const uint32 wakeup_time = g_system->getMillis() + msecs; diff --git a/engines/sci/event.h b/engines/sci/event.h index 9301b1ca09..7882e56c02 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -111,10 +111,10 @@ struct sciEvent { #define SCI_KEYMOD_NO_FOOLOCK (~(SCI_KEYMOD_SCRLOCK | SCI_KEYMOD_NUMLOCK | SCI_KEYMOD_CAPSLOCK | SCI_KEYMOD_INSERT)) #define SCI_KEYMOD_ALL 0xFF -class SciEvent { +class EventManager { public: - SciEvent(ResourceManager *resMgr); - ~SciEvent(); + EventManager(ResourceManager *resMgr); + ~EventManager(); sciEvent get(unsigned int mask); diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 2f8393f9ac..8cc99c787c 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -54,7 +54,7 @@ GfxCursor::~GfxCursor() { purgeCache(); } -void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, SciEvent *event) { +void GfxCursor::init(GfxCoordAdjuster *coordAdjuster, EventManager *event) { _coordAdjuster = coordAdjuster; _event = event; } diff --git a/engines/sci/graphics/cursor.h b/engines/sci/graphics/cursor.h index 6d92b3cf5f..7acd14acd9 100644 --- a/engines/sci/graphics/cursor.h +++ b/engines/sci/graphics/cursor.h @@ -45,7 +45,7 @@ public: GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *screen); ~GfxCursor(); - void init(GfxCoordAdjuster *coordAdjuster, SciEvent *event); + void init(GfxCoordAdjuster *coordAdjuster, EventManager *event); void kernelShow(); void kernelHide(); @@ -74,7 +74,7 @@ private: GfxScreen *_screen; GfxPalette *_palette; GfxCoordAdjuster *_coordAdjuster; - SciEvent *_event; + EventManager *_event; int _upscaledHires; diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp index 4b72050d0b..10b2b1c4fd 100644 --- a/engines/sci/graphics/gui32.cpp +++ b/engines/sci/graphics/gui32.cpp @@ -45,7 +45,7 @@ namespace Sci { -SciGui32::SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor) +SciGui32::SciGui32(SegManager *segMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor) : _screen(screen), _palette(palette), _cache(cache), _cursor(cursor) { _coordAdjuster = new GfxCoordAdjuster32(segMan); diff --git a/engines/sci/graphics/gui32.h b/engines/sci/graphics/gui32.h index 99eb03b321..2c73272566 100644 --- a/engines/sci/graphics/gui32.h +++ b/engines/sci/graphics/gui32.h @@ -41,7 +41,7 @@ class GfxPaint32; class SciGui32 { public: - SciGui32(SegManager *segMan, SciEvent *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor); + SciGui32(SegManager *segMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor); ~SciGui32(); void init(); diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 880e1aba12..ac4f1c0653 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -43,7 +43,7 @@ namespace Sci { -GfxMenu::GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) +GfxMenu::GfxMenu(EventManager *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) : _event(event), _segMan(segMan), _gui(gui), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) { _menuSaveHandle = NULL_REG; diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h index 8f23b46ff8..ec344961de 100644 --- a/engines/sci/graphics/menu.h +++ b/engines/sci/graphics/menu.h @@ -83,7 +83,7 @@ typedef Common::List GuiMenuItemList; */ class GfxMenu { public: - GfxMenu(SciEvent *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); + GfxMenu(EventManager *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); ~GfxMenu(); void reset(); @@ -111,7 +111,7 @@ private: uint16 mouseFindMenuItemSelection(Common::Point mousePosition, uint16 menuId); GuiMenuItemEntry *interactiveGetItem(uint16 menuId, uint16 itemId, bool menuChanged); - SciEvent *_event; + EventManager *_event; SegManager *_segMan; SciGui *_gui; GfxPorts *_ports; diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 1208f8ed65..1b4e4bde77 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -38,7 +38,7 @@ namespace Sci { -Portrait::Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) +Portrait::Portrait(ResourceManager *resMan, EventManager *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) : _resMan(resMan), _event(event), _gui(gui), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) { init(); } diff --git a/engines/sci/graphics/portrait.h b/engines/sci/graphics/portrait.h index 4b22e209a3..2f23ced913 100644 --- a/engines/sci/graphics/portrait.h +++ b/engines/sci/graphics/portrait.h @@ -42,7 +42,7 @@ struct PortraitBitmap { */ class Portrait { public: - Portrait(ResourceManager *resMan, SciEvent *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); + Portrait(ResourceManager *resMan, EventManager *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); ~Portrait(); void setupAudio(uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq); @@ -56,7 +56,7 @@ private: void bitsShow(); ResourceManager *_resMan; - SciEvent *_event; + EventManager *_event; SciGui *_gui; GfxPalette *_palette; GfxScreen *_screen; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 888e72783c..b30665a59e 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -190,7 +190,7 @@ Common::Error SciEngine::run() { _gamestate = new EngineState(segMan); - _gamestate->_event = new SciEvent(_resMan); + _eventMan = new EventManager(_resMan); if (script_init_engine(_gamestate)) return Common::kUnknownError; @@ -203,7 +203,7 @@ Common::Error SciEngine::run() { _gfxPaint16 = 0; _gfxPorts = 0; _gui = 0; - _gui32 = new SciGui32(_gamestate->_segMan, _gamestate->_event, screen, palette, cache, cursor); + _gui32 = new SciGui32(_gamestate->_segMan, _eventMan, screen, palette, cache, cursor); } else { #endif _gfxPorts = new GfxPorts(segMan, screen); @@ -280,7 +280,7 @@ Common::Error SciEngine::run() { delete _gfxPalette; delete cursor; delete _gfxScreen; - delete _gamestate->_event; + delete _eventMan; delete segMan; delete _gamestate; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 685f05e685..0902a41139 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -51,6 +51,7 @@ class Kernel; class GameFeatures; class Console; class AudioPlayer; +class EventManager; class GfxAnimate; class GfxCache; @@ -164,6 +165,7 @@ public: inline Kernel *getKernel() const { return _kernel; } inline EngineState *getEngineState() const { return _gamestate; } inline Vocabulary *getVocabulary() const { return _vocabulary; } + inline EventManager *getEventManager() const { return _eventMan; } Common::String getSavegameName(int nr) const; Common::String getSavegamePattern() const; @@ -222,6 +224,7 @@ private: EngineState *_gamestate; Kernel *_kernel; Vocabulary *_vocabulary; + EventManager *_eventMan; Console *_console; OSystem *_system; }; -- cgit v1.2.3 From 95b080f60b74fe9b83d71abc9a80038f025845c6 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Wed, 9 Jun 2010 08:49:37 +0000 Subject: Fix compile errors svn-id: r49535 --- engines/sci/engine/kmisc.cpp | 2 +- engines/sci/graphics/gui.cpp | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index d90255ab41..25fb11d62f 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -80,7 +80,7 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { uint32 duration = curTime - s->_throttleLastTime; if (duration < neededSleep) { - s->_event->sleep(neededSleep - duration); + g_sci->getEventManager()->sleep(neededSleep - duration); s->_throttleLastTime = g_system->getMillis(); } else { s->_throttleLastTime = curTime; diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index e427edd732..df9227b87f 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -59,7 +59,7 @@ SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCa // then it should init it! _coordAdjuster = new GfxCoordAdjuster16(_ports); g_sci->_gfxCoordAdjuster = _coordAdjuster; - _cursor->init(_coordAdjuster, _s->_event); + _cursor->init(_coordAdjuster, g_sci->getEventManager()); _compare = new GfxCompare(_s->_segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); g_sci->_gfxCompare = _compare; _transitions = new GfxTransitions(this, _screen, _palette, g_sci->getResMan()->isVGA()); @@ -71,7 +71,7 @@ SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCa _text16 = new GfxText16(g_sci->getResMan(), _cache, _ports, _paint16, _screen); _controls = new GfxControls(_s->_segMan, _ports, _paint16, _text16, _screen); g_sci->_gfxControls = _controls; - _menu = new GfxMenu(_s->_event, _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor); + _menu = new GfxMenu(g_sci->getEventManager(), _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor); g_sci->_gfxMenu = _menu; } @@ -123,7 +123,7 @@ reg_t SciGui::portraitLoad(Common::String resourceName) { } void SciGui::portraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { - Portrait *myPortrait = new Portrait(g_sci->getResMan(), _s->_event, this, _screen, _palette, _audio, resourceName); + Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), this, _screen, _palette, _audio, resourceName); // TODO: cache portraits // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates // on kDrawCel, yeah this whole stuff makes sense) -- cgit v1.2.3 From 536b2614e8bd7c3c6e47e686a90596460c5448d1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 09:17:48 +0000 Subject: Globals from script 0 are now initialized in script_init_engine(), and are accessed from the relevant variables pointer. Removed direct reference to script 0 from the engine state svn-id: r49536 --- engines/sci/engine/game.cpp | 7 +++---- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/state.cpp | 16 +++++++++++++--- engines/sci/engine/state.h | 16 ++++++---------- engines/sci/engine/vm.cpp | 15 --------------- engines/sci/graphics/animate.cpp | 6 ++---- 6 files changed, 25 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 4f4ae774e0..9e5b9b8990 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -58,14 +58,13 @@ int script_init_engine(EngineState *s) { s->_msgState = new MessageState(s->_segMan); s->gc_countdown = GC_INTERVAL - 1; - SegmentId script_000_segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); - - if (script_000_segment <= 0) { + // Script 0 should always be at segment 1 + if (s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK) != 1) { debug(2, "Failed to instantiate script.000"); return 1; } - s->script_000 = s->_segMan->getScript(script_000_segment); + s->initGlobals(); s->_segMan->initSysStrings(); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 815ffa32a9..255e2700ee 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -870,7 +870,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->_segMan->reconstructStack(s); s->_segMan->reconstructScripts(s); s->_segMan->reconstructClones(); - s->script_000 = s->_segMan->getScript(s->_segMan->getScriptSegment(0, SCRIPT_GET_DONT_LOAD)); + s->initGlobals(); s->gc_countdown = GC_INTERVAL - 1; // Time state: diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index e94be73077..8860666bef 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -85,7 +85,6 @@ void EngineState::reset(bool isRestoring) { #endif if (!isRestoring) { - script_000 = 0; _gameObj = NULL_REG; _memorySegmentSize = 0; @@ -127,12 +126,23 @@ void EngineState::wait(int16 ticks) { g_sci->getEventManager()->sleep(ticks * 1000 / 60); } +void EngineState::initGlobals() { + Script *script_000 = _segMan->getScript(1); + + if (!script_000->_localsBlock) + error("Script 0 has no locals block"); + + variables_seg[VAR_GLOBAL] = script_000->_localsSegment; + variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->_localsBlock->_locals.begin(); + variables_max[VAR_GLOBAL] = script_000->_localsBlock->_locals.size(); +} + uint16 EngineState::currentRoomNumber() const { - return script_000->_localsBlock->_locals[13].toUint16(); + return variables[VAR_GLOBAL][13].toUint16(); } void EngineState::setRoomNumber(uint16 roomNumber) { - script_000->_localsBlock->_locals[13] = make_reg(0, roomNumber); + variables[VAR_GLOBAL][13] = make_reg(0, roomNumber); } void EngineState::shrinkStackToBase() { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index ae81e9393d..aaeb8c49ee 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -79,13 +79,6 @@ enum { MAX_SAVE_DIR_SIZE = MAXPATHLEN }; -/** values for EngineState.restarting_flag */ -enum { - SCI_GAME_IS_NOT_RESTARTING = 0, - SCI_GAME_WAS_RESTARTED = 1, - SCI_GAME_IS_RESTARTING_NOW = 2 -}; - class FileHandle { public: Common::String _name; @@ -145,7 +138,7 @@ public: bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ - int16 restAdjust; /**< current &rest register (only used for save games) */ + int16 restAdjust; /**< current &rest register */ reg_t r_prev; /**< previous comparison result */ StackPtr stack_base; /**< Pointer to the least stack element */ @@ -158,8 +151,6 @@ public: SegmentId variables_seg[4]; ///< Same as above, contains segment IDs int variables_max[4]; ///< Max. values for all variables - Script *script_000; /**< script 000, e.g. for globals */ - int loadFromLauncher; AbortGameState abortScriptProcessing; @@ -171,6 +162,11 @@ public: uint16 currentRoomNumber() const; void setRoomNumber(uint16 roomNumber); + /** + * Sets global variables from script 0 + */ + void initGlobals(); + /** * Shrink execution stack to size. * Contains an assert it is not already smaller. diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 71d6672eb4..851f301a75 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -736,24 +736,9 @@ void run_vm(EngineState *s, bool restoring) { if (!restoring) s->execution_stack_base = s->_executionStack.size() - 1; -#ifndef DISABLE_VALIDATIONS - // Initialize maximum variable count - if (s->script_000->_localsBlock) - s->variables_max[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.size(); - else - s->variables_max[VAR_GLOBAL] = 0; -#endif - - s->variables_seg[VAR_GLOBAL] = s->script_000->_localsSegment; s->variables_seg[VAR_TEMP] = s->variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); s->variables_base[VAR_TEMP] = s->variables_base[VAR_PARAM] = s->stack_base; - // SCI code reads the zeroth argument to determine argc - if (s->script_000->_localsBlock) - s->variables_base[VAR_GLOBAL] = s->variables[VAR_GLOBAL] = s->script_000->_localsBlock->_locals.begin(); - else - s->variables_base[VAR_GLOBAL] = s->variables[VAR_GLOBAL] = NULL; - s->_executionStackPosChanged = true; // Force initialization while (1) { diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index c201b2cfb7..d4def39ebf 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -84,10 +84,8 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { if (!_ignoreFastCast) { // Check if the game has a fastCast object set // if we don't abort kAnimate processing, at least in kq5 there will be animation cels drawn into speech boxes. - reg_t global84 = _s->script_000->_localsBlock->_locals[84]; - - if (!global84.isNull()) { - if (!strcmp(_s->_segMan->getObjectName(global84), "fastCast")) + if (!_s->variables[VAR_GLOBAL][84].isNull()) { + if (!strcmp(_s->_segMan->getObjectName(_s->variables[VAR_GLOBAL][84]), "fastCast")) return false; } } -- cgit v1.2.3 From 2c629a04dd502ff130127072e69724b2eec29c68 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 10:45:54 +0000 Subject: Merged script_init_engine() and game_init() and cleaned up SciEngine::run() a bit svn-id: r49537 --- engines/sci/engine/game.cpp | 30 +++++++++++++----------------- engines/sci/engine/kernel.cpp | 10 +++++----- engines/sci/engine/kernel.h | 23 +++++++++++------------ engines/sci/engine/vm.cpp | 6 ------ engines/sci/engine/vm.h | 8 -------- engines/sci/sci.cpp | 39 ++++++++++++--------------------------- 6 files changed, 41 insertions(+), 75 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 9e5b9b8990..704fe877c7 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -53,13 +53,21 @@ int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) { } #endif -// Architectural stuff: Init/Unintialize engine -int script_init_engine(EngineState *s) { +/*************************************************************/ +/* Game instance stuff: Init/Unitialize state-dependant data */ +/*************************************************************/ + +int game_init(EngineState *s) { + // FIXME Use new VM instantiation code all over the place + // Script 0 needs to be allocated here before anything else! + int script0Segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); + DataStack *stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL); + s->_msgState = new MessageState(s->_segMan); s->gc_countdown = GC_INTERVAL - 1; // Script 0 should always be at segment 1 - if (s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK) != 1) { + if (script0Segment != 1) { debug(2, "Failed to instantiate script.000"); return 1; } @@ -72,23 +80,11 @@ int script_init_engine(EngineState *s) { s->_executionStack.clear(); // Start without any execution stack s->execution_stack_base = -1; // No vm is running yet + s->_executionStackPosChanged = false; + s->abortScriptProcessing = kAbortNone; s->gameWasRestarted = false; - debug(2, "Engine initialized"); - - return 0; -} - -/*************************************************************/ -/* Game instance stuff: Init/Unitialize state-dependant data */ -/*************************************************************/ - -int game_init(EngineState *s) { - // FIXME Use new VM instantiation code all over the place - DataStack *stack; - - stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL); s->stack_base = stack->_entries; s->stack_top = stack->_entries + stack->_capacity; diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 6ebee2dfbd..995ecc72a4 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -392,6 +392,7 @@ SciKernelFunction kfunct_mappers[] = { }; Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { + loadKernelNames(); loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use } @@ -691,7 +692,7 @@ bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { return false; } -void Kernel::setDefaultKernelNames(Common::String gameId) { +void Kernel::setDefaultKernelNames() { _kernelNames = Common::StringArray(sci_default_knames, SCI_KNAMES_DEFAULT_ENTRIES_NR); // Some (later) SCI versions replaced CanBeHere by CantBeHere @@ -730,7 +731,7 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { // In KQ6 CD, the empty kSetSynonyms function has been replaced // with kPortrait. In KQ6 Mac, kPlayBack has been replaced by // kShowMovie. - if (gameId == "kq6") { + if (!strcmp(g_sci->getGameID(), "kq6")) { if (g_sci->getPlatform() == Common::kPlatformMacintosh) _kernelNames[0x84] = "ShowMovie"; else @@ -747,7 +748,7 @@ void Kernel::setDefaultKernelNames(Common::String gameId) { } } -bool Kernel::loadKernelNames(Common::String gameId) { +void Kernel::loadKernelNames() { _kernelNames.clear(); #ifdef ENABLE_SCI32 @@ -757,10 +758,9 @@ bool Kernel::loadKernelNames(Common::String gameId) { setKernelNamesSci2(); else #endif - setDefaultKernelNames(gameId); + setDefaultKernelNames(); mapFunctions(); - return true; } Common::String Kernel::lookupText(reg_t address, int index) { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 8f8f34f74e..b79ba8caaa 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -155,17 +155,6 @@ public: uint getKernelNamesSize() const; const Common::String &getKernelName(uint number) const; - /** - * Loads the kernel function names. - * - * This function reads the kernel function name table from resource_map, - * and fills the _kernelNames array with them. - * The resulting list has the same format regardless of the format of the - * name table of the resource (the format changed between version 0 and 1). - * @return true on success, false on failure - */ - bool loadKernelNames(Common::String gameId); - /** * Determines the selector ID of a selector by its name * @param selectorName Name of the selector to look up @@ -219,10 +208,20 @@ public: Common::String lookupText(reg_t address, int index); private: + /** + * Loads the kernel function names. + * + * This function reads the kernel function name table from resource_map, + * and fills the _kernelNames array with them. + * The resulting list has the same format regardless of the format of the + * name table of the resource (the format changed between version 0 and 1). + */ + void loadKernelNames(); + /** * Sets the default kernel function names, based on the SCI version used */ - void setDefaultKernelNames(Common::String gameId); + void setDefaultKernelNames(); #ifdef ENABLE_SCI32 /** diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 851f301a75..eb2824d9c7 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1694,19 +1694,13 @@ void game_run(EngineState **_s) { game_exit(s); if (s->abortScriptProcessing == kAbortRestartGame) { - s->abortScriptProcessing = kAbortNone; - s->_executionStackPosChanged = false; - s->_segMan->resetSegMan(); - script_init_engine(s); game_init(s); #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound.sfx_reset_player(); #endif _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - s->gameWasRestarted = true; } else if (s->abortScriptProcessing == kAbortLoadGame) { s->abortScriptProcessing = kAbortNone; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 8c84587284..1764284dae 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -282,14 +282,6 @@ void run_vm(EngineState *s, bool restoring); */ void script_debug(EngineState *s); -/** - * Initializes a EngineState block - * @param[in] s The state to initialize - * @return 0 on success, 1 if vocab.996 (the class table) is missing - * or corrupted - */ -int script_init_engine(EngineState *); - /** * Looks up a selector and returns its type and value * varindex is written to iff it is non-NULL and the selector indicates a property of the object. diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index b30665a59e..22c93c1de0 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -163,20 +163,19 @@ Common::Error SciEngine::run() { upscaledHires = GFX_SCREEN_UPSCALED_640x400; // Initialize graphics-related parts - GfxScreen *screen = 0; // invokes initGraphics() if (_resMan->detectHires()) - screen = new GfxScreen(_resMan, 640, 480); + _gfxScreen = new GfxScreen(_resMan, 640, 480); else - screen = new GfxScreen(_resMan, 320, 200, upscaledHires); + _gfxScreen = new GfxScreen(_resMan, 320, 200, upscaledHires); if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) _gfxMacIconBar = new GfxMacIconBar(); - GfxPalette *palette = new GfxPalette(_resMan, screen); - GfxCache *cache = new GfxCache(_resMan, screen, palette); - GfxCursor *cursor = new GfxCursor(_resMan, palette, screen); + _gfxPalette = new GfxPalette(_resMan, _gfxScreen); + _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); + _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen); // Create debugger console. It requires GFX to be initialized _console = new Console(this); @@ -185,16 +184,10 @@ Common::Error SciEngine::run() { // Only SCI0 and SCI01 games used a parser _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; _audio = new AudioPlayer(_resMan); - _features = new GameFeatures(segMan, _kernel); - _gamestate = new EngineState(segMan); - _eventMan = new EventManager(_resMan); - if (script_init_engine(_gamestate)) - return Common::kUnknownError; - #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { _gfxAnimate = 0; @@ -203,23 +196,19 @@ Common::Error SciEngine::run() { _gfxPaint16 = 0; _gfxPorts = 0; _gui = 0; - _gui32 = new SciGui32(_gamestate->_segMan, _eventMan, screen, palette, cache, cursor); + _gui32 = new SciGui32(_gamestate->_segMan, _eventMan, _gfxScreen, _gfxPalette, _gfxCache, _gfxCursor); } else { #endif - _gfxPorts = new GfxPorts(segMan, screen); - _gui = new SciGui(_gamestate, screen, palette, cache, cursor, _gfxPorts, _audio); + _gfxPorts = new GfxPorts(segMan, _gfxScreen); + _gui = new SciGui(_gamestate, _gfxScreen, _gfxPalette, _gfxCache, _gfxCursor, _gfxPorts, _audio); #ifdef ENABLE_SCI32 _gui32 = 0; _gfxFrameout = 0; } #endif - _gfxPalette = palette; - _gfxScreen = screen; - _gfxCache = cache; - _gfxCursor = cursor; - - _gamestate->abortScriptProcessing = kAbortNone; + // Add the after market GM patches for the specified game, if they exist + _resMan->addNewGMPatch(getGameID()); if (game_init(_gamestate)) { /* Initialize */ warning("Game initialization failed: Aborting..."); @@ -227,17 +216,13 @@ Common::Error SciEngine::run() { return Common::kUnknownError; } - // Add the after market GM patches for the specified game, if they exist - _resMan->addNewGMPatch(getGameID()); - script_adjust_opcode_formats(_gamestate); - _kernel->loadKernelNames(getGameID()); SciVersion soundVersion = _features->detectDoSoundType(); _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); - screen->debugUnditherSetState(ConfMan.getBool("undither")); + _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); #ifdef USE_OLD_MUSIC_FUNCTIONS if (game_init_sound(_gamestate, 0, soundVersion)) { @@ -278,7 +263,7 @@ Common::Error SciEngine::run() { delete _gfxPorts; delete _gfxCache; delete _gfxPalette; - delete cursor; + delete _gfxCursor; delete _gfxScreen; delete _eventMan; delete segMan; -- cgit v1.2.3 From 0f2e6b0f856afdfb540b681a194d001d051029f5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 9 Jun 2010 13:27:59 +0000 Subject: SCI: fix multiple playing of the same sound in a row (without using looping) - thx to LordHoto for helping me finding this one out - fixes pharkas right at the start (hammering only played once) svn-id: r49538 --- engines/sci/sound/music.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index fa5716e7cc..254c70a24f 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -317,6 +317,8 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pLoopStream, -1, pSnd->volume, 0, DisposeAfterUse::NO); } else { + // Rewind in case we play the same sample multiple times (non-looped) like in pharkas right at the start + pSnd->pStreamAud->rewind(); _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, pSnd->pStreamAud, -1, pSnd->volume, 0, DisposeAfterUse::NO); -- cgit v1.2.3 From 015262a0ee77abcbd49d9ab40909daa77d303a81 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 14:06:16 +0000 Subject: Fixed compilation when the old sound code is used svn-id: r49540 --- engines/sci/engine/savegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 255e2700ee..3ad4ed096e 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -864,7 +864,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->sfx_init_flags = s->sfx_init_flags; s->_sound._songlib.freeSounds(); s->_sound._songlib = temp; - s->_soundCmd->updateSfxState(&retval->_sound); + s->_soundCmd->updateSfxState(&s->_sound); #endif s->_segMan->reconstructStack(s); -- cgit v1.2.3 From 32d7f7ddb09c908104dc83217aa08f6083189d17 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 14:16:00 +0000 Subject: Disabled the mouse warping code, as it can be annoying in windowed mode svn-id: r49542 --- engines/sci/graphics/cursor.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 8cc99c787c..14ab3fcdaf 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -258,12 +258,16 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu } void GfxCursor::setPosition(Common::Point pos) { + // This code has been disabled because it's annoying in windowed mode. The engine shouldn't move + // the mouse cursor whenever it wants, it interferes with other programs +#if 0 if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); } else { _screen->adjustToUpscaledCoordinates(pos.y, pos.x); g_system->warpMouse(pos.x, pos.y); } +#endif } Common::Point GfxCursor::getPosition() { @@ -289,6 +293,9 @@ Common::Point GfxCursor::getPosition() { } void GfxCursor::refreshPosition() { + // This code has been disabled because it's annoying in windowed mode. The engine shouldn't move + // the mouse cursor whenever it wants, it interferes with other programs +#if 0 bool clipped = false; Common::Point mousePoint = getPosition(); @@ -311,6 +318,7 @@ void GfxCursor::refreshPosition() { // FIXME: Do this only when mouse is grabbed? if (clipped) setPosition(mousePoint); +#endif } void GfxCursor::kernelSetMoveZone(Common::Rect zone) { -- cgit v1.2.3 From 3c9ab81a0764298baf1b604914a7c2e3f33f6b1a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 15:21:10 +0000 Subject: Fixed regression from commit #49537 svn-id: r49543 --- engines/sci/engine/kernel.cpp | 1 - engines/sci/engine/kernel.h | 2 +- engines/sci/sci.cpp | 1 + 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 995ecc72a4..4d0e981f31 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -392,7 +392,6 @@ SciKernelFunction kfunct_mappers[] = { }; Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { - loadKernelNames(); loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b79ba8caaa..2f1c867474 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -207,7 +207,6 @@ public: */ Common::String lookupText(reg_t address, int index); -private: /** * Loads the kernel function names. * @@ -218,6 +217,7 @@ private: */ void loadKernelNames(); +private: /** * Sets the default kernel function names, based on the SCI version used */ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 22c93c1de0..8f5cfbba65 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -217,6 +217,7 @@ Common::Error SciEngine::run() { } script_adjust_opcode_formats(_gamestate); + _kernel->loadKernelNames(); SciVersion soundVersion = _features->detectDoSoundType(); -- cgit v1.2.3 From a542ce174b68e32a9266c8efaea7be877b74fccc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 15:28:14 +0000 Subject: Proper fix for kernel name loading (regression from commit #49537) svn-id: r49544 --- engines/sci/engine/kernel.cpp | 1 + engines/sci/engine/kernel.h | 2 +- engines/sci/sci.cpp | 1 - 3 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4d0e981f31..93af161219 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -394,6 +394,7 @@ SciKernelFunction kfunct_mappers[] = { Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use + loadKernelNames(); // must be called after the selectors are set } Kernel::~Kernel() { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 2f1c867474..b79ba8caaa 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -207,6 +207,7 @@ public: */ Common::String lookupText(reg_t address, int index); +private: /** * Loads the kernel function names. * @@ -217,7 +218,6 @@ public: */ void loadKernelNames(); -private: /** * Sets the default kernel function names, based on the SCI version used */ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 8f5cfbba65..22c93c1de0 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -217,7 +217,6 @@ Common::Error SciEngine::run() { } script_adjust_opcode_formats(_gamestate); - _kernel->loadKernelNames(); SciVersion soundVersion = _features->detectDoSoundType(); -- cgit v1.2.3 From d191c9d0f935d280d7c1a7e71e3e13bbb76ee893 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 17:04:03 +0000 Subject: Limit kPortrait to be used in the Windows version of KQ6 only svn-id: r49545 --- engines/sci/engine/kernel.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 93af161219..08aa65aa6d 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -728,14 +728,14 @@ void Kernel::setDefaultKernelNames() { break; case SCI_VERSION_1_1: - // In KQ6 CD, the empty kSetSynonyms function has been replaced - // with kPortrait. In KQ6 Mac, kPlayBack has been replaced by - // kShowMovie. + // In the Windows version of KQ6 CD, the empty kSetSynonyms + // function has been replaced with kPortrait. In KQ6 Mac, + // kPlayBack has been replaced by kShowMovie. if (!strcmp(g_sci->getGameID(), "kq6")) { - if (g_sci->getPlatform() == Common::kPlatformMacintosh) - _kernelNames[0x84] = "ShowMovie"; - else + if (g_sci->getPlatform() == Common::kPlatformWindows) _kernelNames[0x26] = "Portrait"; + else if (g_sci->getPlatform() == Common::kPlatformMacintosh) + _kernelNames[0x84] = "ShowMovie"; } _kernelNames[0x71] = "PalVary"; -- cgit v1.2.3 From c486b77bb7d96908d7df1e00b6a61b92fbd176ee Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 18:42:21 +0000 Subject: Fixed crash in SCI2.1 games svn-id: r49546 --- engines/sci/engine/kernel.cpp | 5 ++--- engines/sci/engine/kernel.h | 6 +++--- engines/sci/engine/kernel32.cpp | 4 ++-- engines/sci/sci.cpp | 14 ++++++++------ 4 files changed, 15 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 08aa65aa6d..2315dc384f 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -394,7 +394,6 @@ SciKernelFunction kfunct_mappers[] = { Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use - loadKernelNames(); // must be called after the selectors are set } Kernel::~Kernel() { @@ -748,12 +747,12 @@ void Kernel::setDefaultKernelNames() { } } -void Kernel::loadKernelNames() { +void Kernel::loadKernelNames(GameFeatures *features) { _kernelNames.clear(); #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2_1) - setKernelNamesSci21(); + setKernelNamesSci21(features); else if (getSciVersion() == SCI_VERSION_2) setKernelNamesSci2(); else diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b79ba8caaa..990e2aff17 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -207,7 +207,6 @@ public: */ Common::String lookupText(reg_t address, int index); -private: /** * Loads the kernel function names. * @@ -216,8 +215,9 @@ private: * The resulting list has the same format regardless of the format of the * name table of the resource (the format changed between version 0 and 1). */ - void loadKernelNames(); + void loadKernelNames(GameFeatures *features); +private: /** * Sets the default kernel function names, based on the SCI version used */ @@ -232,7 +232,7 @@ private: /** * Sets the default kernel function names to the SCI2.1 kernel functions */ - void setKernelNamesSci21(); + void setKernelNamesSci21(GameFeatures *features); #endif /** diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 0afdc3f2eb..f279d9a66f 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -378,7 +378,7 @@ void Kernel::setKernelNamesSci2() { _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesSci2); } -void Kernel::setKernelNamesSci21() { +void Kernel::setKernelNamesSci21(GameFeatures *features) { // Some SCI games use a modified SCI2 kernel table instead of the SCI2.1/SCI3 kernel table. // The GK2 demo does this as well as at least one version of KQ7. We detect which version // to use based on where kDoSound is called from Sound::play(). @@ -386,7 +386,7 @@ void Kernel::setKernelNamesSci21() { // This is interesting because they all have the same interpreter version (2.100.002), yet // they would not be compatible with other games of the same interpreter. - if (g_sci->_features->detectSci21KernelType() == SCI_VERSION_2) { + if (features->detectSci21KernelType() == SCI_VERSION_2) { _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo); // OnMe is IsOnMe here, but they should be compatible _kernelNames[0x23] = "Robot"; // Graph in SCI2 diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 22c93c1de0..1d0bbadd63 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -141,6 +141,9 @@ Common::Error SciEngine::run() { return Common::kNoGameDataFoundError; } + // Add the after market GM patches for the specified game, if they exist + _resMan->addNewGMPatch(getGameID()); + SegManager *segMan = new SegManager(_resMan); // Scale the screen, if needed @@ -170,6 +173,8 @@ Common::Error SciEngine::run() { else _gfxScreen = new GfxScreen(_resMan, 320, 200, upscaledHires); + _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); + if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) _gfxMacIconBar = new GfxMacIconBar(); @@ -181,10 +186,10 @@ Common::Error SciEngine::run() { _console = new Console(this); _kernel = new Kernel(_resMan, segMan); + _features = new GameFeatures(segMan, _kernel); // Only SCI0 and SCI01 games used a parser _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; _audio = new AudioPlayer(_resMan); - _features = new GameFeatures(segMan, _kernel); _gamestate = new EngineState(segMan); _eventMan = new EventManager(_resMan); @@ -207,14 +212,13 @@ Common::Error SciEngine::run() { } #endif - // Add the after market GM patches for the specified game, if they exist - _resMan->addNewGMPatch(getGameID()); - if (game_init(_gamestate)) { /* Initialize */ warning("Game initialization failed: Aborting..."); // TODO: Add an "init failed" error? return Common::kUnknownError; } + + _kernel->loadKernelNames(_features); // Must be called after game_init() script_adjust_opcode_formats(_gamestate); @@ -222,8 +226,6 @@ Common::Error SciEngine::run() { _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); - _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); - #ifdef USE_OLD_MUSIC_FUNCTIONS if (game_init_sound(_gamestate, 0, soundVersion)) { warning("Game initialization failed: Error in sound subsystem. Aborting..."); -- cgit v1.2.3 From 5d71ae952f47084da758cb5d2df0e53a6c663111 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 20:12:25 +0000 Subject: The EngineState is no longer recreated when a game is restored, thus we don't need to refresh pointers to it svn-id: r49549 --- engines/sci/engine/savegame.cpp | 1 - engines/sci/graphics/animate.h | 3 --- engines/sci/graphics/gui.cpp | 5 ----- engines/sci/graphics/gui.h | 3 --- 4 files changed, 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 3ad4ed096e..224115f95f 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -895,7 +895,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { g_sci->_gui32->init(); } else { #endif - g_sci->_gui->resetEngineState(s); g_sci->_gui->init(g_sci->_features->usesOldGfxFunctions()); #ifdef ENABLE_SCI32 } diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 706b7182cf..324ca0d700 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -90,9 +90,6 @@ public: GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, GfxPaint16 *paint16, GfxScreen *screen, GfxPalette *palette, GfxCursor *cursor, GfxTransitions *transitions); virtual ~GfxAnimate(); - // FIXME: Don't store EngineState - void resetEngineState(EngineState *newState) { _s = newState; } - void disposeLastCast(); bool invoke(List *list, int argc, reg_t *argv); void makeSortedList(List *list); diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index df9227b87f..63ac6c0a05 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -86,11 +86,6 @@ SciGui::~SciGui() { delete _coordAdjuster; } -void SciGui::resetEngineState(EngineState *s) { - _s = s; - _animate->resetEngineState(s); -} - void SciGui::init(bool usesOldGfxFunctions) { _ports->init(usesOldGfxFunctions, this, _paint16, _text16); _paint16->init(_animate, _text16); diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index 7663036117..8e4abdf5b7 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -61,9 +61,6 @@ public: virtual void portraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); virtual void portraitUnload(uint16 portraitId); - // FIXME: Don't store EngineState - virtual void resetEngineState(EngineState *s); - protected: GfxCursor *_cursor; EngineState *_s; -- cgit v1.2.3 From e533289e07f9bbbc195d91619582df6eca39ec2a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 9 Jun 2010 20:32:55 +0000 Subject: SCI: document raw lipsync data skipping in readAudioMapSCI11() svn-id: r49550 --- engines/sci/resource_audio.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 57efbdcb38..2a5b56d4bc 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -334,6 +334,8 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { } if (n & 0x40) { + // This seems to define the size of raw lipsync data (at least in kq6), may also just be general appended + // data syncSize += READ_LE_UINT16(ptr); ptr += 2; } -- cgit v1.2.3 From 14437e6394172dcabd0f5255b724c38f5b862332 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 9 Jun 2010 21:41:20 +0000 Subject: The segment manager is now initialized before the graphics subsystem. Fixes the detection of the fastCast object on startup, and hence fixes LSL1VGA svn-id: r49553 --- engines/sci/engine/game.cpp | 7 +++---- engines/sci/sci.cpp | 20 +++++++++++++------- 2 files changed, 16 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp index 704fe877c7..04f8501027 100644 --- a/engines/sci/engine/game.cpp +++ b/engines/sci/engine/game.cpp @@ -74,6 +74,9 @@ int game_init(EngineState *s) { s->initGlobals(); + if (s->abortScriptProcessing == kAbortRestartGame && g_sci->_gfxMenu) + g_sci->_gfxMenu->reset(); + s->_segMan->initSysStrings(); s->r_acc = s->r_prev = NULL_REG; @@ -101,10 +104,6 @@ int game_init(EngineState *s) { voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); } - // Initialize menu TODO: Actually this should be another init() - if (g_sci->_gfxMenu) - g_sci->_gfxMenu->reset(); - s->game_start_time = g_system->getMillis(); s->last_wait_time = s->game_start_time; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 1d0bbadd63..d5cab1adc9 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -44,6 +44,7 @@ #include "sci/sound/soundcmd.h" #include "sci/graphics/gui.h" #include "sci/graphics/maciconbar.h" +#include "sci/graphics/menu.h" #include "sci/graphics/ports.h" #include "sci/graphics/palette.h" #include "sci/graphics/cursor.h" @@ -193,6 +194,15 @@ Common::Error SciEngine::run() { _gamestate = new EngineState(segMan); _eventMan = new EventManager(_resMan); + // The game needs to be initialized before the graphics system is initialized, as + // the graphics code checks parts of the seg manager upon initialization (e.g. for + // the presence of the fastCast object) + if (game_init(_gamestate)) { /* Initialize */ + warning("Game initialization failed: Aborting..."); + // TODO: Add an "init failed" error? + return Common::kUnknownError; + } + #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { _gfxAnimate = 0; @@ -209,15 +219,11 @@ Common::Error SciEngine::run() { #ifdef ENABLE_SCI32 _gui32 = 0; _gfxFrameout = 0; - } -#endif - if (game_init(_gamestate)) { /* Initialize */ - warning("Game initialization failed: Aborting..."); - // TODO: Add an "init failed" error? - return Common::kUnknownError; + g_sci->_gfxMenu->reset(); } - +#endif + _kernel->loadKernelNames(_features); // Must be called after game_init() script_adjust_opcode_formats(_gamestate); -- cgit v1.2.3 From ede57eb61b541c9487d2068f01fb28be2e984f5f Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 10 Jun 2010 04:29:34 +0000 Subject: Removed some unnecessary whitespace. (Or should I have saved that for the rapidly approaching, much coveted r50000? :-) svn-id: r49558 --- engines/agos/vga_e2.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/agos/vga_e2.cpp b/engines/agos/vga_e2.cpp index 1bbc7f4849..54ec45b967 100644 --- a/engines/agos/vga_e2.cpp +++ b/engines/agos/vga_e2.cpp @@ -265,7 +265,7 @@ void AGOSEngine::vc53_dissolveIn() { *dst &= color; *dst |= *src & 0xF; - _system->unlockScreen(); + _system->unlockScreen(); dissolveCount--; if (!dissolveCount) { @@ -319,7 +319,7 @@ void AGOSEngine::vc54_dissolveOut() { dst += xoffs; *dst = color; - _system->unlockScreen(); + _system->unlockScreen(); dissolveCount--; if (!dissolveCount) { @@ -388,7 +388,7 @@ void AGOSEngine::vc56_fullScreen() { src += 320; dst += screen->pitch; } - _system->unlockScreen(); + _system->unlockScreen(); fullFade(); } -- cgit v1.2.3 From 9b8e4e8359083ba322c19701579762104b7a6826 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 07:32:05 +0000 Subject: Moved all of the game init/run/exit logic inside the SciEngine class svn-id: r49559 --- engines/sci/detection.cpp | 7 +- engines/sci/engine/game.cpp | 151 -------------------------------------------- engines/sci/engine/vm.cpp | 51 --------------- engines/sci/engine/vm.h | 59 ----------------- engines/sci/module.mk | 1 - engines/sci/sci.cpp | 132 +++++++++++++++++++++++++++++++++++++- engines/sci/sci.h | 41 ++++++++++++ 7 files changed, 177 insertions(+), 265 deletions(-) delete mode 100644 engines/sci/engine/game.cpp (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 1ccfc6bf02..f36bae2d6d 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -36,7 +36,6 @@ #include "sci/engine/script.h" #include "sci/engine/seg_manager.h" #include "sci/engine/state.h" -#include "sci/engine/vm.h" // for convertSierraGameId namespace Sci { @@ -198,6 +197,12 @@ static const OldNewIdTableEntry s_oldNewTable[] = { { "", "", SCI_VERSION_NONE } }; +/** + * Converts the builtin Sierra game IDs to the ones we use in ScummVM + * @param[in] gameId The internal game ID + * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos + * @return The equivalent ScummVM game id + */ Common::String convertSierraGameId(Common::String sierraId, uint32 *gameFlags, ResourceManager *resMan) { // Convert the id to lower case, so that we match all upper/lower case variants. sierraId.toLowercase(); diff --git a/engines/sci/engine/game.cpp b/engines/sci/engine/game.cpp deleted file mode 100644 index 04f8501027..0000000000 --- a/engines/sci/engine/game.cpp +++ /dev/null @@ -1,151 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/system.h" -#include "common/file.h" - -#include "engines/advancedDetector.h" // for ADGF_DEMO - -#include "sci/sci.h" -#include "sci/resource.h" -#include "sci/engine/features.h" -#include "sci/engine/state.h" -#include "sci/engine/kernel.h" -#include "sci/engine/message.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/menu.h" -#include "sci/sound/audio.h" -#include "sci/sound/music.h" - -namespace Sci { - -#ifdef USE_OLD_MUSIC_FUNCTIONS -int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion) { - if (getSciVersion() > SCI_VERSION_0_LATE) - sound_flags |= SFX_STATE_FLAG_MULTIPLAY; - - s->sfx_init_flags = sound_flags; - s->_sound.sfx_init(g_sci->getResMan(), sound_flags, soundVersion); - - return 0; -} -#endif - -/*************************************************************/ -/* Game instance stuff: Init/Unitialize state-dependant data */ -/*************************************************************/ - -int game_init(EngineState *s) { - // FIXME Use new VM instantiation code all over the place - // Script 0 needs to be allocated here before anything else! - int script0Segment = s->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); - DataStack *stack = s->_segMan->allocateStack(VM_STACK_SIZE, NULL); - - s->_msgState = new MessageState(s->_segMan); - s->gc_countdown = GC_INTERVAL - 1; - - // Script 0 should always be at segment 1 - if (script0Segment != 1) { - debug(2, "Failed to instantiate script.000"); - return 1; - } - - s->initGlobals(); - - if (s->abortScriptProcessing == kAbortRestartGame && g_sci->_gfxMenu) - g_sci->_gfxMenu->reset(); - - s->_segMan->initSysStrings(); - - s->r_acc = s->r_prev = NULL_REG; - - s->_executionStack.clear(); // Start without any execution stack - s->execution_stack_base = -1; // No vm is running yet - s->_executionStackPosChanged = false; - - s->abortScriptProcessing = kAbortNone; - s->gameWasRestarted = false; - - s->stack_base = stack->_entries; - s->stack_top = stack->_entries + stack->_capacity; - - if (!script_instantiate(g_sci->getResMan(), s->_segMan, 0)) { - warning("game_init(): Could not instantiate script 0"); - return 1; - } - - // Reset parser - Vocabulary *voc = g_sci->getVocabulary(); - if (voc) { - voc->parserIsValid = false; // Invalidate parser - voc->parser_event = NULL_REG; // Invalidate parser event - voc->parser_base = make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); - } - - s->game_start_time = g_system->getMillis(); - s->last_wait_time = s->game_start_time; - - srand(g_system->getMillis()); // Initialize random number generator - - s->_gameObj = g_sci->getResMan()->findGameObject(); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (s->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) - game_init_sound(s, 0, g_sci->_features->detectDoSoundType()); -#endif - - // Load game language into printLang property of game object - // FIXME: It's evil to achieve this as a side effect of a getter. - // Much better to have an explicit init method for this. - g_sci->getSciLanguage(); - - return 0; -} - -int game_exit(EngineState *s) { - if (s->abortScriptProcessing != kAbortLoadGame) { - s->_executionStack.clear(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_exit(); - // Reinit because some other code depends on having a valid state - game_init_sound(s, SFX_STATE_FLAG_NOSOUND, g_sci->_features->detectDoSoundType()); -#else - g_sci->_audio->stopAllAudio(); - s->_soundCmd->clearPlayList(); -#endif - } - - // TODO Free parser segment here - - // TODO Free scripts here - - // Close all opened file handles - s->_fileHandles.clear(); - s->_fileHandles.resize(5); - - return 0; -} - -} // End of namespace Sci diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index eb2824d9c7..2c92bdadc3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1664,57 +1664,6 @@ void run_vm(EngineState *s, bool restoring) { } } -static void _init_stack_base_with_selector(EngineState *s, Selector selector) { - s->stack_base[0] = make_reg(0, (uint16)selector); - s->stack_base[1] = NULL_REG; -} - -void game_run(EngineState **_s) { - EngineState *s = *_s; - - debugC(2, kDebugLevelVM, "Calling %s::play()", g_sci->getGameID()); - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); // Call the play selector - - // Now: Register the first element on the execution stack - if (!send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base)) { - g_sci->getSciDebugger()->printObject(s->_gameObj); - error("Failed to run the game! Aborting..."); - return; - } - - // and ENGAGE! - - // Attach the debug console on game startup, if requested - if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) - g_sci->getSciDebugger()->attach(); - - do { - s->_executionStackPosChanged = false; - run_vm(s, (s->abortScriptProcessing == kAbortLoadGame)); - game_exit(s); - - if (s->abortScriptProcessing == kAbortRestartGame) { - s->_segMan->resetSegMan(); - game_init(s); -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_reset_player(); -#endif - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.play); - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - s->gameWasRestarted = true; - } else if (s->abortScriptProcessing == kAbortLoadGame) { - s->abortScriptProcessing = kAbortNone; - // Insert a replay selector - _init_stack_base_with_selector(s, g_sci->getKernel()->_selectorCache.replay); - send_selector(s, s->_gameObj, s->_gameObj, s->stack_base, 2, s->stack_base); - } else { - break; // exit loop - } - } while (true); - - debugC(2, kDebugLevelVM, "Game::play() finished."); -} - reg_t *ObjVarRef::getPointer(SegManager *segMan) const { Object *o = segMan->getObject(obj); return o ? &o->getVariableRef(varindex) : 0; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 1764284dae..fa57a1151c 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -329,65 +329,6 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_n */ void script_uninstantiate(SegManager *segMan, int script_nr); -/** - * Converts the builtin Sierra game IDs to the ones we use in ScummVM - * @param[in] gameId The internal game ID - * @param[in] gameFlags The game's flags, which are adjusted accordingly for demos - * @return The equivalent ScummVM game id - */ -Common::String convertSierraGameId(const char *gameId, uint32 *gameFlags, ResourceManager *resMan); - -/** - * Initializes an SCI game - * This function must be run before script_run() is executed. Graphics data - * is initialized iff s->gfx_state != NULL. - * @param[in] s The state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_init(EngineState *s); - -#ifdef USE_OLD_MUSIC_FUNCTIONS -/** - * Initializes the sound part of an SCI game - * This function may only be called if game_init() did not initialize - * the sound data. - * @param[in] s The state to initialize the sound in - * @param[in] sound_flags Flags to pass to the sound subsystem - * @param[in] soundVersion sound-version that got detected during game init - * @return 0 on success, 1 if an error occured - */ -int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion); -#endif - -/** - * Runs an SCI game - * This is the main function for SCI games. It takes a valid state, loads - * script 0 to it, finds the game object, allocates a stack, and runs the - * init method of the game object. In layman's terms, this runs an SCI game. - * Note that, EngineState *s may be changed during the game, e.g. if a game - * state is restored. - * @param[in] s Pointer to the pointer of the state to operate on - */ -void game_run(EngineState **s); - -/** - * Restores an SCI game state and runs the game - * This restores a savegame; otherwise, it behaves just like game_run(). - * @param[in] s Pointer to the pointer of the state to - * operate on - * @param[in] savegame_name Name of the savegame to restore - * @return 0 on success, 1 if an error occured. - */ -int game_restore(EngineState **s, char *savegame_name); - -/** - * Uninitializes an initialized SCI game - * This function should be run after each script_run() call. - * @param[in] s The state to operate on - * @return 0 on success, 1 if an error occured. - */ -int game_exit(EngineState *s); - /** * Read a PMachine instruction from a memory buffer and return its length. * diff --git a/engines/sci/module.mk b/engines/sci/module.mk index a2cfd38f95..4860ac7c2f 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -10,7 +10,6 @@ MODULE_OBJS := \ sci.o \ util.o \ engine/features.o \ - engine/game.o \ engine/gc.o \ engine/kernel.o \ engine/kevent.o \ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index d5cab1adc9..08236597b4 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -36,6 +36,7 @@ #include "sci/event.h" #include "sci/engine/features.h" +#include "sci/engine/message.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/script.h" // for script_adjust_opcode_formats @@ -197,7 +198,7 @@ Common::Error SciEngine::run() { // The game needs to be initialized before the graphics system is initialized, as // the graphics code checks parts of the seg manager upon initialization (e.g. for // the presence of the fastCast object) - if (game_init(_gamestate)) { /* Initialize */ + if (!initGame()) { /* Initialize */ warning("Game initialization failed: Aborting..."); // TODO: Add an "init failed" error? return Common::kUnknownError; @@ -259,7 +260,7 @@ Common::Error SciEngine::run() { _gamestate->loadFromLauncher = -1; } - game_run(&_gamestate); // Run the game + runGame(); ConfMan.flushToDisk(); @@ -280,6 +281,133 @@ Common::Error SciEngine::run() { return Common::kNoError; } +bool SciEngine::initGame() { + // Script 0 needs to be allocated here before anything else! + int script0Segment = _gamestate->_segMan->getScriptSegment(0, SCRIPT_GET_LOCK); + DataStack *stack = _gamestate->_segMan->allocateStack(VM_STACK_SIZE, NULL); + + _gamestate->_msgState = new MessageState(_gamestate->_segMan); + _gamestate->gc_countdown = GC_INTERVAL - 1; + + // Script 0 should always be at segment 1 + if (script0Segment != 1) { + debug(2, "Failed to instantiate script.000"); + return false; + } + + _gamestate->initGlobals(); + + if (_gamestate->abortScriptProcessing == kAbortRestartGame && _gfxMenu) + _gfxMenu->reset(); + + _gamestate->_segMan->initSysStrings(); + + _gamestate->r_acc = _gamestate->r_prev = NULL_REG; + + _gamestate->_executionStack.clear(); // Start without any execution stack + _gamestate->execution_stack_base = -1; // No vm is running yet + _gamestate->_executionStackPosChanged = false; + + _gamestate->abortScriptProcessing = kAbortNone; + _gamestate->gameWasRestarted = false; + + _gamestate->stack_base = stack->_entries; + _gamestate->stack_top = stack->_entries + stack->_capacity; + + if (!script_instantiate(_resMan, _gamestate->_segMan, 0)) { + warning("initGame(): Could not instantiate script 0"); + return false; + } + + // Reset parser + if (_vocabulary) { + _vocabulary->parserIsValid = false; // Invalidate parser + _vocabulary->parser_event = NULL_REG; // Invalidate parser event + _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); + } + + _gamestate->game_start_time = _gamestate->last_wait_time = g_system->getMillis(); + + srand(g_system->getMillis()); // Initialize random number generator + + _gamestate->_gameObj = _resMan->findGameObject(); + +#ifdef USE_OLD_MUSIC_FUNCTIONS + if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) + game_init_sound(_gamestate, 0, _features->detectDoSoundType()); +#endif + + // Load game language into printLang property of game object + // FIXME: It's evil to achieve this as a side effect of a getter. + // Much better to have an explicit init method for this. + getSciLanguage(); + + return true; +} + +void SciEngine::initStackBaseWithSelector(Selector selector) { + _gamestate->stack_base[0] = make_reg(0, (uint16)selector); + _gamestate->stack_base[1] = NULL_REG; + + // Register the first element on the execution stack + if (!send_selector(_gamestate, _gamestate->_gameObj, _gamestate->_gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) { + _console->printObject(_gamestate->_gameObj); + error("initStackBaseWithSelector: error while registering the first selector in the call stack"); + } + +} + +void SciEngine::runGame() { + initStackBaseWithSelector(_kernel->_selectorCache.play); // Call the play selector + + // Attach the debug console on game startup, if requested + if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) + _console->attach(); + + do { + _gamestate->_executionStackPosChanged = false; + run_vm(_gamestate, (_gamestate->abortScriptProcessing == kAbortLoadGame)); + exitGame(); + + if (_gamestate->abortScriptProcessing == kAbortRestartGame) { + _gamestate->_segMan->resetSegMan(); + initGame(); +#ifdef USE_OLD_MUSIC_FUNCTIONS + _gamestate->_sound.sfx_reset_player(); +#endif + initStackBaseWithSelector(_kernel->_selectorCache.play); + _gamestate->gameWasRestarted = true; + } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { + _gamestate->abortScriptProcessing = kAbortNone; + initStackBaseWithSelector(_kernel->_selectorCache.replay); + } else { + break; // exit loop + } + } while (true); +} + +void SciEngine::exitGame() { + if (_gamestate->abortScriptProcessing != kAbortLoadGame) { + _gamestate->_executionStack.clear(); +#ifdef USE_OLD_MUSIC_FUNCTIONS + _gamestate->_sound.sfx_exit(); + // Reinit because some other code depends on having a valid state + game_init_sound(_gamestate, SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType()); +#else + _audio->stopAllAudio(); + _gamestate->_soundCmd->clearPlayList(); +#endif + } + + // TODO Free parser segment here + + // TODO Free scripts here + + // Close all opened file handles + _gamestate->_fileHandles.clear(); + _gamestate->_fileHandles.resize(5); +} + // Invoked by error() when a severe error occurs GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 0902a41139..0bcff8a02e 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -28,6 +28,7 @@ #include "engines/engine.h" #include "common/util.h" +#include "engine/vm_types.h" // for Selector struct ADGameDescription; @@ -219,6 +220,46 @@ public: GameFeatures *_features; private: + /** + * Initializes a SCI game + * This function must be run before script_run() is executed. Graphics data + * is initialized iff s->gfx_state != NULL. + * @param[in] s The state to operate on + * @return true on success, false if an error occured. + */ + bool initGame(); + + /** + * Runs a SCI game + * This is the main function for SCI games. It takes a valid state, loads + * script 0 to it, finds the game object, allocates a stack, and runs the + * init method of the game object. In layman's terms, this runs a SCI game. + * @param[in] s Pointer to the pointer of the state to operate on + */ + void runGame(); + + /** + * Uninitializes an initialized SCI game + * This function should be run after each script_run() call. + * @param[in] s The state to operate on + */ + void exitGame(); + +#ifdef USE_OLD_MUSIC_FUNCTIONS + /** + * Initializes the sound part of a SCI game + * This function may only be called if game_init() did not initialize + * the sound data. + * @param[in] s The state to initialize the sound in + * @param[in] sound_flags Flags to pass to the sound subsystem + * @param[in] soundVersion sound-version that got detected during game init + * @return 0 on success, 1 if an error occured + */ + int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion); +#endif + + void initStackBaseWithSelector(Selector selector); + const ADGameDescription *_gameDescription; ResourceManager *_resMan; /**< The resource manager */ EngineState *_gamestate; -- cgit v1.2.3 From abc5f97608952d4d1f43c736ecd31f23d0aecb8c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 07:41:48 +0000 Subject: Fixed compilation with the old music code svn-id: r49560 --- engines/sci/sci.cpp | 21 +++++++++++++++------ engines/sci/sci.h | 3 +-- 2 files changed, 16 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 08236597b4..537ec4bef0 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -234,10 +234,7 @@ Common::Error SciEngine::run() { _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); #ifdef USE_OLD_MUSIC_FUNCTIONS - if (game_init_sound(_gamestate, 0, soundVersion)) { - warning("Game initialization failed: Error in sound subsystem. Aborting..."); - return Common::kUnknownError; - } + initGameSound(0, soundVersion); #endif syncSoundSettings(); @@ -334,7 +331,7 @@ bool SciEngine::initGame() { #ifdef USE_OLD_MUSIC_FUNCTIONS if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) - game_init_sound(_gamestate, 0, _features->detectDoSoundType()); + initGameSound(0, _features->detectDoSoundType()); #endif // Load game language into printLang property of game object @@ -345,6 +342,18 @@ bool SciEngine::initGame() { return true; } +#ifdef USE_OLD_MUSIC_FUNCTIONS + +void SciEngine::initGameSound(int sound_flags, SciVersion soundVersion) { + if (getSciVersion() > SCI_VERSION_0_LATE) + sound_flags |= SFX_STATE_FLAG_MULTIPLAY; + + _gamestate->sfx_init_flags = sound_flags; + _gamestate->_sound.sfx_init(_resMan, sound_flags, soundVersion); +} + +#endif + void SciEngine::initStackBaseWithSelector(Selector selector) { _gamestate->stack_base[0] = make_reg(0, (uint16)selector); _gamestate->stack_base[1] = NULL_REG; @@ -392,7 +401,7 @@ void SciEngine::exitGame() { #ifdef USE_OLD_MUSIC_FUNCTIONS _gamestate->_sound.sfx_exit(); // Reinit because some other code depends on having a valid state - game_init_sound(_gamestate, SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType()); + initGameSound(SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType()); #else _audio->stopAllAudio(); _gamestate->_soundCmd->clearPlayList(); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 0bcff8a02e..43e9c88da9 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -253,9 +253,8 @@ private: * @param[in] s The state to initialize the sound in * @param[in] sound_flags Flags to pass to the sound subsystem * @param[in] soundVersion sound-version that got detected during game init - * @return 0 on success, 1 if an error occured */ - int game_init_sound(EngineState *s, int sound_flags, SciVersion soundVersion); + void initGameSound(int sound_flags, SciVersion soundVersion); #endif void initStackBaseWithSelector(Selector selector); -- cgit v1.2.3 From 50c1f4e545dde784341eebf6eb8cd6d3ce0751b7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 07:48:32 +0000 Subject: Moved the MoveCountType enum above the GameFeatures class, as it's the only class using it svn-id: r49561 --- engines/sci/console.cpp | 2 +- engines/sci/engine/features.h | 6 ++++++ engines/sci/sci.h | 6 ------ 3 files changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9f1d03df25..7246bef586 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -434,7 +434,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) { DebugPrintf("Sound type: %s\n", getSciVersionDesc(_engine->_features->detectDoSoundType())); DebugPrintf("Graphics functions type: %s\n", getSciVersionDesc(_engine->_features->detectGfxFunctionsType())); DebugPrintf("Lofs type: %s\n", getSciVersionDesc(_engine->_features->detectLofsType())); - DebugPrintf("Move count type: %s\n", (_engine->_features->detectMoveCountType() == kIncrementMoveCount) ? "increment" : "ignore"); + DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); diff --git a/engines/sci/engine/features.h b/engines/sci/engine/features.h index 77c2f0cff7..5b383746d8 100644 --- a/engines/sci/engine/features.h +++ b/engines/sci/engine/features.h @@ -31,6 +31,12 @@ namespace Sci { +enum MoveCountType { + kMoveCountUninitialized, + kIgnoreMoveCount, + kIncrementMoveCount +}; + class GameFeatures { public: GameFeatures(SegManager *segMan, Kernel *kernel); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 43e9c88da9..4e6be667f1 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -118,12 +118,6 @@ enum SciVersion { SCI_VERSION_3 // LSL7, RAMA, Lighthouse }; -enum MoveCountType { - kMoveCountUninitialized, - kIgnoreMoveCount, - kIncrementMoveCount -}; - /** Supported languages */ enum kLanguage { K_LANG_NONE = 0, -- cgit v1.2.3 From 0ab7c908bb3971a74bb1c8848d6f59f161464ad1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 08:11:38 +0000 Subject: Removed the pointer to the game object from the EngineState class svn-id: r49562 --- engines/sci/engine/kparse.cpp | 4 ++-- engines/sci/engine/state.cpp | 8 +++----- engines/sci/engine/state.h | 2 -- engines/sci/sci.cpp | 7 +++---- engines/sci/sci.h | 2 ++ 5 files changed, 10 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index 785ff39d22..465bc177a0 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -118,7 +118,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, 1); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); - invokeSelector(INV_SEL(s, s->_gameObj, syntaxFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(INV_SEL(s, g_sci->getGameObject(), syntaxFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); /* Issue warning */ debugC(2, kDebugLevelParser, "Tree building failed"); @@ -141,7 +141,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, "Word unknown: %s", error); /* Issue warning: */ - invokeSelector(INV_SEL(s, s->_gameObj, wordFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(INV_SEL(s, g_sci->getGameObject(), wordFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); free(error); return make_reg(0, 1); /* Tell them that it didn't work */ } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 8860666bef..716f948ce6 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -85,8 +85,6 @@ void EngineState::reset(bool isRestoring) { #endif if (!isRestoring) { - _gameObj = NULL_REG; - _memorySegmentSize = 0; _soundCmd = 0; @@ -237,7 +235,7 @@ kLanguage SciEngine::getSciLanguage() { lang = K_LANG_ENGLISH; if (_kernel->_selectorCache.printLang != -1) { - lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang)); + lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang)); if ((getSciVersion() >= SCI_VERSION_1_1) || (lang == K_LANG_NONE)) { // If language is set to none, we use the language from the game detector. @@ -272,7 +270,7 @@ kLanguage SciEngine::getSciLanguage() { } // Store language in printLang selector - writeSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(printLang), lang); + writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); } } @@ -284,7 +282,7 @@ Common::String SciEngine::strSplit(const char *str, const char *sep) { kLanguage subLang = K_LANG_NONE; if (_kernel->_selectorCache.subtitleLang != -1) { - subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gamestate->_gameObj, SELECTOR(subtitleLang)); + subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(subtitleLang)); } kLanguage secondLang; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index aaeb8c49ee..32da83b162 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -173,8 +173,6 @@ public: */ void shrinkStackToBase(); - reg_t _gameObj; /**< Pointer to the game object */ - int gc_countdown; /**< Number of kernel calls until next gc */ public: diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 537ec4bef0..fad4e8c4e8 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -145,6 +145,7 @@ Common::Error SciEngine::run() { // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(getGameID()); + _gameObj = _resMan->findGameObject(); SegManager *segMan = new SegManager(_resMan); @@ -327,8 +328,6 @@ bool SciEngine::initGame() { srand(g_system->getMillis()); // Initialize random number generator - _gamestate->_gameObj = _resMan->findGameObject(); - #ifdef USE_OLD_MUSIC_FUNCTIONS if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) initGameSound(0, _features->detectDoSoundType()); @@ -359,8 +358,8 @@ void SciEngine::initStackBaseWithSelector(Selector selector) { _gamestate->stack_base[1] = NULL_REG; // Register the first element on the execution stack - if (!send_selector(_gamestate, _gamestate->_gameObj, _gamestate->_gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) { - _console->printObject(_gamestate->_gameObj); + if (!send_selector(_gamestate, _gameObj, _gameObj, _gamestate->stack_base, 2, _gamestate->stack_base)) { + _console->printObject(_gameObj); error("initStackBaseWithSelector: error while registering the first selector in the call stack"); } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 4e6be667f1..4096019a86 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -161,6 +161,7 @@ public: inline EngineState *getEngineState() const { return _gamestate; } inline Vocabulary *getVocabulary() const { return _vocabulary; } inline EventManager *getEventManager() const { return _eventMan; } + inline reg_t getGameObject() const { return _gameObj; } Common::String getSavegameName(int nr) const; Common::String getSavegamePattern() const; @@ -259,6 +260,7 @@ private: Kernel *_kernel; Vocabulary *_vocabulary; EventManager *_eventMan; + reg_t _gameObj; /**< Pointer to the game object */ Console *_console; OSystem *_system; }; -- cgit v1.2.3 From eb4ec596cdb8e541d5221263b3db185bd01b206f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 09:18:57 +0000 Subject: Use the SELECTOR() macro for readability svn-id: r49563 --- engines/sci/engine/features.cpp | 14 +++++++------- engines/sci/engine/kgraphics.cpp | 4 ++-- engines/sci/engine/state.cpp | 4 ++-- engines/sci/engine/vm.cpp | 5 +++-- engines/sci/graphics/animate.cpp | 4 ++-- engines/sci/graphics/compare.cpp | 8 ++++---- engines/sci/sci.cpp | 7 ++++--- engines/sci/sound/soundcmd.cpp | 2 +- 8 files changed, 25 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 48f7c2d64f..4eb6bf2a56 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -69,7 +69,7 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc bool GameFeatures::autoDetectSoundType() { // Look up the script address - reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play); + reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); if (!addr.segment) return false; @@ -138,7 +138,7 @@ SciVersion GameFeatures::detectDoSoundType() { if (getSciVersion() == SCI_VERSION_0_EARLY) { // This game is using early SCI0 sound code (different headers than SCI0 late) _doSoundType = SCI_VERSION_0_EARLY; - } else if (_kernel->_selectorCache.nodePtr == -1) { + } else if (SELECTOR(nodePtr) == -1) { // No nodePtr selector, so this game is definitely using newer // SCI0 sound code (i.e. SCI_VERSION_0_LATE) _doSoundType = SCI_VERSION_0_LATE; @@ -293,7 +293,7 @@ SciVersion GameFeatures::detectLofsType() { bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { // Look up the script address - reg_t addr = getDetectionAddr("Rm", _kernel->_selectorCache.overlay, methodNum); + reg_t addr = getDetectionAddr("Rm", SELECTOR(overlay), methodNum); if (!addr.segment) return false; @@ -343,10 +343,10 @@ SciVersion GameFeatures::detectGfxFunctionsType() { bool searchRoomObj = false; reg_t rmObjAddr = _segMan->findObjectByName("Rm"); - if (_kernel->_selectorCache.overlay != -1) { + if (SELECTOR(overlay) != -1) { // The game has an overlay selector, check how it calls kDrawPicto determine // the graphics functions type used - if (lookupSelector(_segMan, rmObjAddr, _kernel->_selectorCache.overlay, NULL, NULL) == kSelectorMethod) { + if (lookupSelector(_segMan, rmObjAddr, SELECTOR(overlay), NULL, NULL) == kSelectorMethod) { if (!autoDetectGfxFunctionsType()) { warning("Graphics functions detection failed, taking an educated guess"); @@ -396,7 +396,7 @@ SciVersion GameFeatures::detectGfxFunctionsType() { #ifdef ENABLE_SCI32 bool GameFeatures::autoDetectSci21KernelType() { // Look up the script address - reg_t addr = getDetectionAddr("Sound", _kernel->_selectorCache.play); + reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); if (!addr.segment) return false; @@ -448,7 +448,7 @@ SciVersion GameFeatures::detectSci21KernelType() { bool GameFeatures::autoDetectMoveCountType() { // Look up the script address - reg_t addr = getDetectionAddr("Motion", _kernel->_selectorCache.doit); + reg_t addr = getDetectionAddr("Motion", SELECTOR(doit)); if (!addr.segment) return false; diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index abe55455de..f025d03a09 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -821,12 +821,12 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(x)); // max chars per entry cursorOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor)); - if (g_sci->getKernel()->_selectorCache.topString != -1) { + if (SELECTOR(topString) != -1) { // Games from early SCI1 onwards use topString upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(topString)); } else { // Earlier games use lsTop or brTop - if (lookupSelector(s->_segMan, controlObject, g_sci->getKernel()->_selectorCache.brTop, NULL, NULL) == kSelectorVariable) + if (lookupSelector(s->_segMan, controlObject, SELECTOR(brTop), NULL, NULL) == kSelectorVariable) upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(brTop)); else upperOffset = readSelectorValue(s->_segMan, controlObject, SELECTOR(lsTop)); diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 716f948ce6..367a9b78b9 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -234,7 +234,7 @@ kLanguage SciEngine::getSciLanguage() { lang = K_LANG_ENGLISH; - if (_kernel->_selectorCache.printLang != -1) { + if (SELECTOR(printLang) != -1) { lang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang)); if ((getSciVersion() >= SCI_VERSION_1_1) || (lang == K_LANG_NONE)) { @@ -281,7 +281,7 @@ Common::String SciEngine::strSplit(const char *str, const char *sep) { kLanguage lang = getSciLanguage(); kLanguage subLang = K_LANG_NONE; - if (_kernel->_selectorCache.subtitleLang != -1) { + if (SELECTOR(subtitleLang) != -1) { subLang = (kLanguage)readSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(subtitleLang)); } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 2c92bdadc3..f99ae817bf 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -35,8 +35,9 @@ #include "sci/engine/features.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" -#include "sci/engine/seg_manager.h" #include "sci/engine/script.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/selector.h" // for SELECTOR #include "sci/engine/gc.h" namespace Sci { @@ -205,7 +206,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i if (!stopGroopPos.isNull()) { // does the game have a stopGroop object? // Find the "client" member variable of the stopGroop object, and update it ObjVarRef varp; - if (lookupSelector(segMan, stopGroopPos, kernel->_selectorCache.client, &varp, NULL) == kSelectorVariable) { + if (lookupSelector(segMan, stopGroopPos, SELECTOR(client), &varp, NULL) == kSelectorVariable) { reg_t *clientVar = varp.getPointer(segMan); *clientVar = value; } diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index d4def39ebf..48715af53e 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -93,7 +93,7 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if (!(signal & kSignalFrozen)) { // Call .doit method of that object - invokeSelector(_s, curObject, g_sci->getKernel()->_selectorCache.doit, kContinueOnInvalidSelector, argc, argv, 0); + invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0); // Lookup node again, since the nodetable it was in may have been reallocated curNode = _s->_segMan->lookupNode(curAddress); } @@ -497,7 +497,7 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { if (signal & kSignalDisposeMe) { // Call .delete_ method of that object - invokeSelector(_s, curObject, g_sci->getKernel()->_selectorCache.delete_, kContinueOnInvalidSelector, argc, argv, 0); + invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0); } listIterator--; } diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 3102edc2fa..47b4f22607 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -126,14 +126,14 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) { int16 x = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(x)); int16 y = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(y)); int16 z = 0; - if (_kernel->_selectorCache.z > -1) + if (SELECTOR(z) > -1) z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z)); // now get cel rectangle view = _cache->getView(viewId); view->getCelRect(loopNo, celNo, x, y, z, &celRect); - if (lookupSelector(_segMan, objectReference, _kernel->_selectorCache.nsTop, NULL, NULL) == kSelectorVariable) { + if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) { writeSelectorValue(_segMan, objectReference, SELECTOR(nsLeft), celRect.left); writeSelectorValue(_segMan, objectReference, SELECTOR(nsRight), celRect.right); writeSelectorValue(_segMan, objectReference, SELECTOR(nsTop), celRect.top); @@ -183,10 +183,10 @@ bool GfxCompare::kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, } void GfxCompare::kernelBaseSetter(reg_t object) { - if (lookupSelector(_segMan, object, _kernel->_selectorCache.brLeft, NULL, NULL) == kSelectorVariable) { + if (lookupSelector(_segMan, object, SELECTOR(brLeft), NULL, NULL) == kSelectorVariable) { int16 x = readSelectorValue(_segMan, object, SELECTOR(x)); int16 y = readSelectorValue(_segMan, object, SELECTOR(y)); - int16 z = (_kernel->_selectorCache.z > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; + int16 z = (SELECTOR(z) > -1) ? readSelectorValue(_segMan, object, SELECTOR(z)) : 0; int16 yStep = readSelectorValue(_segMan, object, SELECTOR(yStep)); GuiResourceId viewId = readSelectorValue(_segMan, object, SELECTOR(view)); int16 loopNo = readSelectorValue(_segMan, object, SELECTOR(loop)); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index fad4e8c4e8..3a3c147cb6 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -40,6 +40,7 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/script.h" // for script_adjust_opcode_formats +#include "sci/engine/selector.h" // for SELECTOR #include "sci/sound/audio.h" #include "sci/sound/soundcmd.h" @@ -366,7 +367,7 @@ void SciEngine::initStackBaseWithSelector(Selector selector) { } void SciEngine::runGame() { - initStackBaseWithSelector(_kernel->_selectorCache.play); // Call the play selector + initStackBaseWithSelector(SELECTOR(play)); // Call the play selector // Attach the debug console on game startup, if requested if (DebugMan.isDebugChannelEnabled(kDebugLevelOnStartup)) @@ -383,11 +384,11 @@ void SciEngine::runGame() { #ifdef USE_OLD_MUSIC_FUNCTIONS _gamestate->_sound.sfx_reset_player(); #endif - initStackBaseWithSelector(_kernel->_selectorCache.play); + initStackBaseWithSelector(SELECTOR(play)); _gamestate->gameWasRestarted = true; } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { _gamestate->abortScriptProcessing = kAbortNone; - initStackBaseWithSelector(_kernel->_selectorCache.replay); + initStackBaseWithSelector(SELECTOR(replay)); } else { break; // exit loop } diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 4711fe385d..2bbc5b44de 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -842,7 +842,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { // Update MIDI slots if (musicSlot->signal == 0) { if (musicSlot->dataInc != readSelectorValue(_segMan, obj, SELECTOR(dataInc))) { - if (_kernel->_selectorCache.dataInc > -1) + if (SELECTOR(dataInc) > -1) writeSelectorValue(_segMan, obj, SELECTOR(dataInc), musicSlot->dataInc); writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->dataInc + 127); } -- cgit v1.2.3 From cc6f5eb3e42bb4f7af47a70802a236fdbffc7b74 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 09:22:30 +0000 Subject: Unified invokeSelector() and invokeSelectorArgv(), and removed the INV_SEL kludge. Also, removed the selectorInvocation parameter - if invokeSelector() fails, the error is in most cases unrecoverable, and the error description thrown covers all cases where kContinueOnInvalidSelector was used. This uncovered a bug too: in some places, non reg_t parameters were parsed svn-id: r49564 --- engines/sci/engine/klists.cpp | 9 +++++---- engines/sci/engine/kmovement.cpp | 34 +++++++++++----------------------- engines/sci/engine/kparse.cpp | 6 +++--- engines/sci/engine/selector.cpp | 26 ++------------------------ engines/sci/engine/selector.h | 19 ++----------------- 5 files changed, 23 insertions(+), 71 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index f06f3eec77..18d6638e92 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -424,7 +424,8 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { i = 0; while (node) { - invokeSelector(INV_SEL(s, order_func, doit, kStopOnInvalidSelector), 1, node->value); + reg_t params[1] = { node->value }; + invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params); temp_array[i].key = node->key; temp_array[i].value = node->value; temp_array[i].order = s->r_acc; @@ -523,7 +524,7 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { writeSelector(s->_segMan, curObject, slc, argv[2]); } } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); } curNode = s->_segMan->lookupNode(nextNode); @@ -552,7 +553,7 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) { // Can this happen with variable selectors? warning("kListFirstTrue: Attempted to access a variable selector"); } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); // Check if the result is true if (!s->r_acc.isNull()) @@ -586,7 +587,7 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) { // Can this happen with variable selectors? warning("kListAllTrue: Attempted to access a variable selector"); } else { - invokeSelectorArgv(s, curObject, slc, kContinueOnInvalidSelector, argc, argv, argc - 2, argv + 2); + invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); // Check if the result isn't true if (s->r_acc.isNull()) diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index 499aeabcc6..e45e55373b 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -315,11 +315,11 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "New data: (x,y)=(%d,%d), di=%d", x, y, bdi); - if (g_sci->getKernel()->_selectorCache.cantBeHere != -1) { - invokeSelector(INV_SEL(s, client, cantBeHere, kStopOnInvalidSelector), 0); + if (SELECTOR(cantBeHere) != -1) { + invokeSelector(s, client, SELECTOR(cantBeHere), argc, argv); s->r_acc = make_reg(0, !s->r_acc.offset); } else { - invokeSelector(INV_SEL(s, client, canBeHere, kStopOnInvalidSelector), 0); + invokeSelector(s, client, SELECTOR(canBeHere), argc, argv); } if (!s->r_acc.offset) { // Contains the return value @@ -335,7 +335,7 @@ reg_t kDoBresen(EngineState *s, int argc, reg_t *argv) { if ((getSciVersion() >= SCI_VERSION_1_EGA)) if (completed) - invokeSelector(INV_SEL(s, mover, moveDone, kStopOnInvalidSelector), 0); + invokeSelector(s, mover, SELECTOR(moveDone), argc, argv); return make_reg(0, completed); } @@ -399,20 +399,13 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "Doing avoider %04x:%04x (dest=%d,%d)", PRINT_REG(avoider), destx, desty); - if (invokeSelector(INV_SEL(s, mover, doit, kContinueOnInvalidSelector) , 0)) { - error("Mover %04x:%04x of avoider %04x:%04x doesn't have a doit() funcselector", PRINT_REG(mover), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, mover, SELECTOR(doit), argc, argv); mover = readSelector(segMan, client, SELECTOR(mover)); if (!mover.segment) // Mover has been disposed? return s->r_acc; // Return gracefully. - if (invokeSelector(INV_SEL(s, client, isBlocked, kContinueOnInvalidSelector) , 0)) { - error("Client %04x:%04x of avoider %04x:%04x doesn't" - " have an isBlocked() funcselector", PRINT_REG(client), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, client, SELECTOR(isBlocked), argc, argv); dx = destx - readSelectorValue(segMan, client, SELECTOR(x)); dy = desty - readSelectorValue(segMan, client, SELECTOR(y)); @@ -439,11 +432,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelBresen, "Pos (%d,%d): Trying angle %d; delta=(%d,%d)", oldx, oldy, angle, move_x, move_y); - if (invokeSelector(INV_SEL(s, client, canBeHere, kContinueOnInvalidSelector) , 0)) { - error("Client %04x:%04x of avoider %04x:%04x doesn't" - " have a canBeHere() funcselector", PRINT_REG(client), PRINT_REG(avoider)); - return NULL_REG; - } + invokeSelector(s, client, SELECTOR(canBeHere), argc, argv); writeSelectorValue(segMan, client, SELECTOR(x), oldx); writeSelectorValue(segMan, client, SELECTOR(y), oldy); @@ -472,12 +461,11 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, angle); + reg_t params[2] = { make_reg(0, angle), client }; + if (looper.segment) { - if (invokeSelector(INV_SEL(s, looper, doit, kContinueOnInvalidSelector), 2, angle, client)) { - error("Looper %04x:%04x of avoider %04x:%04x doesn't" - " have a doit() funcselector", PRINT_REG(looper), PRINT_REG(avoider)); - } else - return s->r_acc; + invokeSelector(s, looper, SELECTOR(doit), 2, params); + return s->r_acc; } else { // No looper? Fall back to DirLoop _k_dirloop(client, (uint16)angle, s, argc, argv); diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index 465bc177a0..bb9a49c7e8 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -94,8 +94,8 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { ResultWordList words; reg_t event = argv[1]; Vocabulary *voc = g_sci->getVocabulary(); - voc->parser_event = event; + reg_t params[2] = { voc->parser_base, stringpos }; bool res = voc->tokenizeString(words, string.c_str(), &error); voc->parserIsValid = false; /* not valid */ @@ -118,7 +118,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, 1); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); - invokeSelector(INV_SEL(s, g_sci->getGameObject(), syntaxFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), 2, params); /* Issue warning */ debugC(2, kDebugLevelParser, "Tree building failed"); @@ -141,7 +141,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, "Word unknown: %s", error); /* Issue warning: */ - invokeSelector(INV_SEL(s, g_sci->getGameObject(), wordFail, kStopOnInvalidSelector), 2, voc->parser_base, stringpos); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), 2, params); free(error); return make_reg(0, 1); /* Tell them that it didn't work */ } diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 04a1b8fbba..eafed029c5 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -200,7 +200,7 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t *address.getPointer(segMan) = value; } -int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, +void invokeSelector(EngineState *s, reg_t object, int selectorId, int k_argc, StackPtr k_argp, int argc, const reg_t *argv) { int i; int framesize = 2 + 1 * argc; @@ -214,16 +214,12 @@ int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInv slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, &address); if (slc_type == kSelectorNone) { - warning("Selector '%s' of object at %04x:%04x could not be invoked", + error("Selector '%s' of object at %04x:%04x could not be invoked", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); - if (noinvalid == kStopOnInvalidSelector) - error("[Kernel] Not recoverable: VM was halted"); - return 1; } if (slc_type == kSelectorVariable) { warning("Attempting to invoke variable selector %s of object %04x:%04x", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); - return 0; } for (i = 0; i < argc; i++) @@ -238,24 +234,6 @@ int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInv xstack->fp += argc + 2; run_vm(s, false); // Start a new vm - - return 0; -} - -int invokeSelector(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, ...) { - va_list argp; - reg_t *args = new reg_t[argc]; - - va_start(argp, argc); - for (int i = 0; i < argc; i++) - args[i] = va_arg(argp, reg_t); - va_end(argp); - - int retval = invokeSelectorArgv(s, object, selectorId, noinvalid, k_argc, k_argp, argc, args); - - delete[] args; - return retval; } SelectorType lookupSelector(SegManager *segMan, reg_t obj_location, Selector selectorId, ObjVarRef *varp, reg_t *fptr) { diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index f50b9ab1b3..851ff6bc81 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -34,11 +34,6 @@ namespace Sci { -enum SelectorInvocation { - kStopOnInvalidSelector = 0, - kContinueOnInvalidSelector = 1 -}; - /** * Map a selector name to a selector id. Shortcut for accessing the selector cache. */ @@ -71,18 +66,8 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t /** * Invokes a selector from an object. */ -int invokeSelector(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, ...); -int invokeSelectorArgv(EngineState *s, reg_t object, int selectorId, SelectorInvocation noinvalid, - int k_argc, StackPtr k_argp, int argc, const reg_t *argv); - -/** - * Kludge for use with invokeSelector(). Used for compatibility with compilers - * that cannot handle vararg macros. - */ -#define INV_SEL(s, _object_, _selector_, _noinvalid_) \ - s, _object_, g_sci->getKernel()->_selectorCache._selector_, _noinvalid_, argc, argv - +void invokeSelector(EngineState *s, reg_t object, int selectorId, + int k_argc, StackPtr k_argp, int argc = 0, const reg_t *argv = 0); } // End of namespace Sci -- cgit v1.2.3 From 8a5762c52db029386135ed7dd83f69fe5d34509c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 10 Jun 2010 10:15:32 +0000 Subject: SCI: set picport when loading saved games svn-id: r49565 --- engines/sci/engine/savegame.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 224115f95f..0376486667 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -369,6 +369,10 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint16LE(picPortRect.right); s.syncAsSint16LE(picPortTop); s.syncAsSint16LE(picPortLeft); + + if (s.isLoading()) { + g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false); + } } s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not -- cgit v1.2.3 From 4d8734284701153f10e9a2691d9b3cf5fd51e069 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 10 Jun 2010 10:20:25 +0000 Subject: Added extra code and support methods for properly clearing up backgrounds and used sprites when an animation sequence ends svn-id: r49566 --- engines/m4/graphics.cpp | 45 +++++++++++++++++++++++++++++++-------------- engines/m4/graphics.h | 1 + engines/m4/mads_anim.cpp | 5 +++++ engines/m4/mads_views.cpp | 8 +++++++- engines/m4/mads_views.h | 1 + 5 files changed, 45 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 8624f18da1..f332c8b06c 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -331,6 +331,16 @@ void M4Surface::clear() { Common::set_to((byte *)pixels, (byte *)pixels + w * h, _vm->_palette->BLACK); } +void M4Surface::reset() { + ::free(pixels); + pixels = NULL; + if (_rgbList) { + _vm->_palette->deleteRange(_rgbList); + delete _rgbList; + _rgbList = NULL; + } +} + void M4Surface::frameRect(const Common::Rect &r, uint8 color) { Graphics::Surface::frameRect(r, color); } @@ -412,6 +422,11 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf if (!copyRect.isValidRect()) return; + if (scale != 100) { + destX -= (src->width() * scale / 100) / 2; + destY -= (src->height() * scale / 100); + } + // Copy the specified area byte *data = src->getBasePtr(); @@ -435,27 +450,31 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf } } else { // Scaled variation - for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { - int currX = -1; + int currY = -1; + + for (int rowCtr = 0, yTotal = 0; rowCtr < copyRect.height(); ++rowCtr, yTotal += scale, + srcPtr += src->width(), depthsPtr += depthsSurface->width()) { + int srcY = yTotal / 100; + if (srcY == currY) + continue; + currY = srcY; // Loop through the source pixels - for (int xCtr = 0, xTotal = 0; xCtr < copyRect.width(); ++xCtr, xTotal += (100 - scale)) { + int currX = -1; + byte *destP = destPtr; + for (int xCtr = 0, xTotal = 0; xCtr < copyRect.width(); ++xCtr, xTotal += scale) { int srcX = xTotal / 100; + if (srcX == currX) + continue; + currX = srcX; - if (srcX != currX) { - currX = srcX; - - if ((depthsPtr[currX] > depth) && (srcPtr[xCtr] != transparentColour)) - destPtr[currX] = srcPtr[xCtr]; - } + if ((depthsPtr[currX] > depth) && (srcPtr[xCtr] != transparentColour)) + *destP++ = srcPtr[xCtr]; } - srcPtr += src->width(); - depthsPtr += depthsSurface->width(); destPtr += width(); } } - src->freeData(); depthsSurface->freeData(); } @@ -471,8 +490,6 @@ void M4Surface::loadBackgroundRiddle(const char *sceneName) { } void M4Surface::loadBackground(int sceneNumber, RGBList **palData) { - clear(); // clear previous scene - if (_vm->isM4() || (_vm->getGameType() == GType_RexNebular)) { char resourceName[20]; Common::SeekableReadStream *stream; diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 8c4b9ac072..6901b72e87 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -154,6 +154,7 @@ public: } void freeData(); void clear(); + void reset(); void frameRect(const Common::Rect &r, uint8 color); void fillRect(const Common::Rect &r, uint8 color); void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index e1dbbaf106..eac6d1b4aa 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -524,6 +524,11 @@ void AnimviewView::updateState() { delete _activeAnimation; _activeAnimation = NULL; + // Clear up current background and sprites + _backgroundSurface.reset(); + clearLists(); + + // Check if script is finished if (_script->eos() || _script->err()) { scriptDone(); return; diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index c7b4f76a00..98b04e9f2d 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -192,7 +192,7 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { assert(slot.spriteListIndex < (int)_sprites.size()); SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex]; - if (slot.scale < 100) { + if ((slot.scale < 100) && (slot.scale != -1)) { // Minimalised drawing assert(slot.spriteListIndex < (int)_sprites.size()); M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); @@ -1222,4 +1222,10 @@ void MadsView::refresh() { _textDisplay.cleanUp(); } +void MadsView::clearLists() { + _textDisplay.clear(); + _kernelMessages.clear(); + _spriteSlots.clear(); +} + } // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 29adb7048a..85bfe9e552 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -404,6 +404,7 @@ public: ~MadsView(); void refresh(); + void clearLists(); }; } -- cgit v1.2.3 From a635b948239fbbd1ce302fb9d5eac943e90ca7ee Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 10:27:13 +0000 Subject: Pic port saving/loading is only used in SCI0-SCI11 svn-id: r49567 --- engines/sci/engine/savegame.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 0376486667..99191146e5 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -352,16 +352,14 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_foreground s.skip(4, VER(12), VER(12)); // obsolete: used to be status_bar_background - if (s.getVersion() >= 13 && g_sci->_gui) { - // Save/Load picPort as well (cause sierra sci also does this) + if (s.getVersion() >= 13 && getSciVersion() <= SCI_VERSION_1_1) { + // Save/Load picPort as well for SCI0-SCI1.1. Necessary for Castle of Dr. Brain, + // as the picPort has been changed when loading during the intro int16 picPortTop, picPortLeft; Common::Rect picPortRect; - if (s.isSaving()) { - // FIXME: _gfxPorts is 0 when using SCI32 code - assert(g_sci->_gfxPorts); + if (s.isSaving()) picPortRect = g_sci->_gfxPorts->kernelGetPicWindow(picPortTop, picPortLeft); - } s.syncAsSint16LE(picPortRect.top); s.syncAsSint16LE(picPortRect.left); @@ -370,9 +368,8 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint16LE(picPortTop); s.syncAsSint16LE(picPortLeft); - if (s.isLoading()) { + if (s.isLoading()) g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false); - } } s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not -- cgit v1.2.3 From 93f33c7dab009e8ff82fac195e7b6d02e66ab755 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 11:18:10 +0000 Subject: Resolved a FIXME with getSciLanguage(), by creating a separate setter. Also, some camelCase changes svn-id: r49568 --- engines/sci/console.cpp | 6 +++--- engines/sci/detection.cpp | 4 ++-- engines/sci/engine/ksound.cpp | 5 ++++- engines/sci/engine/savegame.cpp | 4 ++-- engines/sci/engine/scriptdebug.cpp | 4 ++-- engines/sci/engine/state.cpp | 25 +++++++++++++++---------- engines/sci/engine/state.h | 10 +++++----- engines/sci/engine/vm.cpp | 12 ++++++------ engines/sci/sci.cpp | 8 +++----- engines/sci/sci.h | 2 ++ 10 files changed, 44 insertions(+), 36 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7246bef586..098d83a2d3 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -75,7 +75,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { // Variables DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); - DVar_Register("gc_interval", &engine->_gamestate->script_gc_interval, DVAR_INT, 0); + DVar_Register("gc_interval", &engine->_gamestate->scriptGCInterval, DVAR_INT, 0); DVar_Register("simulated_key", &g_debug_simulated_key, DVAR_INT, 0); DVar_Register("track_mouse_clicks", &g_debug_track_mouse_clicks, DVAR_BOOL, 0); DVar_Register("script_abort_flag", &_engine->_gamestate->abortScriptProcessing, DVAR_INT, 0); @@ -2086,7 +2086,7 @@ bool Console::cmdViewAccumulatorObject(int argc, const char **argv) { } bool Console::cmdScriptSteps(int argc, const char **argv) { - DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->script_step_counter); + DebugPrintf("Number of executed SCI operations: %d\n", _engine->_gamestate->scriptStepCounter); return true; } @@ -2114,7 +2114,7 @@ bool Console::cmdSetAccumulator(int argc, const char **argv) { bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); - DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->execution_stack_base); + DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List::iterator iter; uint i = 0; diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index f36bae2d6d..579414b3ea 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -673,11 +673,11 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) { } bool SciEngine::canLoadGameStateCurrently() { - return !_gamestate->execution_stack_base; + return !_gamestate->executionStackBase; } bool SciEngine::canSaveGameStateCurrently() { - return !_gamestate->execution_stack_base; + return !_gamestate->executionStackBase; } } // End of namespace Sci diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 367a89005c..29302181b1 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -151,7 +151,10 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { if (language != -1) g_sci->getResMan()->setAudioLanguage(language); - return make_reg(0, g_sci->getSciLanguage()); + kLanguage kLang = g_sci->getSciLanguage(); + g_sci->setSciLanguage(kLang); + + return make_reg(0, kLang); } break; case kSciAudioCD: diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 99191146e5..3cd444d4d7 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -722,7 +722,7 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); - if (s->execution_stack_base) { + if (s->executionStackBase) { warning("Cannot save from below kernel function"); return 1; } @@ -875,7 +875,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->gc_countdown = GC_INTERVAL - 1; // Time state: - s->last_wait_time = g_system->getMillis(); + s->lastWaitTime = g_system->getMillis(); s->game_start_time = g_system->getMillis(); #ifdef USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 159c278e8c..436eaafec5 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -284,7 +284,7 @@ void script_debug(EngineState *s) { #if 0 if (sci_debug_flags & _DEBUG_FLAG_LOGGING) { - printf("%d: acc=%04x:%04x ", script_step_counter, PRINT_REG(s->r_acc)); + printf("%d: acc=%04x:%04x ", scriptStepCounter, PRINT_REG(s->r_acc)); disassemble(s, s->xs->addr.pc, 0, 1); if (s->seeking == kDebugSeekGlobal) printf("Global %d (0x%x) = %04x:%04x\n", s->seekSpecial, @@ -351,7 +351,7 @@ void script_debug(EngineState *s) { } } - printf("Step #%d\n", s->script_step_counter); + printf("Step #%d\n", s->scriptStepCounter); disassemble(s, s->xs->addr.pc, 0, 1); if (g_debugState.runningStep) { diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 367a9b78b9..8e4a5200c8 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -95,7 +95,7 @@ void EngineState::reset(bool isRestoring) { abortScriptProcessing = kAbortNone; } - execution_stack_base = 0; + executionStackBase = 0; _executionStackPosChanged = false; restAdjust = 0; @@ -103,7 +103,7 @@ void EngineState::reset(bool isRestoring) { r_acc = NULL_REG; r_prev = NULL_REG; - last_wait_time = 0; + lastWaitTime = 0; gc_countdown = 0; @@ -111,14 +111,14 @@ void EngineState::reset(bool isRestoring) { _throttleLastTime = 0; _throttleTrigger = false; - script_step_counter = 0; - script_gc_interval = GC_INTERVAL; + scriptStepCounter = 0; + scriptGCInterval = GC_INTERVAL; } void EngineState::wait(int16 ticks) { uint32 time = g_system->getMillis(); - r_acc = make_reg(0, ((long)time - (long)last_wait_time) * 60 / 1000); - last_wait_time = time; + r_acc = make_reg(0, ((long)time - (long)lastWaitTime) * 60 / 1000); + lastWaitTime = time; ticks *= g_debug_sleeptime_factor; g_sci->getEventManager()->sleep(ticks * 1000 / 60); @@ -144,7 +144,7 @@ void EngineState::setRoomNumber(uint16 roomNumber) { } void EngineState::shrinkStackToBase() { - uint size = execution_stack_base + 1; + uint size = executionStackBase + 1; assert(_executionStack.size() >= size); Common::List::iterator iter = _executionStack.begin(); for (uint i = 0; i < size; ++i) @@ -268,15 +268,20 @@ kLanguage SciEngine::getSciLanguage() { default: lang = K_LANG_ENGLISH; } - - // Store language in printLang selector - writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); } } return lang; } +void SciEngine::setSciLanguage(kLanguage lang) { + writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); +} + +void SciEngine::setSciLanguage() { + setSciLanguage(getSciLanguage()); +} + Common::String SciEngine::strSplit(const char *str, const char *sep) { kLanguage lang = getSciLanguage(); kLanguage subLang = K_LANG_NONE; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 32da83b162..fd2380667b 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -112,7 +112,7 @@ public: SoundCommandParser *_soundCmd; uint32 game_start_time; /**< The time at which the interpreter was started */ - uint32 last_wait_time; /**< The last time the game invoked Wait() */ + uint32 lastWaitTime; /**< The last time the game invoked Wait() */ void wait(int16 ticks); @@ -134,7 +134,7 @@ public: * When called from kernel functions, the vm is re-started recursively on * the same stack. This variable contains the stack base for the current vm. */ - int execution_stack_base; + int executionStackBase; bool _executionStackPosChanged; /**< Set to true if the execution stack position should be re-evaluated by the vm */ reg_t r_acc; /**< Accumulator */ @@ -156,8 +156,8 @@ public: AbortGameState abortScriptProcessing; bool gameWasRestarted; - int script_step_counter; // Counts the number of steps executed - int script_gc_interval; // Number of steps in between gcs + int scriptStepCounter; // Counts the number of steps executed + int scriptGCInterval; // Number of steps in between gcs uint16 currentRoomNumber() const; void setRoomNumber(uint16 roomNumber); @@ -169,7 +169,7 @@ public: /** * Shrink execution stack to size. - * Contains an assert it is not already smaller. + * Contains an assert if it is not already smaller. */ void shrinkStackToBase(); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f99ae817bf..a203352dcd 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -631,7 +631,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { static void gc_countdown(EngineState *s) { if (s->gc_countdown-- <= 0) { - s->gc_countdown = s->script_gc_interval; + s->gc_countdown = s->scriptGCInterval; run_gc(s); } } @@ -726,7 +726,7 @@ void run_vm(EngineState *s, bool restoring) { ExecStack *xs_new = NULL; Object *obj = s->_segMan->getObject(s->xs->objp); Script *local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); - int old_execution_stack_base = s->execution_stack_base; + int old_executionStackBase = s->executionStackBase; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) @@ -735,7 +735,7 @@ void run_vm(EngineState *s, bool restoring) { } if (!restoring) - s->execution_stack_base = s->_executionStack.size() - 1; + s->executionStackBase = s->_executionStack.size() - 1; s->variables_seg[VAR_TEMP] = s->variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); s->variables_base[VAR_TEMP] = s->variables_base[VAR_PARAM] = s->stack_base; @@ -1179,8 +1179,8 @@ void run_vm(EngineState *s, bool restoring) { StackPtr old_fp = s->xs->fp; ExecStack *old_xs = &(s->_executionStack.back()); - if ((int)s->_executionStack.size() - 1 == s->execution_stack_base) { // Have we reached the base? - s->execution_stack_base = old_execution_stack_base; // Restore stack base + if ((int)s->_executionStack.size() - 1 == s->executionStackBase) { // Have we reached the base? + s->executionStackBase = old_executionStackBase; // Restore stack base s->_executionStack.pop_back(); @@ -1661,7 +1661,7 @@ void run_vm(EngineState *s, bool restoring) { opcode); } //#endif - ++s->script_step_counter; + ++s->scriptStepCounter; } } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 3a3c147cb6..2b3194830d 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -304,7 +304,7 @@ bool SciEngine::initGame() { _gamestate->r_acc = _gamestate->r_prev = NULL_REG; _gamestate->_executionStack.clear(); // Start without any execution stack - _gamestate->execution_stack_base = -1; // No vm is running yet + _gamestate->executionStackBase = -1; // No vm is running yet _gamestate->_executionStackPosChanged = false; _gamestate->abortScriptProcessing = kAbortNone; @@ -325,7 +325,7 @@ bool SciEngine::initGame() { _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); } - _gamestate->game_start_time = _gamestate->last_wait_time = g_system->getMillis(); + _gamestate->game_start_time = _gamestate->lastWaitTime = g_system->getMillis(); srand(g_system->getMillis()); // Initialize random number generator @@ -335,9 +335,7 @@ bool SciEngine::initGame() { #endif // Load game language into printLang property of game object - // FIXME: It's evil to achieve this as a side effect of a getter. - // Much better to have an explicit init method for this. - getSciLanguage(); + setSciLanguage(); return true; } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 4096019a86..eb2b82fdce 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -187,6 +187,8 @@ public: Common::String strSplit(const char *str, const char *sep = "\r----------\r"); kLanguage getSciLanguage(); + void setSciLanguage(kLanguage lang); + void setSciLanguage(); Common::String getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2 = NULL) const; -- cgit v1.2.3 From 944b511633e793f149e787b3f9cd1502b14d9993 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 11:35:15 +0000 Subject: Fixed regression from commit #49564 svn-id: r49569 --- engines/sci/engine/kmovement.cpp | 2 +- engines/sci/engine/kparse.cpp | 4 ++-- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index e45e55373b..c30a6e885a 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -464,7 +464,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { reg_t params[2] = { make_reg(0, angle), client }; if (looper.segment) { - invokeSelector(s, looper, SELECTOR(doit), 2, params); + invokeSelector(s, looper, SELECTOR(doit), argc, argv, 2, params); return s->r_acc; } else { // No looper? Fall back to DirLoop diff --git a/engines/sci/engine/kparse.cpp b/engines/sci/engine/kparse.cpp index bb9a49c7e8..45493a95d2 100644 --- a/engines/sci/engine/kparse.cpp +++ b/engines/sci/engine/kparse.cpp @@ -118,7 +118,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { s->r_acc = make_reg(0, 1); writeSelectorValue(segMan, event, SELECTOR(claimed), 1); - invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), 2, params); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(syntaxFail), argc, argv, 2, params); /* Issue warning */ debugC(2, kDebugLevelParser, "Tree building failed"); @@ -141,7 +141,7 @@ reg_t kParse(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelParser, "Word unknown: %s", error); /* Issue warning: */ - invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), 2, params); + invokeSelector(s, g_sci->getGameObject(), SELECTOR(wordFail), argc, argv, 2, params); free(error); return make_reg(0, 1); /* Tell them that it didn't work */ } -- cgit v1.2.3 From 711f679b7ffa9b51c2d6a07dab0a1dd7799f155d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 11:43:20 +0000 Subject: camelCase changes svn-id: r49570 --- engines/sci/console.cpp | 10 +++++----- engines/sci/engine/kmisc.cpp | 2 +- engines/sci/engine/savegame.cpp | 4 ++-- engines/sci/engine/state.cpp | 8 ++++---- engines/sci/engine/state.h | 10 +++++----- engines/sci/engine/vm.cpp | 40 ++++++++++++++++++++-------------------- engines/sci/sci.cpp | 4 ++-- 7 files changed, 39 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 098d83a2d3..3f123fa41b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1771,9 +1771,9 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { DebugPrintf("Addresses of variables in the VM:\n"); for (int i = 0; i < 4; i++) { - DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variables_seg[i], s->variables[i] - s->variables_base[i]))); - if (s->variables_max) - DebugPrintf(" total %d", s->variables_max[i]); + DebugPrintf("%s vars at %04x:%04x ", varnames[i], PRINT_REG(make_reg(s->variablesSegment[i], s->variables[i] - s->variablesBase[i]))); + if (s->variablesMax) + DebugPrintf(" total %d", s->variablesMax[i]); DebugPrintf("\n"); } @@ -1830,8 +1830,8 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } - if ((s->variables_max) && (s->variables_max[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", s->variables_max[vartype], s->variables_max[vartype]); + if ((s->variablesMax) && (s->variablesMax[vartype] <= idx)) { + DebugPrintf("Max. index is %d (0x%x)\n", s->variablesMax[vartype], s->variablesMax[vartype]); return true; } diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 25fb11d62f..f3d4c8a732 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -188,7 +188,7 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) { int retval = 0; // Avoid spurious warning g_system->getTimeAndDate(loc_time); - elapsedTime = g_system->getMillis() - s->game_start_time; + elapsedTime = g_system->getMillis() - s->gameStartTime; int mode = (argc > 0) ? argv[0].toUint16() : 0; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 3cd444d4d7..9c2ff76088 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -872,11 +872,11 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->_segMan->reconstructScripts(s); s->_segMan->reconstructClones(); s->initGlobals(); - s->gc_countdown = GC_INTERVAL - 1; + s->gcCountDown = GC_INTERVAL - 1; // Time state: s->lastWaitTime = g_system->getMillis(); - s->game_start_time = g_system->getMillis(); + s->gameStartTime = g_system->getMillis(); #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound._it = NULL; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 8e4a5200c8..68e7eea4a0 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -105,7 +105,7 @@ void EngineState::reset(bool isRestoring) { lastWaitTime = 0; - gc_countdown = 0; + gcCountDown = 0; _throttleCounter = 0; _throttleLastTime = 0; @@ -130,9 +130,9 @@ void EngineState::initGlobals() { if (!script_000->_localsBlock) error("Script 0 has no locals block"); - variables_seg[VAR_GLOBAL] = script_000->_localsSegment; - variables_base[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->_localsBlock->_locals.begin(); - variables_max[VAR_GLOBAL] = script_000->_localsBlock->_locals.size(); + variablesSegment[VAR_GLOBAL] = script_000->_localsSegment; + variablesBase[VAR_GLOBAL] = variables[VAR_GLOBAL] = script_000->_localsBlock->_locals.begin(); + variablesMax[VAR_GLOBAL] = script_000->_localsBlock->_locals.size(); } uint16 EngineState::currentRoomNumber() const { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index fd2380667b..1b1a1fa86c 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -111,7 +111,7 @@ public: #endif SoundCommandParser *_soundCmd; - uint32 game_start_time; /**< The time at which the interpreter was started */ + uint32 gameStartTime; /**< The time at which the interpreter was started */ uint32 lastWaitTime; /**< The last time the game invoked Wait() */ void wait(int16 ticks); @@ -147,9 +147,9 @@ public: // Script state ExecStack *xs; reg_t *variables[4]; ///< global, local, temp, param, as immediate pointers - reg_t *variables_base[4]; ///< Used for referencing VM ops - SegmentId variables_seg[4]; ///< Same as above, contains segment IDs - int variables_max[4]; ///< Max. values for all variables + reg_t *variablesBase[4]; ///< Used for referencing VM ops + SegmentId variablesSegment[4]; ///< Same as above, contains segment IDs + int variablesMax[4]; ///< Max. values for all variables int loadFromLauncher; @@ -173,7 +173,7 @@ public: */ void shrinkStackToBase(); - int gc_countdown; /**< Number of kernel calls until next gc */ + int gcCountDown; /**< Number of kernel calls until next gc */ public: MessageState *_msgState; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a203352dcd..1db9649a54 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -230,8 +230,8 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #endif -#define READ_VAR(type, index, def) validate_read_var(s->variables[type], s->stack_base, type, s->variables_max[type], index, __LINE__, def) -#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variables_max[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) +#define READ_VAR(type, index, def) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, def) +#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) @@ -629,9 +629,9 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { } } -static void gc_countdown(EngineState *s) { - if (s->gc_countdown-- <= 0) { - s->gc_countdown = s->scriptGCInterval; +static void gcCountDown(EngineState *s) { + if (s->gcCountDown-- <= 0) { + s->gcCountDown = s->scriptGCInterval; run_gc(s); } } @@ -737,8 +737,8 @@ void run_vm(EngineState *s, bool restoring) { if (!restoring) s->executionStackBase = s->_executionStack.size() - 1; - s->variables_seg[VAR_TEMP] = s->variables_seg[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); - s->variables_base[VAR_TEMP] = s->variables_base[VAR_PARAM] = s->stack_base; + s->variablesSegment[VAR_TEMP] = s->variablesSegment[VAR_PARAM] = s->_segMan->findSegmentByType(SEG_TYPE_STACK); + s->variablesBase[VAR_TEMP] = s->variablesBase[VAR_PARAM] = s->stack_base; s->_executionStackPosChanged = true; // Force initialization @@ -776,24 +776,24 @@ void run_vm(EngineState *s, bool restoring) { if (!local_script) { warning("Could not find local script from segment %x", s->xs->local_segment); local_script = NULL; - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS - s->variables_max[VAR_LOCAL] = 0; + s->variablesMax[VAR_LOCAL] = 0; #endif } else { - s->variables_seg[VAR_LOCAL] = local_script->_localsSegment; + s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; if (local_script->_localsBlock) - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); else - s->variables_base[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; #ifndef DISABLE_VALIDATIONS if (local_script->_localsBlock) - s->variables_max[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); + s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); else - s->variables_max[VAR_LOCAL] = 0; - s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp; - s->variables_max[VAR_PARAM] = s->xs->argc + 1; + s->variablesMax[VAR_LOCAL] = 0; + s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; + s->variablesMax[VAR_PARAM] = s->xs->argc + 1; #endif } s->variables[VAR_TEMP] = s->xs->fp; @@ -821,7 +821,7 @@ void run_vm(EngineState *s, bool restoring) { error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp)); - s->variables_max[VAR_TEMP] = s->xs->sp - s->xs->fp; + s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; if (s->xs->addr.pc.offset >= code_buf_size) error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", @@ -1120,7 +1120,7 @@ void run_vm(EngineState *s, bool restoring) { } case op_callk: { // 0x21 (33) - gc_countdown(s); + gcCountDown(s); s->xs->sp -= (opparams[1] >> 1) + 1; @@ -1295,8 +1295,8 @@ void run_vm(EngineState *s, bool restoring) { var_number = temp & 0x03; // Get variable type // Get variable block offset - r_temp.segment = s->variables_seg[var_number]; - r_temp.offset = s->variables[var_number] - s->variables_base[var_number]; + r_temp.segment = s->variablesSegment[var_number]; + r_temp.offset = s->variables[var_number] - s->variablesBase[var_number]; if (temp & 0x08) // Add accumulator offset if requested r_temp.offset += signed_validate_arithmetic(s->r_acc); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 2b3194830d..9e928b82d9 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -286,7 +286,7 @@ bool SciEngine::initGame() { DataStack *stack = _gamestate->_segMan->allocateStack(VM_STACK_SIZE, NULL); _gamestate->_msgState = new MessageState(_gamestate->_segMan); - _gamestate->gc_countdown = GC_INTERVAL - 1; + _gamestate->gcCountDown = GC_INTERVAL - 1; // Script 0 should always be at segment 1 if (script0Segment != 1) { @@ -325,7 +325,7 @@ bool SciEngine::initGame() { _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); } - _gamestate->game_start_time = _gamestate->lastWaitTime = g_system->getMillis(); + _gamestate->gameStartTime = _gamestate->lastWaitTime = g_system->getMillis(); srand(g_system->getMillis()); // Initialize random number generator -- cgit v1.2.3 From afa2af5dfb0214c4aeeb2f21ef43dca5e3886181 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 13:43:38 +0000 Subject: SCI: cleanup svn-id: r49573 --- engines/sci/console.cpp | 2 +- engines/sci/engine/kernel.h | 1 - engines/sci/engine/selector.cpp | 3 +-- 3 files changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 3f123fa41b..c2ea377f9b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2370,7 +2370,7 @@ bool Console::cmdSend(int argc, const char **argv) { return true; } - SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, 0, 0); + SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL); if (selector_type == kSelectorNone) { DebugPrintf("Object does not support selector: \"%s\"\n", selector_name); diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 990e2aff17..c5513f1240 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -258,7 +258,6 @@ private: ResourceManager *_resMan; SegManager *_segMan; - uint32 features; // Kernel-related lists Common::StringArray _selectorNames; diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index eafed029c5..15b008430b 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -204,14 +204,13 @@ void invokeSelector(EngineState *s, reg_t object, int selectorId, int k_argc, StackPtr k_argp, int argc, const reg_t *argv) { int i; int framesize = 2 + 1 * argc; - reg_t address; int slc_type; StackPtr stackframe = k_argp + k_argc; stackframe[0] = make_reg(0, selectorId); // The selector we want to call stackframe[1] = make_reg(0, argc); // Argument count - slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, &address); + slc_type = lookupSelector(s->_segMan, object, selectorId, NULL, NULL); if (slc_type == kSelectorNone) { error("Selector '%s' of object at %04x:%04x could not be invoked", -- cgit v1.2.3 From 5330e632de917d603a6d246d53f4ed4e5bdf51ec Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 14:02:20 +0000 Subject: Don't attempt to modify the printLang selector if it doesn't exist svn-id: r49575 --- engines/sci/engine/state.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 68e7eea4a0..41f263bb62 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -275,7 +275,8 @@ kLanguage SciEngine::getSciLanguage() { } void SciEngine::setSciLanguage(kLanguage lang) { - writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); + if (SELECTOR(printLang) != -1) + writeSelectorValue(_gamestate->_segMan, _gameObj, SELECTOR(printLang), lang); } void SciEngine::setSciLanguage() { -- cgit v1.2.3 From 6ad04a4a96b0290125e33535f84a98e4d79dff2c Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 10 Jun 2010 15:06:25 +0000 Subject: Add support for AIFF sound in SCI32 Mac games and add support for AIFF/WAVE audio36 patches; minor cleanup. svn-id: r49576 --- engines/sci/resource.cpp | 72 +++++++++++++++++++++++------------------- engines/sci/resource.h | 3 +- engines/sci/resource_audio.cpp | 63 ++++++++++++++++++------------------ engines/sci/sound/audio.cpp | 24 +++++++++++--- 4 files changed, 90 insertions(+), 72 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 307b4e888e..0b7badb8f7 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -481,6 +481,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("Robot Folder"); addPatchDir("Sound Folder"); addPatchDir("Voices Folder"); + addPatchDir("Voices"); //addPatchDir("VMD Folder"); // There can also be a "Patches" resource fork with patches @@ -620,11 +621,11 @@ void ResourceManager::scanNewSources() { switch (source->source_type) { case kSourceDirectory: readResourcePatches(source); -#ifdef ENABLE_SCI32 + // We can't use getSciVersion() at this point, thus using _volVersion if (_volVersion >= kResVersionSci11) // SCI1.1+ readResourcePatchesBase36(source); -#endif + readWaveAudioPatches(); break; case kSourceExtMap: @@ -1070,18 +1071,14 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { // version-agnostic patch application void ResourceManager::processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple) { Common::SeekableReadStream *fileStream = 0; - Resource *newrsc; + Resource *newrsc = 0; ResourceId resId = ResourceId(resourceType, resourceNr, tuple); ResourceType checkForType = resourceType; - byte patchType, patchDataOffset; - int fsize; - uint32 audio36Header = 0; // base36 encoded patches (i.e. audio36 and sync36) have the same type as their non-base36 encoded counterparts if (checkForType == kResourceTypeAudio36) checkForType = kResourceTypeAudio; - - if (checkForType == kResourceTypeSync36) + else if (checkForType == kResourceTypeSync36) checkForType = kResourceTypeSync; if (source->resourceFile) { @@ -1094,18 +1091,15 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource } fileStream = file; } - fsize = fileStream->size(); + + int fsize = fileStream->size(); if (fsize < 3) { debug("Patching %s failed - file too small", source->location_name.c_str()); return; } - patchType = fileStream->readByte() & 0x7F; - patchDataOffset = fileStream->readByte(); - - if (resourceType == kResourceTypeAudio36) { - audio36Header = fileStream->readUint32BE(); - } + byte patchType = fileStream->readByte() & 0x7F; + byte patchDataOffset = fileStream->readByte(); delete fileStream; @@ -1114,13 +1108,6 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource return; } - if (resourceType == kResourceTypeAudio36) { - if (audio36Header != MKID_BE('SOL\x00')) { - debug("Patching %s failed - audio36 patch doesn't have SOL header", source->location_name.c_str()); - return; - } - } - // Fixes SQ5/German, patch file special case logic taken from SCI View disassembly if (patchDataOffset & 0x80) { switch (patchDataOffset & 0x7F) { @@ -1144,12 +1131,14 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource source->location_name.c_str(), patchDataOffset + 2, fsize); return; } + // Prepare destination, if neccessary if (_resMap.contains(resId) == false) { newrsc = new Resource; _resMap.setVal(resId, newrsc); } else newrsc = _resMap.getVal(resId); + // Overwrite everything, because we're patching newrsc->_id = resId; newrsc->_status = kResStatusNoMalloc; @@ -1160,8 +1149,6 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource debugC(1, kDebugLevelResMan, "Patching %s - OK", source->location_name.c_str()); } -#ifdef ENABLE_SCI32 - void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { // The base36 encoded audio36 and sync36 resources use a different naming scheme, because they // cannot be described with a single resource number, but are a result of a @@ -1192,19 +1179,20 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { name = (*x)->getName(); + inputName = (*x)->getName(); inputName.toUppercase(); - inputName.deleteChar(0); // delete the first character (type) inputName.deleteChar(7); // delete the dot // The base36 encoded resource contains the following: // uint16 resourceId, byte noun, byte verb, byte cond, byte seq - uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters - uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters - uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters - uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters - uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + uint16 resourceNr = strtol(Common::String(inputName.c_str(), 3).c_str(), 0, 36); // 3 characters + uint16 noun = strtol(Common::String(inputName.c_str() + 3, 2).c_str(), 0, 36); // 2 characters + uint16 verb = strtol(Common::String(inputName.c_str() + 5, 2).c_str(), 0, 36); // 2 characters + uint16 cond = strtol(Common::String(inputName.c_str() + 7, 2).c_str(), 0, 36); // 2 characters + uint16 seq = strtol(Common::String(inputName.c_str() + 9, 1).c_str(), 0, 36); // 1 character + // Check, if we got valid results if ((noun <= 255) && (verb <= 255) && (cond <= 255) && (seq <= 255)) { ResourceId resource36((ResourceType)i, resourceNr, noun, verb, cond, seq); @@ -1216,6 +1204,28 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { debug("sync36 patch: %s => %s. tuple:%d, %s\n", name.c_str(), inputName.c_str(), resource36.tuple, resource36.toString().c_str()); */ + // Make sure that the audio patch is a valid resource + if (i == kResourceTypeAudio36) { + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); + uint32 tag = stream->readUint32BE(); + + if (tag == MKID_BE('RIFF') || tag == MKID_BE('FORM')) { + delete stream; + processWavePatch(resource36, name); + continue; + } + + // Check for SOL as well + tag = (tag << 16) | stream->readUint16BE(); + + if (tag != MKID_BE('SOL\0')) { + delete stream; + continue; + } + + delete stream; + } + psrcPatch = new ResourceSource; psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; @@ -1226,8 +1236,6 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { } } -#endif - void ResourceManager::readResourcePatches(ResourceSource *source) { // Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files // this function tries to read patch file with any supported naming scheme, diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 533c81bdf5..66742f11f5 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -452,15 +452,14 @@ protected: * Reads patch files from a local directory. */ void readResourcePatches(ResourceSource *source); -#ifdef ENABLE_SCI32 void readResourcePatchesBase36(ResourceSource *source); -#endif void processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple = 0); /** * Process wave files as patches for Audio resources */ void readWaveAudioPatches(); + void processWavePatch(ResourceId resourceId, Common::String name); /** * Applies to all versions before 0.000.395 (i.e. KQ4 old, XMAS 1988 and LSL2). diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 2a5b56d4bc..861866edc0 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -162,6 +162,34 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { } } +void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { + ResourceSource *resSrc = new ResourceSource; + resSrc->source_type = kSourceWave; + resSrc->resourceFile = 0; + resSrc->location_name = name; + resSrc->volume_number = 0; + resSrc->audioCompressionType = 0; + + Resource *newRes = 0; + + if (_resMap.contains(resourceId)) { + newRes = _resMap.getVal(resourceId); + } else { + newRes = new Resource; + _resMap.setVal(resourceId, newRes); + } + + Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); + newRes->size = stream->size(); + delete stream; + + newRes->_id = resourceId; + newRes->_status = kResStatusNoMalloc; + newRes->_source = resSrc; + newRes->_headerSize = 0; + debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str()); +} + void ResourceManager::readWaveAudioPatches() { // Here we do check for SCI1.1+ so we can patch wav files in as audio resources Common::ArchiveMemberList files; @@ -170,39 +198,8 @@ void ResourceManager::readWaveAudioPatches() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String name = (*x)->getName(); - if (isdigit(name[0])) { - int number = atoi(name.c_str()); - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourceWave; - psrcPatch->resourceFile = 0; - psrcPatch->location_name = name; - psrcPatch->volume_number = 0; - psrcPatch->audioCompressionType = 0; - - ResourceId resId = ResourceId(kResourceTypeAudio, number); - - Resource *newrsc = NULL; - - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - - // Get the size of the file - Common::SeekableReadStream *stream = (*x)->createReadStream(); - uint32 fileSize = stream->size(); - delete stream; - - // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = psrcPatch; - newrsc->size = fileSize; - newrsc->_headerSize = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", psrcPatch->location_name.c_str()); - } + if (isdigit(name[0])) + processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name); } } diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 7748c0505b..f10cc5ed68 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -24,21 +24,22 @@ */ #include "sci/resource.h" -#include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "sci/engine/selector.h" #include "sci/engine/seg_manager.h" #include "sci/sound/audio.h" -#include "common/system.h" #include "common/file.h" +#include "common/system.h" -#include "sound/audiostream.h" #include "sound/audiocd.h" -#include "sound/decoders/raw.h" -#include "sound/decoders/wave.h" +#include "sound/audiostream.h" +#include "sound/decoders/aiff.h" #include "sound/decoders/flac.h" #include "sound/decoders/mp3.h" +#include "sound/decoders/raw.h" #include "sound/decoders/vorbis.h" +#include "sound/decoders/wave.h" namespace Sci { @@ -287,6 +288,19 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 waveStream->seek(0, SEEK_SET); audioStream = Audio::makeWAVStream(waveStream, DisposeAfterUse::YES); + } else if (audioRes->size > 4 && READ_BE_UINT32(audioRes->data) == MKID_BE('FORM')) { + // AIFF detected + Common::MemoryReadStream *waveStream = new Common::MemoryReadStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); + + // Calculate samplelen from AIFF header + int waveSize = 0, waveRate = 0; + byte waveFlags = 0; + Audio::loadAIFFFromStream(*waveStream, waveSize, waveRate, waveFlags); + *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; + + waveStream->seek(0, SEEK_SET); + audioStream = Audio::makeAIFFStream(*waveStream); + delete waveStream; // makeAIFFStream doesn't handle this for us } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected -- cgit v1.2.3 From 8295eb09cd7f0a62359631ab4b1975b2b6364bf3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 15:25:18 +0000 Subject: SCI: Fix Console::cmdValueType to handle all possible reg types svn-id: r49577 --- engines/sci/console.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index c2ea377f9b..f5a1880bf5 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1911,9 +1911,11 @@ bool Console::cmdValueType(int argc, const char **argv) { break; case KSIG_ARITHMETIC: DebugPrintf("Arithmetic"); + case KSIG_ARITHMETIC | KSIG_NULL: + DebugPrintf("Null"); break; default: - DebugPrintf("Erroneous unknown type %02x(%d decimal)\n", t, t); + DebugPrintf("Erroneous unknown type 0x%02x (%d decimal)\n", t, t); } return true; -- cgit v1.2.3 From 874151f5d12d86557dbea3bde180dbba0dfd4a2c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 15:25:36 +0000 Subject: SCI: Cleanup kernel signature code a bit. * Moved KSIG_SPEC_* from kernel.h to kernel.cpp * Clarified the comment on KSIG_SPEC_* a bit * Changed the other KSIG_ #defines into an enum * Removed KSIG_TERMINATOR and KSIG_SPEC_ARITMETIC (sic) svn-id: r49578 --- engines/sci/engine/kernel.cpp | 23 +++++++++++++++++++++-- engines/sci/engine/kernel.h | 40 ++++++++++++---------------------------- 2 files changed, 33 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2315dc384f..33a4d68c88 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -33,6 +33,26 @@ namespace Sci { +// Uncompiled kernel signatures are formed from a string of letters. +// each corresponding to a type of a parameter (see below). +// Use small letters to indicate end of sum type. +// Use capital letters for sum types, e.g. +// "LNoLr" for a function which takes two arguments: +// (1) list, node or object +// (2) list or ref +#define KSIG_SPEC_LIST 'l' +#define KSIG_SPEC_NODE 'n' +#define KSIG_SPEC_OBJECT 'o' +#define KSIG_SPEC_REF 'r' // Said Specs and strings +#define KSIG_SPEC_ARITHMETIC 'i' +#define KSIG_SPEC_NULL 'z' +#define KSIG_SPEC_ANY '.' +#define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments + +#define KSIG_SPEC_SUM_DONE ('a' - 'A') + + + // Default kernel name table #define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 @@ -538,8 +558,7 @@ static void kernel_compile_signature(const char **s) { break; default: - error("INTERNAL ERROR when compiling kernel function signature '%s': (%02x) not understood (aka" - " '%c')\n", *s, c, c); + error("ERROR compiling kernel function signature '%s': (%02x / '%c') not understood", *s, c, c); } } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY))); diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index c5513f1240..fc4b51f4ee 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -95,36 +95,20 @@ struct List; // from segment.h //#define DISABLE_VALIDATIONS // enable to stop validation checks // ---- Kernel signatures ----------------------------------------------------- -#define KSIG_TERMINATOR 0 - -// Uncompiled signatures -#define KSIG_SPEC_ARITMETIC 'i' -#define KSIG_SPEC_LIST 'l' -#define KSIG_SPEC_NODE 'n' -#define KSIG_SPEC_OBJECT 'o' -#define KSIG_SPEC_REF 'r' // Said Specs and strings -#define KSIG_SPEC_ARITHMETIC 'i' -#define KSIG_SPEC_NULL 'z' -#define KSIG_SPEC_ANY '.' -#define KSIG_SPEC_ELLIPSIS '*' // Arbitrarily more TYPED arguments - -#define KSIG_SPEC_SUM_DONE ('a' - 'A') // Use small letters to indicate end of sum type -/* Use capital letters for sum types, e.g. -** "LNoLr" for a function which takes two arguments: -** (1) list, node or object -** (2) list or ref -*/ + // Compiled signatures -#define KSIG_LIST 0x01 -#define KSIG_NODE 0x02 -#define KSIG_OBJECT 0x04 -#define KSIG_REF 0x08 -#define KSIG_ARITHMETIC 0x10 - -#define KSIG_NULL 0x40 -#define KSIG_ANY 0x5f -#define KSIG_ELLIPSIS 0x80 +enum { + KSIG_LIST = 0x01, + KSIG_NODE = 0x02, + KSIG_OBJECT = 0x04, + KSIG_REF = 0x08, + KSIG_ARITHMETIC = 0x10, + KSIG_NULL = 0x40, + KSIG_ANY = 0x5f, + KSIG_ELLIPSIS = 0x80 +}; + // ---------------------------------------------------------------------------- /* Generic description: */ -- cgit v1.2.3 From 5424d8aecb0d2c078aa8e18e94a2ac104d4bf039 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 15:25:54 +0000 Subject: SCI: Get rid of DEFUN, cleanup svn-id: r49579 --- engines/sci/engine/kernel.cpp | 405 +++++++++++++++++++++--------------------- 1 file changed, 199 insertions(+), 206 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 33a4d68c88..011dd0802e 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -53,10 +53,8 @@ namespace Sci { -// Default kernel name table -#define SCI_KNAMES_DEFAULT_ENTRIES_NR 0x89 - -static const char *sci_default_knames[SCI_KNAMES_DEFAULT_ENTRIES_NR] = { +/** Default kernel name table. */ +static const char *s_defaultKernelNames[] = { /*0x00*/ "Load", /*0x01*/ "UnLoad", /*0x02*/ "ScriptID", @@ -207,205 +205,203 @@ struct SciKernelFunction { const char *signature; /* kfunct signature */ }; -#define DEFUN(name, fun, sig) {name, fun, sig} - SciKernelFunction kfunct_mappers[] = { - /*00*/ DEFUN("Load", kLoad, "iii*"), - /*01*/ DEFUN("UnLoad", kUnLoad, "i.*"), // Work around SQ1 bug, when exiting the Ulence flats bar - /*02*/ DEFUN("ScriptID", kScriptID, "Ioi*"), - /*03*/ DEFUN("DisposeScript", kDisposeScript, "Oii*"), // Work around QfG1 bug - /*04*/ DEFUN("Clone", kClone, "o"), - /*05*/ DEFUN("DisposeClone", kDisposeClone, "o"), - /*06*/ DEFUN("IsObject", kIsObject, "."), - /*07*/ DEFUN("RespondsTo", kRespondsTo, ".i"), - /*08*/ DEFUN("DrawPic", kDrawPic, "i*"), - - /*0a*/ DEFUN("PicNotValid", kPicNotValid, "i*"), - /*0b*/ DEFUN("Animate", kAnimate, "LI*"), // More like (li?)? - /*0c*/ DEFUN("SetNowSeen", kSetNowSeen, "oi*"), // The second parameter is ignored - /*0d*/ DEFUN("NumLoops", kNumLoops, "o"), - /*0e*/ DEFUN("NumCels", kNumCels, "o"), - /*0f*/ DEFUN("CelWide", kCelWide, "iOi*"), - /*10*/ DEFUN("CelHigh", kCelHigh, "iOi*"), - /*11*/ DEFUN("DrawCel", kDrawCel, "iiiiii*i*r*"), - /*12*/ DEFUN("AddToPic", kAddToPic, "Il*"), + /*00*/ { "Load", kLoad, "iii*" }, + /*01*/ { "UnLoad", kUnLoad, "i.*" }, // Work around SQ1 bug, when exiting the Ulence flats bar + /*02*/ { "ScriptID", kScriptID, "Ioi*" }, + /*03*/ { "DisposeScript", kDisposeScript, "Oii*" }, // Work around QfG1 bug + /*04*/ { "Clone", kClone, "o" }, + /*05*/ { "DisposeClone", kDisposeClone, "o" }, + /*06*/ { "IsObject", kIsObject, "." }, + /*07*/ { "RespondsTo", kRespondsTo, ".i" }, + /*08*/ { "DrawPic", kDrawPic, "i*" }, + + /*0a*/ { "PicNotValid", kPicNotValid, "i*" }, + /*0b*/ { "Animate", kAnimate, "LI*" }, // More like (li?)? + /*0c*/ { "SetNowSeen", kSetNowSeen, "oi*" }, // The second parameter is ignored + /*0d*/ { "NumLoops", kNumLoops, "o" }, + /*0e*/ { "NumCels", kNumCels, "o" }, + /*0f*/ { "CelWide", kCelWide, "iOi*" }, + /*10*/ { "CelHigh", kCelHigh, "iOi*" }, + /*11*/ { "DrawCel", kDrawCel, "iiiiii*i*r*" }, + /*12*/ { "AddToPic", kAddToPic, "Il*" }, // FIXME: signature check removed (set to .*) as kNewWindow is different in Mac versions - /*13*/ DEFUN("NewWindow", kNewWindow, "*."), - ///*13*/ DEFUN("NewWindow", kNewWindow, "iiiiZRi*"), - /*14*/ DEFUN("GetPort", kGetPort, ""), - /*15*/ DEFUN("SetPort", kSetPort, "ii*"), - /*16*/ DEFUN("DisposeWindow", kDisposeWindow, "ii*"), - /*17*/ DEFUN("DrawControl", kDrawControl, "o"), - /*18*/ DEFUN("HiliteControl", kHiliteControl, "o"), - /*19*/ DEFUN("EditControl", kEditControl, "ZoZo"), - /*1a*/ DEFUN("TextSize", kTextSize, "rZrii*r*"), - /*1b*/ DEFUN("Display", kDisplay, ".*"), - /*1c*/ DEFUN("GetEvent", kGetEvent, "ioi*"), // Mac versions pass an extra 3rd parameter (ignored - always 0?) - /*1d*/ DEFUN("GlobalToLocal", kGlobalToLocal, "oo*"), - /*1e*/ DEFUN("LocalToGlobal", kLocalToGlobal, "oo*"), - /*1f*/ DEFUN("MapKeyToDir", kMapKeyToDir, "o"), - /*20*/ DEFUN("DrawMenuBar", kDrawMenuBar, "i"), - /*21*/ DEFUN("MenuSelect", kMenuSelect, "oi*"), - /*22*/ DEFUN("AddMenu", kAddMenu, "rr"), - /*23*/ DEFUN("DrawStatus", kDrawStatus, "Zri*"), - /*24*/ DEFUN("Parse", kParse, "ro"), - /*25*/ DEFUN("Said", kSaid, "Zr"), - /*26*/ DEFUN("SetSynonyms", kSetSynonyms, "o"), - /*27*/ DEFUN("HaveMouse", kHaveMouse, ""), - /*28*/ DEFUN("SetCursor", kSetCursor, "i*"), + /*13*/ { "NewWindow", kNewWindow, "*." }, + ///*13*/ { "NewWindow", kNewWindow, "iiiiZRi*" }, + /*14*/ { "GetPort", kGetPort, "" }, + /*15*/ { "SetPort", kSetPort, "ii*" }, + /*16*/ { "DisposeWindow", kDisposeWindow, "ii*" }, + /*17*/ { "DrawControl", kDrawControl, "o" }, + /*18*/ { "HiliteControl", kHiliteControl, "o" }, + /*19*/ { "EditControl", kEditControl, "ZoZo" }, + /*1a*/ { "TextSize", kTextSize, "rZrii*r*" }, + /*1b*/ { "Display", kDisplay, ".*" }, + /*1c*/ { "GetEvent", kGetEvent, "ioi*" }, // Mac versions pass an extra 3rd parameter (ignored - always 0?) + /*1d*/ { "GlobalToLocal", kGlobalToLocal, "oo*" }, + /*1e*/ { "LocalToGlobal", kLocalToGlobal, "oo*" }, + /*1f*/ { "MapKeyToDir", kMapKeyToDir, "o" }, + /*20*/ { "DrawMenuBar", kDrawMenuBar, "i" }, + /*21*/ { "MenuSelect", kMenuSelect, "oi*" }, + /*22*/ { "AddMenu", kAddMenu, "rr" }, + /*23*/ { "DrawStatus", kDrawStatus, "Zri*" }, + /*24*/ { "Parse", kParse, "ro" }, + /*25*/ { "Said", kSaid, "Zr" }, + /*26*/ { "SetSynonyms", kSetSynonyms, "o" }, + /*27*/ { "HaveMouse", kHaveMouse, "" }, + /*28*/ { "SetCursor", kSetCursor, "i*" }, // FIXME: The number 0x28 occurs twice :-) - /*28*/ DEFUN("MoveCursor", kMoveCursor, "ii"), - /*29*/ DEFUN("FOpen", kFOpen, "ri"), - /*2a*/ DEFUN("FPuts", kFPuts, "ir"), - /*2b*/ DEFUN("FGets", kFGets, "rii"), - /*2c*/ DEFUN("FClose", kFClose, "i"), - /*2d*/ DEFUN("SaveGame", kSaveGame, "rirr*"), - /*2e*/ DEFUN("RestoreGame", kRestoreGame, "rir*"), - /*2f*/ DEFUN("RestartGame", kRestartGame, ""), - /*30*/ DEFUN("GameIsRestarting", kGameIsRestarting, "i*"), - /*31*/ DEFUN("DoSound", kDoSound, "iIo*"), - /*32*/ DEFUN("NewList", kNewList, ""), - /*33*/ DEFUN("DisposeList", kDisposeList, "l"), - /*34*/ DEFUN("NewNode", kNewNode, ".."), - /*35*/ DEFUN("FirstNode", kFirstNode, "Zl"), - /*36*/ DEFUN("LastNode", kLastNode, "l"), - /*37*/ DEFUN("EmptyList", kEmptyList, "l"), - /*38*/ DEFUN("NextNode", kNextNode, "n"), - /*39*/ DEFUN("PrevNode", kPrevNode, "n"), - /*3a*/ DEFUN("NodeValue", kNodeValue, "Zn"), - /*3b*/ DEFUN("AddAfter", kAddAfter, "lnn"), - /*3c*/ DEFUN("AddToFront", kAddToFront, "ln"), - /*3d*/ DEFUN("AddToEnd", kAddToEnd, "ln"), - /*3e*/ DEFUN("FindKey", kFindKey, "l."), - /*3f*/ DEFUN("DeleteKey", kDeleteKey, "l."), - /*40*/ DEFUN("Random", kRandom, "i*"), - /*41*/ DEFUN("Abs", kAbs, "Oi"), - /*42*/ DEFUN("Sqrt", kSqrt, "i"), - /*43*/ DEFUN("GetAngle", kGetAngle, "iiiii*"), // occasionally KQ6 passes a 5th argument by mistake - /*44*/ DEFUN("GetDistance", kGetDistance, "iiiii*"), - /*45*/ DEFUN("Wait", kWait, "i"), - /*46*/ DEFUN("GetTime", kGetTime, "i*"), - /*47*/ DEFUN("StrEnd", kStrEnd, "r"), - /*48*/ DEFUN("StrCat", kStrCat, "rr"), - /*49*/ DEFUN("StrCmp", kStrCmp, "rri*"), - /*4a*/ DEFUN("StrLen", kStrLen, "Zr"), - /*4b*/ DEFUN("StrCpy", kStrCpy, "rZri*"), - /*4c*/ DEFUN("Format", kFormat, "r.*"), - /*4d*/ DEFUN("GetFarText", kGetFarText, "iiZr"), - /*4e*/ DEFUN("ReadNumber", kReadNumber, "r"), - /*4f*/ DEFUN("BaseSetter", kBaseSetter, "o"), - /*50*/ DEFUN("DirLoop", kDirLoop, "oi"), + /*28*/ { "MoveCursor", kMoveCursor, "ii" }, + /*29*/ { "FOpen", kFOpen, "ri" }, + /*2a*/ { "FPuts", kFPuts, "ir" }, + /*2b*/ { "FGets", kFGets, "rii" }, + /*2c*/ { "FClose", kFClose, "i" }, + /*2d*/ { "SaveGame", kSaveGame, "rirr*" }, + /*2e*/ { "RestoreGame", kRestoreGame, "rir*" }, + /*2f*/ { "RestartGame", kRestartGame, "" }, + /*30*/ { "GameIsRestarting", kGameIsRestarting, "i*" }, + /*31*/ { "DoSound", kDoSound, "iIo*" }, + /*32*/ { "NewList", kNewList, "" }, + /*33*/ { "DisposeList", kDisposeList, "l" }, + /*34*/ { "NewNode", kNewNode, ".." }, + /*35*/ { "FirstNode", kFirstNode, "Zl" }, + /*36*/ { "LastNode", kLastNode, "l" }, + /*37*/ { "EmptyList", kEmptyList, "l" }, + /*38*/ { "NextNode", kNextNode, "n" }, + /*39*/ { "PrevNode", kPrevNode, "n" }, + /*3a*/ { "NodeValue", kNodeValue, "Zn" }, + /*3b*/ { "AddAfter", kAddAfter, "lnn" }, + /*3c*/ { "AddToFront", kAddToFront, "ln" }, + /*3d*/ { "AddToEnd", kAddToEnd, "ln" }, + /*3e*/ { "FindKey", kFindKey, "l." }, + /*3f*/ { "DeleteKey", kDeleteKey, "l." }, + /*40*/ { "Random", kRandom, "i*" }, + /*41*/ { "Abs", kAbs, "Oi" }, + /*42*/ { "Sqrt", kSqrt, "i" }, + /*43*/ { "GetAngle", kGetAngle, "iiiii*" }, // occasionally KQ6 passes a 5th argument by mistake + /*44*/ { "GetDistance", kGetDistance, "iiiii*" }, + /*45*/ { "Wait", kWait, "i" }, + /*46*/ { "GetTime", kGetTime, "i*" }, + /*47*/ { "StrEnd", kStrEnd, "r" }, + /*48*/ { "StrCat", kStrCat, "rr" }, + /*49*/ { "StrCmp", kStrCmp, "rri*" }, + /*4a*/ { "StrLen", kStrLen, "Zr" }, + /*4b*/ { "StrCpy", kStrCpy, "rZri*" }, + /*4c*/ { "Format", kFormat, "r.*" }, + /*4d*/ { "GetFarText", kGetFarText, "iiZr" }, + /*4e*/ { "ReadNumber", kReadNumber, "r" }, + /*4f*/ { "BaseSetter", kBaseSetter, "o" }, + /*50*/ { "DirLoop", kDirLoop, "oi" }, // Opcode 51 is defined twice for a reason: In older SCI versions // it is CanBeHere, whereas in newer version it is CantBeHere - /*51*/ DEFUN("CanBeHere", kCanBeHere, "ol*"), - /*51*/ DEFUN("CantBeHere", kCantBeHere, "ol*"), - /*52*/ DEFUN("OnControl", kOnControl, "i*"), - /*53*/ DEFUN("InitBresen", kInitBresen, "oi*"), - /*54*/ DEFUN("DoBresen", kDoBresen, "o"), - /*55*/ DEFUN("DoAvoider", kDoAvoider, "o"), - /*56*/ DEFUN("SetJump", kSetJump, "oiii"), - /*57*/ DEFUN("SetDebug", kSetDebug, "i*"), - /*5c*/ DEFUN("MemoryInfo", kMemoryInfo, "i"), - /*5f*/ DEFUN("GetMenu", kGetMenu, "i."), - /*60*/ DEFUN("SetMenu", kSetMenu, "i.*"), - /*61*/ DEFUN("GetSaveFiles", kGetSaveFiles, "rrr"), - /*62*/ DEFUN("GetCWD", kGetCWD, "r"), - /*63*/ DEFUN("CheckFreeSpace", kCheckFreeSpace, "r.*"), - /*64*/ DEFUN("ValidPath", kValidPath, "r"), - /*65*/ DEFUN("CoordPri", kCoordPri, "ii*"), - /*66*/ DEFUN("StrAt", kStrAt, "rii*"), - /*67*/ DEFUN("DeviceInfo", kDeviceInfo, "i.*"), - /*68*/ DEFUN("GetSaveDir", kGetSaveDir, ".*"), // accepts a parameter in SCI2+ games - /*69*/ DEFUN("CheckSaveGame", kCheckSaveGame, ".*"), - /*6a*/ DEFUN("ShakeScreen", kShakeScreen, "ii*"), - /*6b*/ DEFUN("FlushResources", kFlushResources, "i"), - /*6c*/ DEFUN("TimesSin", kTimesSin, "ii"), - /*6d*/ DEFUN("TimesCos", kTimesCos, "ii"), - /*6e*/ DEFUN("6e", kTimesSin, "ii"), - /*6f*/ DEFUN("6f", kTimesCos, "ii"), - /*70*/ DEFUN("Graph", kGraph, ".*"), - /*71*/ DEFUN("Joystick", kJoystick, ".*"), + /*51*/ { "CanBeHere", kCanBeHere, "ol*" }, + /*51*/ { "CantBeHere", kCantBeHere, "ol*" }, + /*52*/ { "OnControl", kOnControl, "i*" }, + /*53*/ { "InitBresen", kInitBresen, "oi*" }, + /*54*/ { "DoBresen", kDoBresen, "o" }, + /*55*/ { "DoAvoider", kDoAvoider, "o" }, + /*56*/ { "SetJump", kSetJump, "oiii" }, + /*57*/ { "SetDebug", kSetDebug, "i*" }, + /*5c*/ { "MemoryInfo", kMemoryInfo, "i" }, + /*5f*/ { "GetMenu", kGetMenu, "i." }, + /*60*/ { "SetMenu", kSetMenu, "i.*" }, + /*61*/ { "GetSaveFiles", kGetSaveFiles, "rrr" }, + /*62*/ { "GetCWD", kGetCWD, "r" }, + /*63*/ { "CheckFreeSpace", kCheckFreeSpace, "r.*" }, + /*64*/ { "ValidPath", kValidPath, "r" }, + /*65*/ { "CoordPri", kCoordPri, "ii*" }, + /*66*/ { "StrAt", kStrAt, "rii*" }, + /*67*/ { "DeviceInfo", kDeviceInfo, "i.*" }, + /*68*/ { "GetSaveDir", kGetSaveDir, ".*" }, // accepts a parameter in SCI2+ games + /*69*/ { "CheckSaveGame", kCheckSaveGame, ".*" }, + /*6a*/ { "ShakeScreen", kShakeScreen, "ii*" }, + /*6b*/ { "FlushResources", kFlushResources, "i" }, + /*6c*/ { "TimesSin", kTimesSin, "ii" }, + /*6d*/ { "TimesCos", kTimesCos, "ii" }, + /*6e*/ { "6e", kTimesSin, "ii" }, + /*6f*/ { "6f", kTimesCos, "ii" }, + /*70*/ { "Graph", kGraph, ".*" }, + /*71*/ { "Joystick", kJoystick, ".*" }, // Experimental functions - /*74*/ DEFUN("FileIO", kFileIO, "i.*"), - /*(?)*/ DEFUN("Memory", kMemory, "i.*"), - /*(?)*/ DEFUN("Sort", kSort, "ooo"), - /*(?)*/ DEFUN("AvoidPath", kAvoidPath, "ii.*"), - /*(?)*/ DEFUN("Lock", kLock, "iii*"), - /*(?)*/ DEFUN("Palette", kPalette, "i.*"), - /*(?)*/ DEFUN("IsItSkip", kIsItSkip, "iiiii"), - /*7b*/ DEFUN("StrSplit", kStrSplit, "rrZr"), + /*74*/ { "FileIO", kFileIO, "i.*" }, + /*(?)*/ { "Memory", kMemory, "i.*" }, + /*(?)*/ { "Sort", kSort, "ooo" }, + /*(?)*/ { "AvoidPath", kAvoidPath, "ii.*" }, + /*(?)*/ { "Lock", kLock, "iii*" }, + /*(?)*/ { "Palette", kPalette, "i.*" }, + /*(?)*/ { "IsItSkip", kIsItSkip, "iiiii" }, + /*7b*/ { "StrSplit", kStrSplit, "rrZr" }, // Non-experimental functions without a fixed ID - DEFUN("CosMult", kTimesCos, "ii"), - DEFUN("SinMult", kTimesSin, "ii"), + { "CosMult", kTimesCos, "ii" }, + { "SinMult", kTimesSin, "ii" }, // Misc functions - /*(?)*/ DEFUN("CosDiv", kCosDiv, "ii"), - /*(?)*/ DEFUN("PriCoord", kPriCoord, "i"), - /*(?)*/ DEFUN("SinDiv", kSinDiv, "ii"), - /*(?)*/ DEFUN("TimesCot", kTimesCot, "ii"), - /*(?)*/ DEFUN("TimesTan", kTimesTan, "ii"), - DEFUN("Message", kMessage, ".*"), - DEFUN("GetMessage", kGetMessage, "iiir"), - DEFUN("DoAudio", kDoAudio, ".*"), - DEFUN("DoSync", kDoSync, ".*"), - DEFUN("MemorySegment", kMemorySegment, "iri*"), - DEFUN("Intersections", kIntersections, "iiiiriiiri"), - DEFUN("MergePoly", kMergePoly, "rli"), - DEFUN("ResCheck", kResCheck, "iii*"), - DEFUN("SetQuitStr", kSetQuitStr, "r"), - DEFUN("ShowMovie", kShowMovie, ".*"), - DEFUN("SetVideoMode", kSetVideoMode, "i"), - DEFUN("Platform", kPlatform, ".*"), - DEFUN("TextColors", kTextColors, ".*"), - DEFUN("TextFonts", kTextFonts, ".*"), - DEFUN("Portrait", kPortrait, ".*"), + /*(?)*/ { "CosDiv", kCosDiv, "ii" }, + /*(?)*/ { "PriCoord", kPriCoord, "i" }, + /*(?)*/ { "SinDiv", kSinDiv, "ii" }, + /*(?)*/ { "TimesCot", kTimesCot, "ii" }, + /*(?)*/ { "TimesTan", kTimesTan, "ii" }, + { "Message", kMessage, ".*" }, + { "GetMessage", kGetMessage, "iiir" }, + { "DoAudio", kDoAudio, ".*" }, + { "DoSync", kDoSync, ".*" }, + { "MemorySegment", kMemorySegment, "iri*" }, + { "Intersections", kIntersections, "iiiiriiiri" }, + { "MergePoly", kMergePoly, "rli" }, + { "ResCheck", kResCheck, "iii*" }, + { "SetQuitStr", kSetQuitStr, "r" }, + { "ShowMovie", kShowMovie, ".*" }, + { "SetVideoMode", kSetVideoMode, "i" }, + { "Platform", kPlatform, ".*" }, + { "TextColors", kTextColors, ".*" }, + { "TextFonts", kTextFonts, ".*" }, + { "Portrait", kPortrait, ".*" }, #ifdef ENABLE_SCI32 // SCI2 Kernel Functions - DEFUN("IsHiRes", kIsHiRes, ""), - DEFUN("Array", kArray, ".*"), - DEFUN("ListAt", kListAt, "li"), - DEFUN("String", kString, ".*"), - DEFUN("AddScreenItem", kAddScreenItem, "o"), - DEFUN("UpdateScreenItem", kUpdateScreenItem, "o"), - DEFUN("DeleteScreenItem", kDeleteScreenItem, "o"), - DEFUN("AddPlane", kAddPlane, "o"), - DEFUN("DeletePlane", kDeletePlane, "o"), - DEFUN("UpdatePlane", kUpdatePlane, "o"), - DEFUN("RepaintPlane", kRepaintPlane, "o"), - DEFUN("GetHighPlanePri", kGetHighPlanePri, ""), - DEFUN("FrameOut", kFrameOut, ""), - DEFUN("ListEachElementDo", kListEachElementDo, "li.*"), - DEFUN("ListFirstTrue", kListFirstTrue, "li.*"), - DEFUN("ListAllTrue", kListAllTrue, "li.*"), - DEFUN("ListIndexOf", kListIndexOf, "lZo"), - DEFUN("OnMe", kOnMe, "iio.*"), - DEFUN("InPolygon", kInPolygon, "iio"), - DEFUN("CreateTextBitmap", kCreateTextBitmap, "i.*"), + { "IsHiRes", kIsHiRes, "" }, + { "Array", kArray, ".*" }, + { "ListAt", kListAt, "li" }, + { "String", kString, ".*" }, + { "AddScreenItem", kAddScreenItem, "o" }, + { "UpdateScreenItem", kUpdateScreenItem, "o" }, + { "DeleteScreenItem", kDeleteScreenItem, "o" }, + { "AddPlane", kAddPlane, "o" }, + { "DeletePlane", kDeletePlane, "o" }, + { "UpdatePlane", kUpdatePlane, "o" }, + { "RepaintPlane", kRepaintPlane, "o" }, + { "GetHighPlanePri", kGetHighPlanePri, "" }, + { "FrameOut", kFrameOut, "" }, + { "ListEachElementDo", kListEachElementDo, "li.*" }, + { "ListFirstTrue", kListFirstTrue, "li.*" }, + { "ListAllTrue", kListAllTrue, "li.*" }, + { "ListIndexOf", kListIndexOf, "lZo" }, + { "OnMe", kOnMe, "iio.*" }, + { "InPolygon", kInPolygon, "iio" }, + { "CreateTextBitmap", kCreateTextBitmap, "i.*" }, // SCI2.1 Kernel Functions - DEFUN("Save", kSave, ".*"), - DEFUN("List", kList, ".*"), - DEFUN("Robot", kRobot, ".*"), - DEFUN("IsOnMe", kOnMe, "iio.*"), // TODO: this seems right, but verify... + { "Save", kSave, ".*" }, + { "List", kList, ".*" }, + { "Robot", kRobot, ".*" }, + { "IsOnMe", kOnMe, "iio.*" }, // TODO: this seems right, but verify... #endif // its a stub, but its needed for Pharkas to work - DEFUN("PalVary", kPalVary, "ii*"), - DEFUN("AssertPalette", kAssertPalette, "i"), + { "PalVary", kPalVary, "ii*" }, + { "AssertPalette", kAssertPalette, "i" }, #if 0 // Stub functions - /*09*/ DEFUN("Show", kShow, "i"), - DEFUN("ShiftScreen", kShiftScreen, ".*"), - DEFUN("ListOps", kListOps, ".*"), - DEFUN("ATan", kATan, ".*"), - DEFUN("Record", kRecord, ".*"), - DEFUN("PlayBack", kPlayBack, ".*"), - DEFUN("DbugStr", kDbugStr, ".*"), + /*09*/ { "Show", kShow, "i" }, + { "ShiftScreen", kShiftScreen, ".*" }, + { "ListOps", kListOps, ".*" }, + { "ATan", kATan, ".*" }, + { "Record", kRecord, ".*" }, + { "PlayBack", kPlayBack, ".*" }, + { "DbugStr", kDbugStr, ".*" }, #endif {NULL, NULL, NULL} // Terminator @@ -500,8 +496,7 @@ void Kernel::loadSelectorNames() { static void kernel_compile_signature(const char **s) { const char *src = *s; char *result; - int ellipsis = 0; - char v; + bool ellipsis = false; int index = 0; if (!src) @@ -511,7 +506,7 @@ static void kernel_compile_signature(const char **s) { while (*src) { char c; - v = 0; + char v = 0; if (ellipsis) { error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", *s, *src); @@ -554,7 +549,7 @@ static void kernel_compile_signature(const char **s) { case KSIG_SPEC_ELLIPSIS: v |= KSIG_ELLIPSIS; - ellipsis = 1; + ellipsis = true; break; default: @@ -706,12 +701,13 @@ bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { } if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) return true; + warning("kernel_matches_signature: too few arguments"); return false; } void Kernel::setDefaultKernelNames() { - _kernelNames = Common::StringArray(sci_default_knames, SCI_KNAMES_DEFAULT_ENTRIES_NR); + _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); // Some (later) SCI versions replaced CanBeHere by CantBeHere if (_selectorCache.cantBeHere != -1) @@ -787,31 +783,28 @@ Common::String Kernel::lookupText(reg_t address, int index) { if (address.segment) return _segMan->getString(address); - else { - int textlen; - int _index = index; - textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0); - - if (!textres) { - error("text.%03d not found", address.offset); - return NULL; /* Will probably segfault */ - } - textlen = textres->size; - seeker = (char *) textres->data; + int textlen; + int _index = index; + textres = _resMan->findResource(ResourceId(kResourceTypeText, address.offset), 0); - while (index--) - while ((textlen--) && (*seeker++)) - ; + if (!textres) { + error("text.%03d not found", address.offset); + return NULL; /* Will probably segfault */ + } - if (textlen) - return seeker; - else { - error("Index %d out of bounds in text.%03d", _index, address.offset); - return NULL; - } + textlen = textres->size; + seeker = (char *) textres->data; - } + while (index--) + while ((textlen--) && (*seeker++)) + ; + + if (textlen) + return seeker; + + error("Index %d out of bounds in text.%03d", _index, address.offset); + return NULL; } } // End of namespace Sci -- cgit v1.2.3 From 4b0f0894c4fbd864c7d75dd04134f4b59af448a6 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 15:26:10 +0000 Subject: SCI: Switch Console::cmdSelector to use Kernel::getSelectorName svn-id: r49580 --- engines/sci/console.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f5a1880bf5..f025c63335 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -482,14 +482,15 @@ bool Console::cmdSelector(int argc, const char **argv) { return true; } - for (uint seeker = 0; seeker < _engine->getKernel()->getSelectorNamesSize(); seeker++) { - if (!scumm_stricmp(_engine->getKernel()->getSelectorName(seeker).c_str(), argv[1])) { - DebugPrintf("Selector %s found at %03x (%d)\n", _engine->getKernel()->getSelectorName(seeker).c_str(), seeker, seeker); - return true; - } + Common::String name = argv[1]; + name.toLowercase(); + int seeker = _engine->getKernel()->findSelector(name.c_str()); + if (seeker >= 0) { + DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); + return true; } - DebugPrintf("Selector %s wasn't found\n", argv[1]); + DebugPrintf("Selector %s wasn't found\n", name.c_str()); return true; } -- cgit v1.2.3 From 85b0ec3408ca46251835f9e3db8f2e96cafe60ac Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 10 Jun 2010 15:26:26 +0000 Subject: SCI: Fix some doxygen comments svn-id: r49581 --- engines/sci/engine/kernel.h | 32 ++++++++++++++++---------------- 1 file changed, 16 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index fc4b51f4ee..5cd044eadb 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -128,7 +128,7 @@ enum AutoDetectedFeatures { class Kernel { public: /** - * Initializes the SCI kernel + * Initializes the SCI kernel. */ Kernel(ResourceManager *resMan, SegManager *segMan); ~Kernel(); @@ -140,7 +140,7 @@ public: const Common::String &getKernelName(uint number) const; /** - * Determines the selector ID of a selector by its name + * Determines the selector ID of a selector by its name. * @param selectorName Name of the selector to look up * @return The appropriate selector ID, or -1 on error */ @@ -151,9 +151,9 @@ public: void dumpScriptObject(char *data, int seeker, int objsize); void dumpScriptClass(char *data, int seeker, int objsize); - SelectorCache _selectorCache; /**< Shortcut list for important selectors */ + SelectorCache _selectorCache; /**< Shortcut list for important selectors. */ typedef Common::Array KernelFuncsContainer; - KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions */ + KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions. */ /** * Determines whether a list of registers matches a given signature. @@ -179,11 +179,11 @@ public: /******************** Text functionality ********************/ /** - * Looks up text referenced by scripts - * SCI uses two values to reference to text: An address, and an index. The address - * determines whether the text should be read from a resource file, or from the heap, - * while the index either refers to the number of the string in the specified source, - * or to a relative position inside the text. + * Looks up text referenced by scripts. + * SCI uses two values to reference to text: An address, and an index. The + * address determines whether the text should be read from a resource file, + * or from the heap, while the index either refers to the number of the + * string in the specified source, or to a relative position inside the text. * * @param address The address to look up * @param index The relative index @@ -203,18 +203,18 @@ public: private: /** - * Sets the default kernel function names, based on the SCI version used + * Sets the default kernel function names, based on the SCI version used. */ void setDefaultKernelNames(); #ifdef ENABLE_SCI32 /** - * Sets the default kernel function names to the SCI2 kernel functions + * Sets the default kernel function names to the SCI2 kernel functions. */ void setKernelNamesSci2(); /** - * Sets the default kernel function names to the SCI2.1 kernel functions + * Sets the default kernel function names to the SCI2.1 kernel functions. */ void setKernelNamesSci21(GameFeatures *features); #endif @@ -231,12 +231,12 @@ private: Common::StringArray checkStaticSelectorNames(); /** - * Maps special selectors + * Maps special selectors. */ void mapSelectors(); /** - * Maps kernel functions + * Maps kernel functions. */ void mapFunctions(); @@ -252,14 +252,14 @@ private: /******************** Misc functions ********************/ /** - * Get all sound events, apply their changes to the heap + * Get all sound events, apply their changes to the heap. */ void process_sound_events(EngineState *s); /******************** Constants ********************/ #endif -/* Maximum length of a savegame name (including terminator character) */ +/* Maximum length of a savegame name (including terminator character). */ #define SCI_MAX_SAVENAME_LENGTH 0x24 /******************** Kernel functions ********************/ -- cgit v1.2.3 From 8f55c4ddb4ceb64e6121ee9fe08b07c2905d4748 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 10 Jun 2010 18:16:05 +0000 Subject: Allow for digits in stage directions in SCI32 games: GK1 floppy uses them. svn-id: r49582 --- engines/sci/engine/message.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 07f8792471..523e8321db 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -330,7 +330,8 @@ bool MessageState::stringStage(Common::String &outstr, const Common::String &inS } // If we find a lowercase character or a digit, it's not a stage direction - if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9'))) + // SCI32 seems to support having digits in stage directions + if (((inStr[i] >= 'a') && (inStr[i] <= 'z')) || ((inStr[i] >= '0') && (inStr[i] <= '9') && (getSciVersion() < SCI_VERSION_2))) return false; } -- cgit v1.2.3 From 9f907aac095123ac016a23a559f54ada35af6772 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 10 Jun 2010 20:26:59 +0000 Subject: kSciAudioWPlay should not actually play the song, but 'pre-load' it. We fake the pre-loading with a flag that will return 0 if the song has been called with kSciAudioWPlay. Fixes the dream sequence sound in MUMG. svn-id: r49583 --- engines/sci/engine/ksound.cpp | 8 ++++++-- engines/sci/sound/audio.cpp | 16 ++++++++++++++++ engines/sci/sound/audio.h | 5 +++-- 3 files changed, 25 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 29302181b1..ebfd6e6885 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -44,7 +44,6 @@ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { - case kSciAudioWPlay: case kSciAudioPlay: { if (argc < 2) return NULL_REG; @@ -72,6 +71,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { break; case kSciAudioPosition: return make_reg(0, g_sci->_audio->audioCdPosition()); + case kSciAudioWPlay: // CD Audio can't be preloaded case kSciAudioRate: // No need to set the audio rate case kSciAudioVolume: // The speech setting isn't used by CD Audio case kSciAudioLanguage: // No need to set the language @@ -119,7 +119,11 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - return make_reg(0, g_sci->_audio->startAudio(module, number)); // return sample length in ticks + // return sample length in ticks + if (argv[0].toUint16() == kSciAudioWPlay) + return make_reg(0, g_sci->_audio->wPlayAudio(module, number)); + else + return make_reg(0, g_sci->_audio->startAudio(module, number)); } case kSciAudioStop: g_sci->_audio->stopAudio(); diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index f10cc5ed68..62cfcd9621 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -47,6 +47,7 @@ AudioPlayer::AudioPlayer(ResourceManager *resMan) : _resMan(resMan), _audioRate( _syncResource(NULL), _syncOffset(0), _audioCdStart(0) { _mixer = g_system->getMixer(); + _wPlayFlag = false; } AudioPlayer::~AudioPlayer() { @@ -65,6 +66,7 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { Audio::AudioStream *audioStream = getAudioStream(number, module, &sampleLen); if (audioStream) { + _wPlayFlag = false; _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); return sampleLen; } @@ -72,6 +74,18 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { return 0; } +int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { + // Get the audio sample length and set the wPlay flag so we return 0 on position. + // SSCI pre-loads the audio here, but it's much easier for us to just get the + // sample length and return that. wPlayAudio should *not* actually start the sample. + + int sampleLen = 0; + Audio::AudioStream *audioStream = getAudioStream(module, tuple, &sampleLen); + delete audioStream; + _wPlayFlag = true; + return sampleLen; +} + void AudioPlayer::stopAudio() { _mixer->stopHandle(_audioHandle); } @@ -87,6 +101,8 @@ void AudioPlayer::resumeAudio() { int AudioPlayer::getAudioPosition() { if (_mixer->isSoundHandleActive(_audioHandle)) return _mixer->getSoundElapsedTime(_audioHandle) * 6 / 100; // return elapsed time in ticks + else if (_wPlayFlag) + return 0; // Sound has "loaded" so return that it hasn't started else return -1; // Sound finished } diff --git a/engines/sci/sound/audio.h b/engines/sci/sound/audio.h index 9fc3cbac51..7c1221fc4c 100644 --- a/engines/sci/sound/audio.h +++ b/engines/sci/sound/audio.h @@ -33,8 +33,7 @@ namespace Sci { enum AudioCommands { - // TODO: find the difference between kSci1AudioWPlay and kSci1AudioPlay - kSciAudioWPlay = 1, /* Plays an audio stream */ + kSciAudioWPlay = 1, /* Loads an audio stream */ kSciAudioPlay = 2, /* Plays an audio stream */ kSciAudioStop = 3, /* Stops an audio stream */ kSciAudioPause = 4, /* Pauses an audio stream */ @@ -69,6 +68,7 @@ public: Audio::RewindableAudioStream *getAudioStream(uint32 number, uint32 volume, int *sampleLen); int getAudioPosition(); int startAudio(uint16 module, uint32 tuple); + int wPlayAudio(uint16 module, uint32 tuple); void stopAudio(); void pauseAudio(); void resumeAudio(); @@ -92,6 +92,7 @@ private: Resource *_syncResource; /**< Used by kDoSync for speech syncing in CD talkie games */ uint _syncOffset; uint32 _audioCdStart; + bool _wPlayFlag; }; } // End of namespace Sci -- cgit v1.2.3 From f470e1d96ed152751dc57418b7659559bc43217b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 10 Jun 2010 20:52:04 +0000 Subject: SCI: adding current delta to tick position when getting the setsignalloop command - fixes sq3 music slight delay before actual looping svn-id: r49585 --- engines/sci/sound/midiparser_sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 3ee8a3a83d..8f88945888 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -176,7 +176,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { _signalSet = true; _signalToSet = info.basic.param1; } else { - _loopTick = _position._play_tick; + _loopTick = _position._play_tick + info.delta; } } break; -- cgit v1.2.3 From 5baa47a9cbd42b2b40b599928ea6bf41f47fdc18 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 10 Jun 2010 23:16:32 +0000 Subject: In SCI1.1, kSetSynonyms is a dummy (empty) function svn-id: r49586 --- engines/sci/engine/kernel.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 011dd0802e..829687f226 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -742,6 +742,9 @@ void Kernel::setDefaultKernelNames() { break; case SCI_VERSION_1_1: + // In SCI1.1, kSetSynonyms is a dummy (empty) function + _kernelNames[0x26] = "Dummy"; + // In the Windows version of KQ6 CD, the empty kSetSynonyms // function has been replaced with kPortrait. In KQ6 Mac, // kPlayBack has been replaced by kShowMovie. -- cgit v1.2.3 From 377cfe6fefe6a817a6ce778e7721dc3818780c01 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 11 Jun 2010 07:47:57 +0000 Subject: Added a new kernel function, kEmpty, for really empty (not dummy, i.e. unimplemented) functions svn-id: r49591 --- engines/sci/engine/kernel.cpp | 5 +++-- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kmisc.cpp | 8 ++++++++ 3 files changed, 12 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 829687f226..d418fb7998 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -357,6 +357,7 @@ SciKernelFunction kfunct_mappers[] = { { "TextColors", kTextColors, ".*" }, { "TextFonts", kTextFonts, ".*" }, { "Portrait", kPortrait, ".*" }, + { "Empty", kEmpty, ".*" }, #ifdef ENABLE_SCI32 // SCI2 Kernel Functions @@ -742,8 +743,8 @@ void Kernel::setDefaultKernelNames() { break; case SCI_VERSION_1_1: - // In SCI1.1, kSetSynonyms is a dummy (empty) function - _kernelNames[0x26] = "Dummy"; + // In SCI1.1, kSetSynonyms is an empty function + _kernelNames[0x26] = "Empty"; // In the Windows version of KQ6 CD, the empty kSetSynonyms // function has been replaced with kPortrait. In KQ6 Mac, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 5cd044eadb..722473a85b 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -405,6 +405,7 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv); reg_t kPlatform(EngineState *s, int argc, reg_t *argv); reg_t kTextColors(EngineState *s, int argc, reg_t *argv); reg_t kTextFonts(EngineState *s, int argc, reg_t *argv); +reg_t kEmpty(EngineState *s, int argc, reg_t *argv); #ifdef ENABLE_SCI32 // SCI2 Kernel Functions diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index f3d4c8a732..d836ec4a7f 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -375,4 +375,12 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +reg_t kEmpty(EngineState *s, int argc, reg_t *argv) { + // Placeholder for empty kernel functions which are still called from the engine + // scripts (like the empty kSetSynonyms function in SCI1.1). This differs from + // dummy functions because it does nothing and never throws a warning when it's + // called + return s->r_acc; +} + } // End of namespace Sci -- cgit v1.2.3 From 3269e5cc4ca2ea04f862767595720ad2044cfd09 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 11 Jun 2010 09:17:11 +0000 Subject: SCI: adjust priority bottom, if its 200 to avoid possible out of bounds (sierra actually does the same) svn-id: r49592 --- engines/sci/graphics/ports.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index cdb6fe4ae1..d230c1eb9f 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -496,6 +496,11 @@ void GfxPorts::priorityBandsInit(int16 bandCount, int16 top, int16 bottom) { // We fill space that is left over with the highest band (hardcoded 200 limit, because this algo isnt meant to be used on hires) for (y = _priorityBottom; y < 200; y++) _priorityBands[y] = _priorityBandCount; + + // adjust, if bottom is 200 (one over the actual screen range) - we could otherwise go possible out of bounds + // sierra sci also adjust accordingly + if (_priorityBottom == 200) + _priorityBottom--; } void GfxPorts::priorityBandsInit(byte *data) { -- cgit v1.2.3 From ef34896dce9188591e8ddd6e8eed543febd70b87 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 11 Jun 2010 11:03:51 +0000 Subject: Clarified various incorrectly named parameters, and fixed code for loading the correct art file backgrounds when running animation sequences svn-id: r49595 --- engines/m4/animation.cpp | 4 ++-- engines/m4/animation.h | 2 +- engines/m4/mads_anim.cpp | 17 +++++++++++------ engines/m4/mads_anim.h | 1 + engines/m4/mads_scene.cpp | 2 +- engines/m4/mads_views.h | 2 +- 6 files changed, 17 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 1142ba48d1..dacfd8c581 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -63,7 +63,7 @@ MadsAnimation::~MadsAnimation() { /** * Initialises and loads the data of an animation */ -void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface) { +void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) { MadsPack anim(filename.c_str(), _vm); bool madsRes = filename[0] == '*'; char buffer[20]; @@ -114,7 +114,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S if (_animMode == 4) flags |= 0x4000; if (flags & 0x100) - loadInterface(interfaceSurface, sceneSurface); + loadInterface(surface, depthSurface); // Initialise the reference list for (int i = 0; i < spriteListCount; ++i) diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 5c7227a256..029cf45738 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -108,7 +108,7 @@ public: MadsAnimation(MadsM4Engine *vm, MadsView *view); virtual ~MadsAnimation(); - virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *interfaceSurface, M4Surface *sceneSurface); + virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface); virtual void load(const Common::String &filename, int abortTimers); virtual void update(); virtual void setCurrentFrame(int frameNumber); diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index eac6d1b4aa..c618ae57cc 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -458,6 +458,8 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): _previousUpdate = 0; _transition = kTransitionNone; _activeAnimation = NULL; + _bgLoadFlag = true; + reset(); // Set up system palette colors @@ -572,12 +574,12 @@ void AnimviewView::readNextCommand() { if (strchr(_currentLine, '.') == NULL) strcat(_currentLine, ".aa"); - _activeAnimation = new MadsAnimation(_vm, this); - _activeAnimation->load(_currentLine, 0); + uint16 flags = 0; + if (_bgLoadFlag) + flags |= 0x100; - _backgroundSurface.loadBackground(_activeAnimation->roomNumber()); - _codeSurface.setSize(_backgroundSurface.width(), _backgroundSurface.height()); - _codeSurface.fillRect(_codeSurface.bounds(), 0xff); + _activeAnimation = new MadsAnimation(_vm, this); + _activeAnimation->initialise(_currentLine, flags, &_backgroundSurface, &_codeSurface); _spriteSlots.fullRefresh(); /* @@ -675,7 +677,10 @@ void AnimviewView::processCommand() { str_upper(commandStr); char *param = commandStr; - if (!strncmp(commandStr, "X", 1)) { + if (!strncmp(commandStr, "B", 1)) { + // Toggle background load flag + _bgLoadFlag = !_bgLoadFlag; + } else if (!strncmp(commandStr, "X", 1)) { //printf("X "); } else if (!strncmp(commandStr, "W", 1)) { //printf("W "); diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h index 8c4a5e6fb7..f18fe46f48 100644 --- a/engines/m4/mads_anim.h +++ b/engines/m4/mads_anim.h @@ -90,6 +90,7 @@ private: RGBList *_palData; int _transition; MadsAnimation *_activeAnimation; + bool _bgLoadFlag; void reset(); void readNextCommand(); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index a65224c722..f98684de6a 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -720,7 +720,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su _vm->_resourceManager->toss(sceneName); // Load the surface artwork - surface->loadBackground(sceneNumber); + surface->loadBackground(artFileNum); // Final cleanup if (ssFlag) diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 85bfe9e552..c0f3790a23 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -367,7 +367,7 @@ protected: public: Animation(MadsM4Engine *vm); virtual ~Animation(); - virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *walkSurface, M4Surface *sceneSurface) = 0; + virtual void initialise(const Common::String &filename, uint16 flags, M4Surface *surface, M4Surface *depthSurface) = 0; virtual void load(const Common::String &filename, int v0) = 0; virtual void update() = 0; virtual void setCurrentFrame(int frameNumber) = 0; -- cgit v1.2.3 From e572267a05674b4b462602781be58f813c84479d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 11 Jun 2010 11:08:37 +0000 Subject: Bugfixes to correctly scroll the background during animations svn-id: r49596 --- engines/m4/animation.cpp | 2 +- engines/m4/graphics.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index dacfd8c581..adb802ee0e 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -87,7 +87,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S animStream->skip(2); _field12 = animStream->readUint16LE() != 0; _spriteListIndex = animStream->readUint16LE(); - _scrollX = animStream->readUint16LE(); + _scrollX = animStream->readSint16LE(); _scrollY = animStream->readSint16LE(); animStream->skip(10); diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index f332c8b06c..dd18972eec 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -769,7 +769,7 @@ void M4Surface::scrollX(int xAmount) { return; byte buffer[80]; - int direction = (xAmount > 0) ? 1 : -1; + int direction = (xAmount > 0) ? -1 : 1; int xSize = ABS(xAmount); assert(xSize <= 80); -- cgit v1.2.3 From a08d06ad353996ee9bf495a84988f3a91cacf51a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 11 Jun 2010 14:47:13 +0000 Subject: - Added a new debug command, verify_midi, which can be used to check all the songs of a game for unmapped instruments (still WIP and disabled) - Fixed a bug in the verify_scripts command (it was loading the script resource twice) svn-id: r49597 --- engines/sci/console.cpp | 106 ++++++++++++++++++++++++++++++++++- engines/sci/console.h | 1 + engines/sci/sound/midiparser_sci.cpp | 42 ++++++++------ engines/sci/sound/midiparser_sci.h | 2 + 4 files changed, 132 insertions(+), 19 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f025c63335..ac165f22b1 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -39,6 +39,7 @@ #include "sci/sound/iterator/songlib.h" // for SongLibrary #include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0 #else +#include "sci/sound/midiparser_sci.h" #include "sci/sound/music.h" #endif #include "sci/sound/drivers/mididriver.h" @@ -106,6 +107,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("list", WRAP_METHOD(Console, cmdList)); DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); + DCmd_Register("verify_midi", WRAP_METHOD(Console, cmdVerifyMidi)); // Game DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); @@ -326,6 +328,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" list - Lists all the resources of a given type\n"); DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); + DebugPrintf(" verify_midi - Performs checks on MIDI patches, for unmapped instruments\n"); DebugPrintf("\n"); DebugPrintf("Game:\n"); DebugPrintf(" save_game - Saves the current game state to the hard disk\n"); @@ -832,7 +835,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { if (!script) DebugPrintf("Error: script %d couldn't be loaded\n", itr->number); - heap = _engine->getResMan()->findResource(*itr, false); + heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->number), false); if (!heap) DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->number); @@ -848,6 +851,107 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { return true; } +bool Console::cmdVerifyMidi(int argc, const char **argv) { + // TODO: Sometimes this goes out of bounds with some songs, as it misses + // the EOT signal +#if 0 + SciVersion doSoundVersion = _engine->_features->detectDoSoundType(); + MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion); + MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion); + parser->setMidiDriver(player); + + Common::List *resources = _engine->getResMan()->listResources(kResourceTypeSound); + sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::List::iterator itr = resources->begin(); + + DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size()); + + SoundResource *sound; + + while (itr != resources->end()) { + sound = new SoundResource(itr->number, _engine->getResMan(), doSoundVersion); + int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel()); + SoundResource::Track *track = sound->getTrackByType(player->getPlayId()); + if (track->digitalChannelNr != -1) { + // Skip digitized sound effects + delete sound; + continue; + } + + parser->loadMusic(track, NULL, channelFilterMask, doSoundVersion); + const byte *channelData = parser->getMixedData(); + + byte param1 = 0; + byte command = 0, prev = 0; + byte curEvent = 0; + bool endOfTrack = false; + + do { + while (*channelData == 0xF8) + channelData++; + + channelData++; // delta + + if ((*channelData & 0xF0) >= 0x80) + curEvent = *(channelData++); + else + curEvent = prev; + if (curEvent < 0x80) + continue; + + prev = curEvent; + command = curEvent >> 4; + + switch (command) { + case 0xC: // program change + param1 = *channelData++; + // TODO: verify that the instrument is mapped + printf("Song %d, patch %d\n", itr->number, param1); + break; + case 0xD: + case 0xB: + param1 = *channelData++; + break; + case 0x8: + case 0x9: + case 0xA: + case 0xE: + param1 = *channelData++; + *channelData++; // param2 + break; + case 0xF: + if ((curEvent & 0x0F) == 0x2) { + param1 = *channelData++; + *channelData++; // param2 + } else if ((curEvent & 0x0F) == 0x3) { + param1 = *channelData++; + } else if ((curEvent & 0x0F) == 0xF) { // META + byte type = *channelData++; + if (type == 0x2F) {// end of track reached + endOfTrack = true; + } else { + // no further processing necessary + } + } + break; + default: + break; + } + } while (!endOfTrack); + + delete sound; + ++itr; + } + + delete parser; + delete player; + + DebugPrintf("Music check finished\n"); +#endif + + return true; +} + bool Console::cmdList(int argc, const char **argv) { if (argc < 2) { DebugPrintf("Lists all the resources of a given type\n"); diff --git a/engines/sci/console.h b/engines/sci/console.h index 2b13e03ef6..572a62c274 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -74,6 +74,7 @@ private: bool cmdList(int argc, const char **argv); bool cmdHexgrep(int argc, const char **argv); bool cmdVerifyScripts(int argc, const char **argv); + bool cmdVerifyMidi(int argc, const char **argv); // Game bool cmdSaveGame(int argc, const char **argv); bool cmdRestoreGame(int argc, const char **argv); diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 8f88945888..f852367bfe 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -75,7 +75,8 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _pSnd = psnd; _soundVersion = soundVersion; - setVolume(psnd->volume); + if (_pSnd) + setVolume(psnd->volume); if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection @@ -86,30 +87,35 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _num_tracks = 1; _tracks[0] = _mixedData; - setTrack(0); + if (_pSnd) + setTrack(0); _loopTick = 0; - if (_soundVersion <= SCI_VERSION_0_LATE) { - // Set initial voice count - for (int i = 0; i < 16; ++i) { - byte voiceCount = 0; - if (channelFilterMask & (1 << i)) - voiceCount = psnd->soundRes->getInitialVoiceCount(i); - _driver->send(0xB0 | i, 0x4B, voiceCount); + if (_pSnd) { + if (_soundVersion <= SCI_VERSION_0_LATE) { + // Set initial voice count + for (int i = 0; i < 16; ++i) { + byte voiceCount = 0; + if (channelFilterMask & (1 << i)) + voiceCount = psnd->soundRes->getInitialVoiceCount(i); + _driver->send(0xB0 | i, 0x4B, voiceCount); + } } - } - // Send a velocity off signal to all channels - for (int i = 0; i < 16; ++i) { - _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity + // Send a velocity off signal to all channels + for (int i = 0; i < 16; ++i) { + _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity + } } return true; } void MidiParser_SCI::unloadMusic() { - resetTracking(); - allNotesOff(); + if (_pSnd) { + resetTracking(); + allNotesOff(); + } _num_tracks = 0; _active_track = 255; _resetOnPause = false; @@ -120,7 +126,7 @@ void MidiParser_SCI::unloadMusic() { } // Center the pitch wheels and hold pedal in preparation for the next piece of music - if (_driver) { + if (_driver && _pSnd) { for (int i = 0; i < 16; ++i) { if (isChannelUsed(i)) { _driver->send(0xE0 | i, 0, 0x40); // Reset pitch wheel @@ -359,10 +365,10 @@ byte *MidiParser_SCI::midiMixChannels() { long new_delta; SoundResource::Channel *channel; - while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still active channel + while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel channel = &_track->channels[curr]; curDelta = *channel->data++; - channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the comamnd is supposed to occur + channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur if (curDelta == 0xF8) continue; new_delta = channel->time - ticker; diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 9d4b5a39da..8384c74cf6 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -79,6 +79,8 @@ public: void clearUsedChannels() { _channelsUsed = 0; } + const byte *getMixedData() const { return _mixedData; } + protected: bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); } void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); } -- cgit v1.2.3 From a8af267651c054bb45a0b5da77ea71b7100474ad Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 11 Jun 2010 19:49:41 +0000 Subject: Renamed verify_midi to show_instruments (and fixed a bug with it at the same time). This command scans all songs, or a specific song of a game and displays the instruments used svn-id: r49599 --- engines/sci/console.cpp | 85 +++++++++++++++++++++++++++++++++++-------------- engines/sci/console.h | 2 +- 2 files changed, 62 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index ac165f22b1..9d713cd2dd 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -107,7 +107,7 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("list", WRAP_METHOD(Console, cmdList)); DCmd_Register("hexgrep", WRAP_METHOD(Console, cmdHexgrep)); DCmd_Register("verify_scripts", WRAP_METHOD(Console, cmdVerifyScripts)); - DCmd_Register("verify_midi", WRAP_METHOD(Console, cmdVerifyMidi)); + DCmd_Register("show_instruments", WRAP_METHOD(Console, cmdShowInstruments)); // Game DCmd_Register("save_game", WRAP_METHOD(Console, cmdSaveGame)); DCmd_Register("restore_game", WRAP_METHOD(Console, cmdRestoreGame)); @@ -328,7 +328,7 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" list - Lists all the resources of a given type\n"); DebugPrintf(" hexgrep - Searches some resources for a particular sequence of bytes, represented as hexadecimal numbers\n"); DebugPrintf(" verify_scripts - Performs sanity checks on SCI1.1-SCI2.1 game scripts (e.g. if they're up to 64KB in total)\n"); - DebugPrintf(" verify_midi - Performs checks on MIDI patches, for unmapped instruments\n"); + DebugPrintf(" show_instruments - Shows the instruments of a specific song, or all songs\n"); DebugPrintf("\n"); DebugPrintf("Game:\n"); DebugPrintf(" save_game - Saves the current game state to the hard disk\n"); @@ -851,40 +851,56 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { return true; } -bool Console::cmdVerifyMidi(int argc, const char **argv) { - // TODO: Sometimes this goes out of bounds with some songs, as it misses - // the EOT signal -#if 0 +bool Console::cmdShowInstruments(int argc, const char **argv) { + int songNumber = -1; + + if (argc == 2) + songNumber = atoi(argv[1]); + SciVersion doSoundVersion = _engine->_features->detectDoSoundType(); MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion); MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion); parser->setMidiDriver(player); - + Common::List *resources = _engine->getResMan()->listResources(kResourceTypeSound); sort(resources->begin(), resources->end(), ResourceIdLess()); Common::List::iterator itr = resources->begin(); + int instruments[128]; + for (int i = 0; i < 128; i++) + instruments[i] = 0; - DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size()); + if (songNumber == -1) { + DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size()); + DebugPrintf("Instruments:\n"); + DebugPrintf("============\n"); + } SoundResource *sound; while (itr != resources->end()) { + if (songNumber >= 0 && itr->number != songNumber) { + ++itr; + continue; + } + sound = new SoundResource(itr->number, _engine->getResMan(), doSoundVersion); int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel()); SoundResource::Track *track = sound->getTrackByType(player->getPlayId()); if (track->digitalChannelNr != -1) { // Skip digitized sound effects delete sound; + ++itr; continue; } parser->loadMusic(track, NULL, channelFilterMask, doSoundVersion); const byte *channelData = parser->getMixedData(); - byte param1 = 0; - byte command = 0, prev = 0; - byte curEvent = 0; + byte curEvent = 0, prevEvent = 0, command = 0; bool endOfTrack = false; + bool firstOneShown = false; + + DebugPrintf("Song %d: ", itr->number); do { while (*channelData == 0xF8) @@ -895,36 +911,47 @@ bool Console::cmdVerifyMidi(int argc, const char **argv) { if ((*channelData & 0xF0) >= 0x80) curEvent = *(channelData++); else - curEvent = prev; + curEvent = prevEvent; if (curEvent < 0x80) continue; - prev = curEvent; + prevEvent = curEvent; command = curEvent >> 4; switch (command) { case 0xC: // program change - param1 = *channelData++; - // TODO: verify that the instrument is mapped - printf("Song %d, patch %d\n", itr->number, param1); + { + //byte channel = curEvent & 0x0F; + byte instrument = *channelData++; + if (!firstOneShown) + firstOneShown = true; + else + DebugPrintf(","); + + DebugPrintf(" %d", instrument); + instruments[instrument]++; + } break; case 0xD: + channelData++; // param1 + break; case 0xB: - param1 = *channelData++; + channelData++; // param1 + channelData++; // param2 break; case 0x8: case 0x9: case 0xA: case 0xE: - param1 = *channelData++; - *channelData++; // param2 + channelData++; // param1 + channelData++; // param2 break; case 0xF: if ((curEvent & 0x0F) == 0x2) { - param1 = *channelData++; - *channelData++; // param2 + channelData++; // param1 + channelData++; // param2 } else if ((curEvent & 0x0F) == 0x3) { - param1 = *channelData++; + channelData++; // param1 } else if ((curEvent & 0x0F) == 0xF) { // META byte type = *channelData++; if (type == 0x2F) {// end of track reached @@ -939,6 +966,8 @@ bool Console::cmdVerifyMidi(int argc, const char **argv) { } } while (!endOfTrack); + DebugPrintf("\n"); + delete sound; ++itr; } @@ -946,8 +975,16 @@ bool Console::cmdVerifyMidi(int argc, const char **argv) { delete parser; delete player; - DebugPrintf("Music check finished\n"); -#endif + DebugPrintf("\n"); + + if (songNumber == -1) { + DebugPrintf("Used instruments: "); + for (int i = 0; i < 128; i++) { + if (instruments[i] > 0) + DebugPrintf("%d, ", i); + } + DebugPrintf("\n\n"); + } return true; } diff --git a/engines/sci/console.h b/engines/sci/console.h index 572a62c274..5f3b0e3951 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -74,7 +74,7 @@ private: bool cmdList(int argc, const char **argv); bool cmdHexgrep(int argc, const char **argv); bool cmdVerifyScripts(int argc, const char **argv); - bool cmdVerifyMidi(int argc, const char **argv); + bool cmdShowInstruments(int argc, const char **argv); // Game bool cmdSaveGame(int argc, const char **argv); bool cmdRestoreGame(int argc, const char **argv); -- cgit v1.2.3 From b97d7adc3b43c648e56738fc6e43736a74248961 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 12 Jun 2010 09:29:28 +0000 Subject: Extended show_instruments to show the songs where each instrument is used in svn-id: r49603 --- engines/sci/console.cpp | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 9d713cd2dd..bd597aaa19 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -866,9 +866,15 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { sort(resources->begin(), resources->end(), ResourceIdLess()); Common::List::iterator itr = resources->begin(); int instruments[128]; + bool instrumentsSongs[128][1000]; + for (int i = 0; i < 128; i++) instruments[i] = 0; + for (int i = 0; i < 128; i++) + for (int j = 0; j < 1000; j++) + instrumentsSongs[i][j] = false; + if (songNumber == -1) { DebugPrintf("%d sounds found, checking their instrument mappings...\n", resources->size()); DebugPrintf("Instruments:\n"); @@ -930,6 +936,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { DebugPrintf(" %d", instrument); instruments[instrument]++; + instrumentsSongs[instrument][itr->number] = true; } break; case 0xD: @@ -984,6 +991,20 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { DebugPrintf("%d, ", i); } DebugPrintf("\n\n"); + + DebugPrintf("Used instruments in songs:\n"); + for (int i = 0; i < 128; i++) { + if (instruments[i] > 0) { + DebugPrintf("Instrument %d: ", i); + for (int j = 0; j < 1000; j++) { + if (instrumentsSongs[i][j]) + DebugPrintf("%d, ", j); + } + DebugPrintf("\n"); + } + } + + DebugPrintf("\n\n"); } return true; -- cgit v1.2.3 From 277a700e6743b481eba8efb86fe37c339d880279 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 12 Jun 2010 11:32:28 +0000 Subject: Reimplemented the scaled sprite drawing logic. The first introduction sequence scene now displays correctly svn-id: r49604 --- engines/m4/graphics.cpp | 190 ++++++++++++++++++++++++++++++++++-------------- 1 file changed, 137 insertions(+), 53 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index dd18972eec..fc5cb0f9f9 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -401,41 +401,33 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest */ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthsSurface, int scale, int transparentColour) { - /* TODO: This isn't a straight re-implementation of the original draw routine. Double check in future - * whether this implementation provides equivalent functionality - */ - Common::Rect copyRect(0, 0, src->width(), src->height()); - if (destX < 0) { - copyRect.left += -destX; - destX = 0; - } else if (destX + copyRect.width() > w) { - copyRect.right -= destX + copyRect.width() - w; - } - if (destY < 0) { - copyRect.top += -destY; - destY = 0; - } else if (destY + copyRect.height() > h) { - copyRect.bottom -= destY + copyRect.height() - h; - } - - if (!copyRect.isValidRect()) - return; + if (scale == 100) { + // Copy the specified area + Common::Rect copyRect(0, 0, src->width(), src->height()); + + if (destX < 0) { + copyRect.left += -destX; + destX = 0; + } else if (destX + copyRect.width() > w) { + copyRect.right -= destX + copyRect.width() - w; + } + if (destY < 0) { + copyRect.top += -destY; + destY = 0; + } else if (destY + copyRect.height() > h) { + copyRect.bottom -= destY + copyRect.height() - h; + } - if (scale != 100) { - destX -= (src->width() * scale / 100) / 2; - destY -= (src->height() * scale / 100); - } + if (!copyRect.isValidRect()) + return; - // Copy the specified area + byte *data = src->getBasePtr(); + byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); + byte *depthsData = depthsSurface->getBasePtr(); + byte *depthsPtr = depthsData + (src->width() * copyRect.top + copyRect.left); + byte *destPtr = (byte *)pixels + (destY * width()) + destX; - byte *data = src->getBasePtr(); - byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); - byte *depthsData = depthsSurface->getBasePtr(); - byte *depthsPtr = depthsData + (src->width() * copyRect.top + copyRect.left); - byte *destPtr = (byte *)pixels + (destY * width()) + destX; - - if (scale == 100) { // 100% scaling variation for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { // Copy each byte one at a time checking against the depth @@ -448,35 +440,127 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf depthsPtr += depthsSurface->width(); destPtr += width(); } - } else { - // Scaled variation - int currY = -1; - for (int rowCtr = 0, yTotal = 0; rowCtr < copyRect.height(); ++rowCtr, yTotal += scale, - srcPtr += src->width(), depthsPtr += depthsSurface->width()) { - int srcY = yTotal / 100; - if (srcY == currY) + src->freeData(); + depthsSurface->freeData(); + return; + } + + // Start of draw logic for scaled sprites + const byte *srcPixelsP = src->getBasePtr(); + + int destRight = this->width() - 1; + int destBottom = this->height() - 1; + bool normalFrame = true; // TODO: false for negative frame numbers + int frameWidth = src->width(); + int frameHeight = src->height(); + + int highestDim = MAX(frameWidth, frameHeight); + bool lineDist[MADS_SURFACE_WIDTH]; + int distIndex = 0; + int distXCount = 0, distYCount = 0; + + int distCtr = 0; + do { + distCtr += scale; + if (distCtr < 100) { + lineDist[distIndex] = false; + } else { + lineDist[distIndex] = true; + distCtr -= 100; + + if (distIndex < frameWidth) + ++distXCount; + + if (distIndex < frameHeight) + ++distYCount; + } + } while (++distIndex < highestDim); + + destX -= distXCount / 2; + destY -= distYCount - 1; + + // Check x bounding area + int spriteLeft = 0; + int spriteWidth = distXCount; + int widthAmount = destX + distXCount - 1; + + if (destX < 0) { + spriteWidth += destX; + spriteLeft -= destX; + } + widthAmount -= destRight; + if (widthAmount > 0) + spriteWidth -= widthAmount; + + int spriteRight = spriteLeft + spriteWidth; + if (spriteWidth <= 0) + return; + if (!normalFrame) { + destX += distXCount - 1; + spriteLeft = -(distXCount - spriteRight); + spriteRight = (-spriteLeft + spriteWidth); + } + + // Check y bounding area + int spriteTop = 0; + int spriteHeight = distYCount; + int heightAmount = destY + distYCount - 1; + + if (destY < 0) { + spriteHeight += destY; + spriteTop -= destY; + } + heightAmount -= destBottom; + if (heightAmount > 0) + spriteHeight -= heightAmount; + int spriteBottom = spriteTop + spriteHeight; + + if (spriteHeight <= 0) + return; + + byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); + const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop); + + spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); + + // Loop through the lines of the sprite + for (int yp = 0, sprY = -1; yp < frameHeight; ++yp, srcPixelsP += src->pitch) { + if (!lineDist[yp]) + // Not a display line, so skip it + continue; + // Check whether the sprite line is in the display range + ++sprY; + if ((sprY >= spriteBottom) || (sprY < spriteTop)) + continue; + + // Found a line to display. Loop through the pixels + const byte *srcP = srcPixelsP; + const byte *depthP = depthPixelsP; + byte *destP = destPixelsP; + for (int xp = 0, sprX = 0; xp < frameWidth; ++xp, ++srcP) { + if (xp < spriteLeft) + // Not yet reached start of display area + continue; + if (!lineDist[sprX++]) + // Not a display pixel continue; - currY = srcY; - - // Loop through the source pixels - int currX = -1; - byte *destP = destPtr; - for (int xCtr = 0, xTotal = 0; xCtr < copyRect.width(); ++xCtr, xTotal += scale) { - int srcX = xTotal / 100; - if (srcX == currX) - continue; - currX = srcX; - - if ((depthsPtr[currX] > depth) && (srcPtr[xCtr] != transparentColour)) - *destP++ = srcPtr[xCtr]; - } - destPtr += width(); + if (depth <= *depthP) + *destP = *srcP; + + ++destP; + ++depthP; } + + // Move to the next destination line + destPixelsP += this->pitch; + depthPixelsP += depthsSurface->pitch; } + src->freeData(); depthsSurface->freeData(); + this->freeData(); } void M4Surface::loadBackgroundRiddle(const char *sceneName) { -- cgit v1.2.3 From f4739f9f68026d5e3ea3304777260cef3101a031 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 12 Jun 2010 11:41:22 +0000 Subject: Added debug output to kDoAudio and some music commands. Also added a warning when an audio stream can't be created. Finally, the debug level of the MIDI parser debug output has been raised to 4, as it's too verbose svn-id: r49605 --- engines/sci/engine/ksound.cpp | 15 +++++++++++++-- engines/sci/sound/audio.cpp | 4 ++++ engines/sci/sound/midiparser_sci.cpp | 30 +++++++++++++++--------------- engines/sci/sound/soundcmd.cpp | 9 +++++++-- 4 files changed, 39 insertions(+), 19 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index ebfd6e6885..8cf9400353 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -119,6 +119,8 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } + debugC(2, kDebugLevelSound, "kDoAudio: play sample %d, module %d", number, module); + // return sample length in ticks if (argv[0].toUint16() == kSciAudioWPlay) return make_reg(0, g_sci->_audio->wPlayAudio(module, number)); @@ -126,31 +128,39 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { return make_reg(0, g_sci->_audio->startAudio(module, number)); } case kSciAudioStop: + debugC(2, kDebugLevelSound, "kDoAudio: stop"); g_sci->_audio->stopAudio(); break; case kSciAudioPause: + debugC(2, kDebugLevelSound, "kDoAudio: pause"); g_sci->_audio->pauseAudio(); break; case kSciAudioResume: + debugC(2, kDebugLevelSound, "kDoAudio: resume"); g_sci->_audio->resumeAudio(); break; case kSciAudioPosition: + //debugC(2, kDebugLevelSound, "kDoAudio: get position"); // too verbose return make_reg(0, g_sci->_audio->getAudioPosition()); case kSciAudioRate: + debugC(2, kDebugLevelSound, "kDoAudio: set audio rate to %d", argv[1].toUint16()); g_sci->_audio->setAudioRate(argv[1].toUint16()); break; case kSciAudioVolume: { int16 volume = argv[1].toUint16(); volume = CLIP(volume, 0, AUDIO_VOLUME_MAX); + debugC(2, kDebugLevelSound, "kDoAudio: set volume to %d", volume); mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); break; } case kSciAudioLanguage: // In SCI1.1: tests for digital audio support - if (getSciVersion() == SCI_VERSION_1_1) + if (getSciVersion() == SCI_VERSION_1_1) { + debugC(2, kDebugLevelSound, "kDoAudio: audio capability test"); return make_reg(0, 1); - else { + } else { int16 language = argv[1].toSint16(); + debugC(2, kDebugLevelSound, "kDoAudio: set language to %d", language); if (language != -1) g_sci->getResMan()->setAudioLanguage(language); @@ -162,6 +172,7 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { } break; case kSciAudioCD: + debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop"); return kDoCdAudio(s, argc - 1, argv + 1); // TODO: There are 3 more functions used in Freddy Pharkas (11, 12 and 13) and new within sierra sci // Details currently unknown diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 62cfcd9621..b0b9a73e00 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -69,6 +69,8 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { _wPlayFlag = false; _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); return sampleLen; + } else { + warning("startAudio: unable to create stream for audio number %d, module %d", number, module); } return 0; @@ -81,6 +83,8 @@ int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { int sampleLen = 0; Audio::AudioStream *audioStream = getAudioStream(module, tuple, &sampleLen); + if (!audioStream) + warning("wPlayAudio: unable to create stream for audio tuple %d, module %d", tuple, module); delete audioStream; _wPlayFlag = true; return sampleLen; diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index f852367bfe..bb353da780 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -148,12 +148,12 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { _dataincAdd = false; _pSnd->dataInc += _dataincToAdd; _pSnd->signal = 0x7f + _pSnd->dataInc; - debugC(2, kDebugLevelSound, "datainc %04x", _dataincToAdd); + debugC(4, kDebugLevelSound, "datainc %04x", _dataincToAdd); } if (_signalSet) { _signalSet = false; _pSnd->signal = _signalToSet; - debugC(2, kDebugLevelSound, "signal %04x", _signalToSet); + debugC(4, kDebugLevelSound, "signal %04x", _signalToSet); } info.start = _position._play_pos; @@ -313,7 +313,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { _pSnd->status = kSoundStopped; _pSnd->signal = SIGNAL_OFFSET; - debugC(2, kDebugLevelSound, "signal EOT"); + debugC(4, kDebugLevelSound, "signal EOT"); } } break; @@ -376,21 +376,21 @@ byte *MidiParser_SCI::midiMixChannels() { command = *channel->data++; if (command != kEndOfTrack) { - debugC(2, kDebugLevelSound, "\nDELTA "); + debugC(4, kDebugLevelSound, "\nDELTA "); // Write delta while (new_delta > 240) { *outData++ = 0xF8; - debugC(2, kDebugLevelSound, "F8 "); + debugC(4, kDebugLevelSound, "F8 "); new_delta -= 240; } *outData++ = (byte)new_delta; - debugC(2, kDebugLevelSound, "%02X ", (uint32)new_delta); + debugC(4, kDebugLevelSound, "%02X ", (uint32)new_delta); } // Write command switch (command) { case 0xF0: // sysEx *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); + debugC(4, kDebugLevelSound, "%02X ", command); do { par1 = *channel->data++; *outData++ = par1; // out @@ -478,22 +478,22 @@ byte *MidiParser_SCI::midiFilterChannels(int channelMask) { } if ((1 << curChannel) & channelMask) { if (command != kEndOfTrack) { - debugC(2, kDebugLevelSound, "\nDELTA "); + debugC(4, kDebugLevelSound, "\nDELTA "); // Write delta while (delta > 240) { *outData++ = 0xF8; - debugC(2, kDebugLevelSound, "F8 "); + debugC(4, kDebugLevelSound, "F8 "); delta -= 240; } *outData++ = (byte)delta; - debugC(2, kDebugLevelSound, "%02X ", delta); + debugC(4, kDebugLevelSound, "%02X ", delta); delta = 0; } // Write command switch (command) { case 0xF0: // sysEx *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); + debugC(4, kDebugLevelSound, "%02X ", command); do { curByte = *channelData++; *outData++ = curByte; // out @@ -507,20 +507,20 @@ byte *MidiParser_SCI::midiFilterChannels(int channelMask) { default: // MIDI command if (lastCommand != command) { *outData++ = command; - debugC(2, kDebugLevelSound, "%02X ", command); + debugC(4, kDebugLevelSound, "%02X ", command); lastCommand = command; } if (midiParamCount > 0) { if (curByte & 0x80) { - debugC(2, kDebugLevelSound, "%02X ", *channelData); + debugC(4, kDebugLevelSound, "%02X ", *channelData); *outData++ = *channelData++; } else { - debugC(2, kDebugLevelSound, "%02X ", curByte); + debugC(4, kDebugLevelSound, "%02X ", curByte); *outData++ = curByte; } } if (midiParamCount > 1) { - debugC(2, kDebugLevelSound, "%02X ", *channelData); + debugC(4, kDebugLevelSound, "%02X ", *channelData); *outData++ = *channelData++; } } diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 2bbc5b44de..71fc2b7ef0 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -307,6 +307,9 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); + debugC(2, kDebugLevelSound, "cmdInitSound, number %d, loop %d, prio %d, vol %d", resourceId, + newSound->loop, newSound->priority, newSound->volume); + // In SCI1.1 games, sound effects are started from here. If we can find // a relevant audio resource, play it, otherwise switch to synthesized // effects. If the resource exists, play it using map 65535 (sound @@ -423,8 +426,6 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { // Find slot again :) musicSlot = _music->getSlot(obj); } - int16 loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); - debugC(2, kDebugLevelSound, "cmdPlaySound: resource number %d, loop %d", resourceId, loop); writeSelector(_segMan, obj, SELECTOR(handle), obj); @@ -442,6 +443,10 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { musicSlot->priority = readSelectorValue(_segMan, obj, SELECTOR(priority)); if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); + + debugC(2, kDebugLevelSound, "cmdPlaySound, number %d, loop %d, prio %d, vol %d", resourceId, + musicSlot->loop, musicSlot->priority, musicSlot->volume); + _music->soundPlay(musicSlot); #endif -- cgit v1.2.3 From 6fa4d1ba805237cd44f6c64cf1088988c5d652f8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 12 Jun 2010 11:43:30 +0000 Subject: Initialize compression-related variables when loading external patch files. Fixes Cassima's speech in the intro of KQ6 (the engine thought that the external patch files of her speech were compressed) svn-id: r49606 --- engines/sci/resource.cpp | 4 ++++ engines/sci/resource_audio.cpp | 2 ++ 2 files changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 0b7badb8f7..05aae0a39e 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1230,6 +1230,8 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; psrcPatch->resourceFile = 0; + psrcPatch->audioCompressionType = 0; + psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); } } @@ -1281,6 +1283,8 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; psrcPatch->resourceFile = 0; + psrcPatch->audioCompressionType = 0; + psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, (ResourceType)i, resourceNr); } } diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 861866edc0..0e60239331 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -158,6 +158,8 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { psrcPatch->source_type = kSourcePatch; psrcPatch->resourceFile = 0; psrcPatch->location_name = gmPatchFile; + psrcPatch->audioCompressionType = 0; + psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, kResourceTypePatch, 4); } } -- cgit v1.2.3 From 0492bd6aa65fa931bb84bb994f9e9e9757acc90a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 12 Jun 2010 18:20:22 +0000 Subject: SAGA: Music code cleanup. The music driver is now placed inside the MusicPlayer class, instead of the SagaEngine class. Split the functionality that the music parser should handle from the functionality that the music driver should handle. Also, fixed a bug in MusicDriver::send() (the notes off signal was sent to unallocated channels, not allocated ones) svn-id: r49607 --- engines/saga/music.cpp | 272 +++++++++++++++++++------------------------------ engines/saga/music.h | 52 ++++------ engines/saga/saga.cpp | 16 +-- engines/saga/saga.h | 1 - 4 files changed, 123 insertions(+), 218 deletions(-) (limited to 'engines') diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 75c5cdffd7..f38e47dc48 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -42,19 +42,25 @@ namespace Saga { #define BUFFER_SIZE 4096 #define MUSIC_SUNSPOT 26 -MusicPlayer::MusicPlayer(MidiDriver *driver) : _parser(0), _driver(driver), _looping(false), _isPlaying(false), _passThrough(false), _isGM(false) { +MusicDriver::MusicDriver() : _isGM(false) { memset(_channel, 0, sizeof(_channel)); _masterVolume = 0; + _nativeMT32 = ConfMan.getBool("native_mt32"); + + _driverType = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = MidiDriver::createMidi(_driverType); + if (isMT32()) + _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + this->open(); } -MusicPlayer::~MusicPlayer() { - _driver->setTimerCallback(NULL, NULL); - stopMusic(); +MusicDriver::~MusicDriver() { this->close(); + delete _driver; } -void MusicPlayer::setVolume(int volume) { +void MusicDriver::setVolume(int volume) { volume = CLIP(volume, 0, 255); if (_masterVolume == volume) @@ -71,32 +77,7 @@ void MusicPlayer::setVolume(int volume) { } } -int MusicPlayer::open() { - // Don't ever call open without first setting the output driver! - if (!_driver) - return 255; - - int ret = _driver->open(); - if (ret) - return ret; - - _driver->setTimerCallback(this, &onTimer); - return 0; -} - -void MusicPlayer::close() { - stopMusic(); - if (_driver) - _driver->close(); - _driver = 0; -} - -void MusicPlayer::send(uint32 b) { - if (_passThrough) { - _driver->send(b); - return; - } - +void MusicDriver::send(uint32 b) { byte channel = (byte)(b & 0x0F); if ((b & 0xFFF0) == 0x07B0) { // Adjust volume changes by master volume @@ -104,71 +85,86 @@ void MusicPlayer::send(uint32 b) { _channelVolume[channel] = volume; volume = volume * _masterVolume / 255; b = (b & 0xFF00FFFF) | (volume << 16); - } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { + } else if ((b & 0xF0) == 0xC0 && !_isGM && !isMT32()) { + // Remap MT32 instruments to General Midi b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; - } - else if ((b & 0xFFF0) == 0x007BB0) { - //Only respond to All Notes Off if this channel - //has currently been allocated - if (_channel[b & 0x0F]) + } else if ((b & 0xFFF0) == 0x007BB0) { + // Only respond to All Notes Off if this channel + // has currently been allocated + if (!_channel[channel]) return; } if (!_channel[channel]) _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); - - if (_channel[channel]) + else _channel[channel]->send(b); } -void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { - // FIXME: The "elkfanfare" is played much too quickly. There are some - // meta events that we don't handle. Perhaps there is a - // connection...? - - switch (type) { - case 0x2F: // End of Track - if (_looping) - _parser->jumpToTick(0); - else - stopMusic(); - break; - default: - //warning("Unhandled meta event: %02x", type); - break; - } -} - -void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; - Common::StackLock lock(music->_mutex); - - if (music->_isPlaying) - music->_parser->onTimer(); -} - -void MusicPlayer::playMusic() { - _isPlaying = true; -} +Music::Music(SagaEngine *vm, Audio::Mixer *mixer) : _vm(vm), _mixer(mixer) { + _currentVolume = 0; + _driver = new MusicDriver(); -void MusicPlayer::stopMusic() { - Common::StackLock lock(_mutex); + _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE); + if (!_driver->isAdlib()) + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_GM); + else + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM); - _isPlaying = false; - if (_parser) { - _parser->unloadMusic(); - _parser = NULL; + if (!_musicContext) { + if (_vm->getGameId() == GID_ITE) { + _musicContext = _vm->_resource->getContext(GAME_RESOURCEFILE); + } 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. + // Note that the IHNM demo has only got one music file + // (music.rsc). It is assumed that it contains FM music + _musicContext = _vm->_resource->getContext(GAME_MUSICFILE_FM); + } } -} -Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), _mixer(mixer), _adlib(false) { - _player = new MusicPlayer(driver); - _currentVolume = 0; - - xmidiParser = MidiParser::createParser_XMIDI(); - smfParser = MidiParser::createParser_SMF(); + // Check if the game is using XMIDI or SMF music + if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { + // Just set an XMIDI parser for Mac IHNM for now + _parser = MidiParser::createParser_XMIDI(); + } else { + byte *resourceData; + size_t resourceSize; + int resourceId = (_vm->getGameId() == GID_ITE ? 9 : 0); + _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); + if (!memcmp(resourceData, "FORM", 4)) { + _parser = MidiParser::createParser_XMIDI(); + // ITE had MT32 mapped instruments + _driver->setGM(_vm->getGameId() != GID_ITE); + } else { + _parser = MidiParser::createParser_SMF(); + } + free(resourceData); + } - _digitalMusicContext = _vm->_resource->getContext(GAME_DIGITALMUSICFILE); + _parser->setMidiDriver(_driver); + _parser->setTimerRate(_driver->getBaseTempo()); + _parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); _songTableLen = 0; _songTable = 0; @@ -180,11 +176,11 @@ Music::Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver) : _vm(vm), Music::~Music() { _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); _mixer->stopHandle(_musicHandle); - delete _player; - xmidiParser->setMidiDriver(NULL); - smfParser->setMidiDriver(NULL); - delete xmidiParser; - delete smfParser; + _driver->setTimerCallback(NULL, NULL); + _driver->close(); + delete _driver; + _parser->setMidiDriver(NULL); + delete _parser; free(_songTable); free(_midiMusicData); @@ -194,6 +190,12 @@ void Music::musicVolumeGaugeCallback(void *refCon) { ((Music *)refCon)->musicVolumeGauge(); } +void Music::onTimer(void *refCon) { + Music *music = (Music *)refCon; + Common::StackLock lock(music->_driver->_mutex); + music->_parser->onTimer(); +} + void Music::musicVolumeGauge() { int volume; @@ -209,7 +211,7 @@ void Music::musicVolumeGauge() { volume = 1; _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); - _player->setVolume(volume); + _driver->setVolume(volume); if (_currentVolumePercent == 100) { _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); @@ -226,7 +228,7 @@ void Music::setVolume(int volume, int time) { if (time == 1) { _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); - _player->setVolume(volume); + _driver->setVolume(volume); _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); _currentVolume = volume; return; @@ -236,13 +238,11 @@ void Music::setVolume(int volume, int time) { } bool Music::isPlaying() { - return _mixer->isSoundHandleActive(_musicHandle) || _player->isPlaying(); + return _mixer->isSoundHandleActive(_musicHandle) || _parser->isPlaying(); } void Music::play(uint32 resourceId, MusicFlags flags) { Audio::SeekableAudioStream *audioStream = NULL; - MidiParser *parser; - ResourceContext *context = NULL; byte *resourceData; size_t resourceSize; uint32 loopStart; @@ -254,8 +254,8 @@ void Music::play(uint32 resourceId, MusicFlags flags) { } _trackNumber = resourceId; - _player->stopMusic(); _mixer->stopHandle(_musicHandle); + _parser->unloadMusic(); int realTrackNumber; @@ -356,55 +356,10 @@ void Music::play(uint32 resourceId, MusicFlags flags) { return; } - if (flags == MUSIC_DEFAULT) { + if (flags == MUSIC_DEFAULT) flags = MUSIC_NORMAL; - } // Load MIDI/XMI resource data - - if (_vm->getGameId() == GID_ITE) { - context = _vm->_resource->getContext(GAME_MUSICFILE_GM); - if (context == NULL) { - context = _vm->_resource->getContext(GAME_RESOURCEFILE); - } - } else if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { - // The music of the Mac version of IHNM is loaded from its - // associated external file later on - } 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. - // Note that the IHNM demo has only got one music file - // (music.rsc). It is assumed that it contains FM music - - if (hasAdLib() || _vm->isIHNMDemo()) { - context = _vm->_resource->getContext(GAME_MUSICFILE_FM); - } else { - context = _vm->_resource->getContext(GAME_MUSICFILE_GM); - } - } - - _player->setGM(true); - if (_vm->getGameId() == GID_IHNM && _vm->isMacResources()) { // Load the external music file for Mac IHNM #if 0 @@ -422,56 +377,39 @@ void Music::play(uint32 resourceId, MusicFlags flags) { #endif return; } else { - _vm->_resource->loadResource(context, resourceId, resourceData, resourceSize); + _vm->_resource->loadResource(_musicContext, resourceId, resourceData, resourceSize); } if (resourceSize < 4) { error("Music::play() wrong music resource size"); } - if (xmidiParser->loadMusic(resourceData, resourceSize)) { - if (_vm->getGameId() == GID_ITE) - _player->setGM(false); + if (!_parser->loadMusic(resourceData, resourceSize)) + error("Music::play() wrong music resource"); - parser = xmidiParser; - } else { - if (smfParser->loadMusic(resourceData, resourceSize)) { - parser = smfParser; - } else { - error("Music::play() wrong music resource"); - } - } - - parser->setTrack(0); - parser->setMidiDriver(_player); - parser->setTimerRate(_player->getBaseTempo()); - parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + _parser->setTrack(0); + _driver->setTimerCallback(this, &onTimer); - _player->_parser = parser; setVolume(_vm->_musicVolume); - if (flags & MUSIC_LOOP) - _player->setLoop(true); - else - _player->setLoop(false); + // Handle music looping + _parser->property(MidiParser::mpAutoLoop, (flags & MUSIC_LOOP) ? 1 : 0); - _player->playMusic(); free(_midiMusicData); _midiMusicData = resourceData; } void Music::pause() { - _player->setVolume(-1); - _player->setPlaying(false); + _driver->setTimerCallback(NULL, NULL); } void Music::resume() { - _player->setVolume(_vm->_musicVolume); - _player->setPlaying(true); + _driver->setTimerCallback(this, &onTimer); } void Music::stop() { - _player->stopMusic(); + _driver->setTimerCallback(NULL, NULL); + _parser->unloadMusic(); } } // End of namespace Saga diff --git a/engines/saga/music.h b/engines/saga/music.h index 22711ba167..cb068cd835 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -44,41 +44,32 @@ enum MusicFlags { MUSIC_DEFAULT = 0xffff }; -class MusicPlayer : public MidiDriver { +class MusicDriver : public MidiDriver { public: - MusicPlayer(MidiDriver *driver); - ~MusicPlayer(); - - bool isPlaying() { return _isPlaying; } - void setPlaying(bool playing) { _isPlaying = playing; } + MusicDriver(); + ~MusicDriver(); void setVolume(int volume); int getVolume() { return _masterVolume; } - void setNativeMT32(bool b) { _nativeMT32 = b; } - bool hasNativeMT32() { return _nativeMT32; } - void playMusic(); - void stopMusic(); - void setLoop(bool loop) { _looping = loop; } - void setPassThrough(bool b) { _passThrough = b; } - + bool isAdlib() { return _driverType == MD_ADLIB; } + bool isMT32() { return _driverType == MD_MT32 || _nativeMT32; } void setGM(bool isGM) { _isGM = isGM; } //MidiDriver interface implementation - int open(); - void close(); + int open() { return _driver->open(); } + void close() { _driver->close(); } void send(uint32 b); - void metaEvent(byte type, byte *data, uint16 length); + void metaEvent(byte type, byte *data, uint16 length) {} - void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } - uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; } + void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { _driver->setTimerCallback(timerParam, timerProc); } + uint32 getBaseTempo() { return _driver->getBaseTempo(); } //Channel allocation functions MidiChannel *allocateChannel() { return 0; } MidiChannel *getPercussionChannel() { return 0; } - MidiParser *_parser; Common::Mutex _mutex; protected: @@ -87,14 +78,11 @@ protected: MidiChannel *_channel[16]; MidiDriver *_driver; + MidiDriverType _driverType; byte _channelVolume[16]; - bool _nativeMT32; bool _isGM; - bool _passThrough; + bool _nativeMT32; - bool _isPlaying; - bool _looping; - bool _randomLoop; byte _masterVolume; byte *_musicData; @@ -105,13 +93,8 @@ protected: class Music { public: - Music(SagaEngine *vm, Audio::Mixer *mixer, MidiDriver *driver); + Music(SagaEngine *vm, Audio::Mixer *mixer); ~Music(); - void setNativeMT32(bool b) { _player->setNativeMT32(b); } - bool hasNativeMT32() { return _player->hasNativeMT32(); } - void setAdLib(bool b) { _adlib = b; } - bool hasAdLib() { return _adlib; } - void setPassThrough(bool b) { _player->setPassThrough(b); } bool isPlaying(); bool hasDigitalMusic() { return _digitalMusic; } @@ -130,24 +113,23 @@ private: SagaEngine *_vm; Audio::Mixer *_mixer; - MusicPlayer *_player; + MusicDriver *_driver; Audio::SoundHandle _musicHandle; uint32 _trackNumber; - bool _adlib; - int _targetVolume; int _currentVolume; int _currentVolumePercent; bool _digitalMusic; + ResourceContext *_musicContext; ResourceContext *_digitalMusicContext; - MidiParser *xmidiParser; - MidiParser *smfParser; + MidiParser *_parser; byte *_midiMusicData; static void musicVolumeGaugeCallback(void *refCon); + static void onTimer(void *refCon); void musicVolumeGauge(); }; diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index ed8a9055ba..446ab86228 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -83,7 +83,6 @@ SagaEngine::SagaEngine(OSystem *syst, const SAGAGameDescription *gameDesc) _sndRes = NULL; _sound = NULL; _music = NULL; - _driver = NULL; _anim = NULL; _render = NULL; _isoMap = NULL; @@ -198,9 +197,6 @@ SagaEngine::~SagaEngine() { delete _sound; _sound = NULL; - delete _driver; - _driver = NULL; - delete _gfx; _gfx = NULL; @@ -285,17 +281,7 @@ Common::Error SagaEngine::run() { _console = new Console(this); // Graphics should be initialized before music - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - bool adlib = (midiDriver == MD_ADLIB); - - _driver = MidiDriver::createMidi(midiDriver); - if (native_mt32) - _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - - _music = new Music(this, _mixer, _driver); - _music->setNativeMT32(native_mt32); - _music->setAdLib(adlib); + _music = new Music(this, _mixer); _render = new Render(this, _system); if (!_render->initialized()) { return Common::kUnknownError; diff --git a/engines/saga/saga.h b/engines/saga/saga.h index 2bef489e05..102d1e5c82 100644 --- a/engines/saga/saga.h +++ b/engines/saga/saga.h @@ -525,7 +525,6 @@ public: SndRes *_sndRes; Sound *_sound; Music *_music; - MidiDriver *_driver; Anim *_anim; Render *_render; IsoMap *_isoMap; -- cgit v1.2.3 From 2625c9b20be6ed4bef0fd8da600729a7316d7ac4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 12 Jun 2010 23:53:26 +0000 Subject: Applied fix for checking unallocated channels for All Notes Off MIDI command svn-id: r49613 --- engines/m4/midi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/midi.cpp b/engines/m4/midi.cpp index 78fe0d6bd6..2c767fdf5a 100644 --- a/engines/m4/midi.cpp +++ b/engines/m4/midi.cpp @@ -109,7 +109,7 @@ void MidiPlayer::send(uint32 b) { else if ((b & 0xFFF0) == 0x007BB0) { //Only respond to All Notes Off if this channel //has currently been allocated - if (_channel[b & 0x0F]) + if (!_channel[b & 0x0F]) return; } -- cgit v1.2.3 From 0659d5f2448cbea343d294146ba20f656f759f42 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 06:55:24 +0000 Subject: Improved debug output of BRA walk code. svn-id: r49618 --- engines/parallaction/walk.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 8fc916e490..4468a7a678 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -450,7 +450,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { Common::Point foot; s._a->getFoot(foot); - debugC(1, kDebugWalk, "buildPath: from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y); + debugC(1, kDebugWalk, "buildPath: try to build path from (%i, %i) to (%i, %i)", foot.x, foot.y, x, y); s._walkPath.clear(); // look for easy path first @@ -465,13 +465,13 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { ZonePtr z0 = _vm->hitZone(kZonePath, x, y); if (!z0) { s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: corner case 0"); + debugC(3, kDebugWalk, "buildPath: corner case 0 (%i nodes)", s._walkPath.size()); return; } ZonePtr z1 = _vm->hitZone(kZonePath, foot.x, foot.y); if (!z1 || z1 == z0) { s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: corner case 1"); + debugC(3, kDebugWalk, "buildPath: corner case 1 (%i nodes)", s._walkPath.size()); return; } @@ -480,7 +480,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { if (z1->u._pathLists[id].empty()) { s._walkPath.clear(); - debugC(3, kDebugWalk, "buildPath: no path"); + debugC(3, kDebugWalk, "buildPath: no path found"); return; } @@ -490,7 +490,7 @@ void PathWalker_BR::buildPath(State &s, uint16 x, uint16 y) { s._walkPath.push_front(*b); } s._walkPath.push_back(dest); - debugC(3, kDebugWalk, "buildPath: complex path"); + debugC(3, kDebugWalk, "buildPath: complex path (%i nodes)", s._walkPath.size()); } @@ -541,8 +541,6 @@ void PathWalker_BR::walk() { return; } - debugC(3, kDebugWalk, "PathWalker_BR::walk()"); - doWalk(_character); doWalk(_follower); @@ -566,8 +564,6 @@ void PathWalker_BR::walk() { } _vm->_gfx->initiateScroll(dx, dy); - - debugC(3, kDebugWalk, "PathWalker_BR::walk() -> done"); } void PathWalker_BR::checkTrap(const Common::Point &p) { @@ -601,8 +597,6 @@ void PathWalker_BR::doWalk(State &s) { return; } - debugC(3, kDebugWalk, "PathWalker_BR::doWalk(%s)", s._a->_name); - if (s._walkDelay > 0) { s._walkDelay--; if (s._walkDelay == 0 && s._a->_scriptName) { @@ -619,10 +613,10 @@ void PathWalker_BR::doWalk(State &s) { if (s._walkPath.empty()) { finalizeWalk(s); - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 0"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, walk completed (no more nodes)"); return; } else { - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, moving to next node"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, reached a walkpath node, %i left", s._walkPath.size()); } } @@ -714,7 +708,7 @@ void PathWalker_BR::doWalk(State &s) { Common::Point p2; s._a->getFoot(p2); checkTrap(p2); - debugC(3, kDebugWalk, "PathWalker_BR::doWalk, case 1"); + debugC(3, kDebugWalk, "PathWalker_BR::doWalk, stepped to (%i, %i)", p2.x, p2.y); return; } -- cgit v1.2.3 From 3cacd7bc4372dbaae5c454236b4413ab87955347 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 06:55:40 +0000 Subject: Keep the balloon from getting stuck in an infinite loop when floating near the borders of the screen. See the detailed explanation in walk.cpp. svn-id: r49619 --- engines/parallaction/walk.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/parallaction/walk.cpp b/engines/parallaction/walk.cpp index 4468a7a678..d6df23d415 100644 --- a/engines/parallaction/walk.cpp +++ b/engines/parallaction/walk.cpp @@ -626,6 +626,19 @@ void PathWalker_BR::doWalk(State &s) { int xStep = (scale * 16) / 100 + 1; int yStep = (scale * 10) / 100 + 1; + + /* WORKAROUND: in the balloon scene, the position of the balloon (which is implemented as a + Character) is controlled by the user (for movement, via this walking code) and by the scripts + (to simulate the balloon floating in the air, in a neverending loop that alters the position + coordinates). + When the two step sizes are equal in magnitude and opposite in direction, then the walk code + enters an infinite loop without giving control back to the user (this happens quite frequently + when navigating the balloon near the borders of the screen, where the calculated step is + forcibly small because of clipping). Since the "floating" script (part1/scripts/mongolo.scr) + uses increments of 3 for both x and y, we tweak the calculated steps accordingly here. */ + if (xStep == 3) xStep--; + if (yStep == 3) yStep--; + debugC(9, kDebugWalk, "calculated step: (%i, %i)", xStep, yStep); s._fieldC = 0; -- cgit v1.2.3 From d16eb491b17e662705e80d14c1f2ebe5f4e38cef Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 06:55:58 +0000 Subject: Support for vertical scrolling. Patch 3005933 by fuzzie. svn-id: r49620 --- engines/parallaction/gfxbase.cpp | 4 +++- engines/parallaction/graphics.cpp | 8 ++++++-- 2 files changed, 9 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index fc6cb28d9e..835bb204b4 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -222,10 +222,12 @@ void Gfx::drawGfxObject(GfxObj *obj, Graphics::Surface &surf) { obj->getRect(obj->frame, rect); int x = obj->x; + int y = obj->y; if (_overlayMode) { x += _scrollPosX; + y += _scrollPosY; } - rect.translate(x, obj->y); + rect.translate(x, y); data = obj->getData(obj->frame); if (obj->getSize(obj->frame) == obj->getRawSize(obj->frame)) { diff --git a/engines/parallaction/graphics.cpp b/engines/parallaction/graphics.cpp index bc1759ecd7..2990d024d2 100644 --- a/engines/parallaction/graphics.cpp +++ b/engines/parallaction/graphics.cpp @@ -317,8 +317,10 @@ void Gfx::drawList(Graphics::Surface &surface, GfxObjArray &list) { void Gfx::copyRectToScreen(const byte *buf, int pitch, int x, int y, int w, int h) { if (_doubleBuffering) { - if (_overlayMode) + if (_overlayMode) { x += _scrollPosX; + y += _scrollPosY; + } byte *dst = (byte*)_backBuffer.getBasePtr(x, y); for (int i = 0; i < h; i++) { @@ -358,7 +360,7 @@ void Gfx::unlockScreen() { void Gfx::updateScreenIntern() { if (_doubleBuffering) { - byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, 0); + byte *data = (byte*)_backBuffer.getBasePtr(_scrollPosX, _scrollPosY); _vm->_system->copyRectToScreen(data, _backBuffer.pitch, 0, 0, _vm->_screenWidth, _vm->_screenHeight); } @@ -863,6 +865,8 @@ void Gfx::setBackground(uint type, BackgroundInfo *info) { _minScrollX = 0; _maxScrollX = MAX(0, _backgroundInfo->width - _vm->_screenWidth); + _minScrollY = 0; + _maxScrollY = MAX(0, _backgroundInfo->height - _vm->_screenHeight); } -- cgit v1.2.3 From 94cdfefe1c9c32b3497d8d1564d4e5e0940dc403 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 06:56:13 +0000 Subject: Fixed clipping when drawing sprites at small scale factors (this fixes the balloon scene). svn-id: r49621 --- engines/parallaction/gfxbase.cpp | 56 ++++++++++++++++++++++++++++------------ 1 file changed, 40 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/gfxbase.cpp b/engines/parallaction/gfxbase.cpp index 835bb204b4..a1926fc197 100644 --- a/engines/parallaction/gfxbase.cpp +++ b/engines/parallaction/gfxbase.cpp @@ -283,30 +283,54 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur return; } - Common::Rect q(r); - Common::Rect clipper(surf->w, surf->h); - q.clip(clipper); - if (!q.isValidRect()) return; - - uint inc = r.width() * (100 - scale); - uint thr = r.width() * 100; - uint xAccum = 0, yAccum = 0; + // unscaled rectangle size + uint width = r.width(); + uint height = r.height(); + + // scaled rectangle size + uint scaledWidth = r.width() * scale / 100; + uint scaledHeight = r.height() * scale / 100; + + // scaled rectangle origin + uint scaledLeft = r.left + (width - scaledWidth) / 2; + uint scaledTop = r.top + (height - scaledHeight); + + // clipped scaled destination rectangle + Common::Rect dstRect(scaledWidth, scaledHeight); + dstRect.moveTo(scaledLeft, scaledTop); + + Common::Rect clipper(surf->w, surf->h); + dstRect.clip(clipper); + if (!dstRect.isValidRect()) return; + + + // clipped source rectangle + Common::Rect srcRect; + srcRect.left = (dstRect.left - scaledLeft) * 100 / scale; + srcRect.top = (dstRect.top - scaledTop) * 100 / scale; + srcRect.setWidth(dstRect.width() * 100 / scale); + srcRect.setHeight(dstRect.height() * 100 / scale); + if (!srcRect.isValidRect()) return; Common::Point dp; - dp.x = q.left + (r.width() * (100 - scale)) / 200; - dp.y = q.top + (r.height() * (100 - scale)) / 100; - q.translate(-r.left, -r.top); - byte *s = data + q.left + q.top * r.width(); + dp.x = dstRect.left; + dp.y = dstRect.top; + + byte *s = data + srcRect.left + srcRect.top * width; byte *d = (byte*)surf->getBasePtr(dp.x, dp.y); uint line = 0, col = 0; - for (uint16 i = 0; i < q.height(); i++) { + uint xAccum = 0, yAccum = 0; + uint inc = width * (100 - scale); + uint thr = width * 100; + + for (uint16 i = 0; i < srcRect.height(); i++) { yAccum += inc; if (yAccum >= thr) { yAccum -= thr; - s += r.width(); + s += width; continue; } @@ -314,7 +338,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur byte *d2 = d; col = 0; - for (uint16 j = 0; j < q.width(); j++) { + for (uint16 j = 0; j < srcRect.width(); j++) { xAccum += inc; if (xAccum >= thr) { @@ -337,7 +361,7 @@ void Gfx::bltMaskScale(const Common::Rect& r, byte *data, Graphics::Surface *sur col++; } - s += r.width() - q.width(); + s += width - srcRect.width(); d += surf->w; line++; } -- cgit v1.2.3 From eff1d4bb1c2e1a33946c7333c3d28f38dfdcb5e8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 13 Jun 2010 07:17:44 +0000 Subject: Added a default constructor for the ResourceSource struct svn-id: r49622 --- engines/sci/resource.cpp | 20 -------------------- engines/sci/resource.h | 9 +++++++++ 2 files changed, 9 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 05aae0a39e..1906510d24 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -174,9 +174,6 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volum newsrc->source_type = kSourceExtMap; newsrc->location_name = file_name; - newsrc->resourceFile = 0; - newsrc->scanned = false; - newsrc->associated_map = NULL; newsrc->volume_number = volume_nr; _sources.push_back(newsrc); @@ -189,8 +186,6 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i newsrc->source_type = kSourceExtMap; newsrc->location_name = mapFile->getName(); newsrc->resourceFile = mapFile; - newsrc->scanned = false; - newsrc->associated_map = NULL; newsrc->volume_number = volume_nr; _sources.push_back(newsrc); @@ -201,13 +196,9 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty ResourceSource *newsrc = new ResourceSource(); newsrc->source_type = type; - newsrc->scanned = false; newsrc->location_name = filename; - newsrc->resourceFile = 0; newsrc->volume_number = number; newsrc->associated_map = map; - newsrc->audioCompressionType = 0; - newsrc->audioCompressionOffsetMapping = NULL; if (type == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); @@ -219,13 +210,10 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty ResourceSource *newsrc = new ResourceSource(); newsrc->source_type = type; - newsrc->scanned = false; newsrc->location_name = resFile->getName(); newsrc->resourceFile = resFile; newsrc->volume_number = number; newsrc->associated_map = map; - newsrc->audioCompressionType = 0; - newsrc->audioCompressionOffsetMapping = NULL; if (type == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); @@ -237,8 +225,6 @@ ResourceSource *ResourceManager::addPatchDir(const char *dirname) { ResourceSource *newsrc = new ResourceSource(); newsrc->source_type = kSourceDirectory; - newsrc->resourceFile = 0; - newsrc->scanned = false; newsrc->location_name = dirname; _sources.push_back(newsrc); @@ -1229,9 +1215,6 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { psrcPatch = new ResourceSource; psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; - psrcPatch->resourceFile = 0; - psrcPatch->audioCompressionType = 0; - psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); } } @@ -1282,9 +1265,6 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { psrcPatch = new ResourceSource; psrcPatch->source_type = kSourcePatch; psrcPatch->location_name = name; - psrcPatch->resourceFile = 0; - psrcPatch->audioCompressionType = 0; - psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, (ResourceType)i, resourceNr); } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 66742f11f5..7fbb3ca9a2 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -133,6 +133,15 @@ struct ResourceSource { uint32 audioCompressionType; int32 *audioCompressionOffsetMapping; Common::MacResManager macResMan; + ResourceSource() { + source_type = kSourceDirectory; + scanned = false; + resourceFile = 0; + volume_number = 0; + associated_map = NULL; + audioCompressionType = 0; + audioCompressionOffsetMapping = NULL; + } }; class ResourceId { -- cgit v1.2.3 From d1993773880143d234f3355dd5a03f778e35b78c Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 07:35:48 +0000 Subject: When closing inventory, do not force input back to game-mode if commands need otherwise. svn-id: r49623 --- engines/parallaction/input.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/input.cpp b/engines/parallaction/input.cpp index d6dd9feb19..6d3f6f0b04 100644 --- a/engines/parallaction/input.cpp +++ b/engines/parallaction/input.cpp @@ -395,7 +395,7 @@ void Input::exitInventoryMode() { _vm->dropItem(z->u._mergeObj1); _vm->dropItem(z->u._mergeObj2); _vm->addInventoryItem(z->u._mergeObj3); - _vm->_cmdExec->run(z->_commands); + _vm->_cmdExec->run(z->_commands); // commands might set a new _inputMode } } @@ -412,7 +412,11 @@ void Input::exitInventoryMode() { } _vm->resumeJobs(); - _inputMode = kInputModeGame; + // in case the input mode was not changed by the code above (especially by the commands + // executed in case of a merge), then assume we are going back to game mode + if (_inputMode == kInputModeInventory) { + _inputMode = kInputModeGame; + } } bool Input::updateInventoryInput() { -- cgit v1.2.3 From 02ed880180a83a46ec72f69879df565f42c840db Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 13 Jun 2010 08:53:06 +0000 Subject: Added logic for handling the rate of animation background scrolling, and miscellaneous extra fields svn-id: r49627 --- engines/m4/animation.cpp | 36 +++++++++++++++++++++++------------- engines/m4/animation.h | 6 ++++++ 2 files changed, 29 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index adb802ee0e..cf2d201b81 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -44,6 +44,7 @@ MadsAnimation::MadsAnimation(MadsM4Engine *vm, MadsView *view): Animation(vm), _ _currentFrame = 0; _oldFrameEntry = 0; _nextFrameTimer = _madsVm->_currentTimer; + _nextScrollTimer = 0; } MadsAnimation::~MadsAnimation() { @@ -89,7 +90,8 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S _spriteListIndex = animStream->readUint16LE(); _scrollX = animStream->readSint16LE(); _scrollY = animStream->readSint16LE(); - animStream->skip(10); + _scrollTicks = animStream->readUint16LE(); + animStream->skip(8); animStream->read(buffer, 13); _interfaceFile = Common::String(buffer, 13); @@ -180,7 +182,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S for (int i = 0; i < miscEntriesCount; ++i) { AnimMiscEntry rec; rec.soundNum = animStream->readByte(); - animStream->skip(1); + rec.msgIndex = animStream->readSByte(); rec.numTicks = animStream->readUint16LE(); rec.posAdjust.x = animStream->readUint16LE(); rec.posAdjust.y = animStream->readUint16LE(); @@ -232,6 +234,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S int idx = _frameEntries[i].spriteSlot.spriteListIndex; _frameEntries[i].spriteSlot.spriteListIndex = _spriteListIndexes[idx]; } + + if (hasScroll()) + _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; } /** @@ -282,9 +287,24 @@ void MadsAnimation::update() { load1(newIndex); } + // Check for scroll change + bool screenChanged = false; + + // Handle any scrolling of the screen surface + if (hasScroll() && (_madsVm->_currentTimer >= _nextScrollTimer)) { + _view->_bgSurface->scrollX(_scrollX); + _view->_bgSurface->scrollY(_scrollY); + + _nextScrollTimer = _madsVm->_currentTimer + _scrollTicks; + screenChanged = true; + } + // If it's not time for the next frame, then exit - if (_madsVm->_currentTimer < _nextFrameTimer) + if (_madsVm->_currentTimer < _nextFrameTimer) { + if (screenChanged) + _view->_spriteSlots.fullRefresh(); return; + } // Loop checks for any prior animation sprite slots to be expired for (int slotIndex = 0; slotIndex < _view->_spriteSlots.startIndex; ++slotIndex) { @@ -311,16 +331,6 @@ void MadsAnimation::update() { if (misc.soundNum) _vm->_sound->playSound(misc.soundNum); - bool screenChanged = false; - - // Handle any scrolling of the screen surface - if ((_scrollX != 0) || (_scrollY != 0)) { - _view->_bgSurface->scrollX(_scrollX); - _view->_bgSurface->scrollY(_scrollY); - - screenChanged = true; - } - // Handle any offset adjustment for sprites as of this frame if (_view->_posAdjust.x != misc.posAdjust.x) { misc.posAdjust.x = _view->_posAdjust.x; diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 029cf45738..cffcf9f689 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -57,6 +57,7 @@ public: class AnimMiscEntry { public: int soundNum; + int msgIndex; int numTicks; Common::Point posAdjust; }; @@ -82,6 +83,7 @@ private: int _spriteListIndex; int _scrollX; int _scrollY; + int _scrollTicks; Common::String _interfaceFile; Common::String _spriteSetNames[10]; Common::String _lbmFilename; @@ -96,14 +98,17 @@ private: int _unkIndex; Common::Point _unkList[2]; uint32 _nextFrameTimer; + uint32 _nextScrollTimer; int _messageCtr; int _abortTimers; AbortTimerMode _abortMode; uint16 _actionNouns[3]; + void load1(int frameNumber); bool proc1(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber); void loadInterface(M4Surface *&interfaceSurface, M4Surface *&depthSurface); + bool hasScroll() const { return (_scrollX != 0) || (_scrollY != 0); } public: MadsAnimation(MadsM4Engine *vm, MadsView *view); virtual ~MadsAnimation(); @@ -114,6 +119,7 @@ public: virtual void setCurrentFrame(int frameNumber); bool freeFlag() const { return _freeFlag; } + bool getAnimMode() const { return _animMode; } int roomNumber() const { return _roomNumber; } }; -- cgit v1.2.3 From 466479eb77dfd04c7116f97f93e2f8013442307b Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 13 Jun 2010 09:07:15 +0000 Subject: Added a parser for kZoneNone zones/animations in BRA. The only thing it does is parsing a possible command list, which is enough to support the script bug in "scende2". See ticket #3005384. svn-id: r49628 --- engines/parallaction/parser.h | 1 + engines/parallaction/parser_br.cpp | 13 +++++++++++-- 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parser.h b/engines/parallaction/parser.h index 3e46e99180..5eb26e9fa1 100644 --- a/engines/parallaction/parser.h +++ b/engines/parallaction/parser.h @@ -294,6 +294,7 @@ public: virtual void parseGetData(ZonePtr z); virtual void parseDoorData(ZonePtr z); virtual void parseHearData(ZonePtr z); + virtual void parseNoneData(ZonePtr z); protected: void parseAnswerCounter(Answer *answer); virtual Answer *parseAnswer(); diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp index d3ce1235c1..57259fd637 100644 --- a/engines/parallaction/parser_br.cpp +++ b/engines/parallaction/parser_br.cpp @@ -825,6 +825,16 @@ void LocationParser_br::parseHearData(ZonePtr z) { } } +void LocationParser_br::parseNoneData(ZonePtr z) { + /* the only case we have to handle here is that of "scende2", which is the only Animation with + a command list following the type marker. + */ + if (!scumm_stricmp(_tokens[0], "commands")) { + parseCommands(z->_commands); + } +} + + typedef void (LocationParser_br::*ZoneTypeParser)(ZonePtr); static ZoneTypeParser parsers[] = { 0, // no type @@ -836,7 +846,7 @@ static ZoneTypeParser parsers[] = { &LocationParser_br::parseHearData, 0, // feel &LocationParser_br::parseSpeakData, - 0, // none + &LocationParser_br::parseNoneData, 0, // trap 0, // you 0, // command @@ -882,7 +892,6 @@ DECLARE_ANIM_PARSER(moveto) { // ctxt.a->_moveTo.z = atoi(_tokens[3]); } - DECLARE_ANIM_PARSER(endanimation) { debugC(7, kDebugParser, "ANIM_PARSER(endanimation) "); -- cgit v1.2.3 From 4c6d276ce914cafc170732fb7203145c8a763b37 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 13 Jun 2010 10:50:54 +0000 Subject: Bugfixes for correct moving of the screen viewport within an animation svn-id: r49629 --- engines/m4/animation.cpp | 6 ++++-- engines/m4/mads_scene.cpp | 1 - engines/m4/mads_views.cpp | 11 ++++++++--- engines/m4/mads_views.h | 2 +- 4 files changed, 13 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index cf2d201b81..9b6d5d1a6f 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -333,13 +333,15 @@ void MadsAnimation::update() { // Handle any offset adjustment for sprites as of this frame if (_view->_posAdjust.x != misc.posAdjust.x) { - misc.posAdjust.x = _view->_posAdjust.x; + _view->_posAdjust.x = misc.posAdjust.x; screenChanged = true; } if (_view->_posAdjust.y != misc.posAdjust.y) { - misc.posAdjust.y = _view->_posAdjust.y; + _view->_posAdjust.y = misc.posAdjust.y; screenChanged = true; } + + if (screenChanged) { // Signal the entire screen needs refreshing _view->_spriteSlots.fullRefresh(); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index f98684de6a..d910340930 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -655,7 +655,6 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su drawStyle = stream->readUint16LE(); width = stream->readUint16LE(); height = stream->readUint16LE(); - assert((width == 320) && (height == 156)); stream->skip(24); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 98b04e9f2d..178fd90fd3 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -855,10 +855,15 @@ void MadsDirtyAreas::mergeAreas(int idx1, int idx2) { da1.textActive = true; } -void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset) { +void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset, const Common::Point &posAdjust) { for (uint i = 0; i < _entries.size(); ++i) { + const Common::Rect &srcBounds = _entries[i].bounds; + + Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y, + srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); + if (_entries[i].active && _entries[i].bounds.isValidRect()) - src->copyTo(dest, _entries[i].bounds, _entries[i].bounds.left, _entries[i].bounds.top + yOffset); + src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top + yOffset); } } @@ -1202,7 +1207,7 @@ void MadsView::refresh() { _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); // Copy dirty areas to the main display surface - _dirtyAreas.copy(_view, _bgSurface, _yOffset); + _dirtyAreas.copy(_view, _bgSurface, _yOffset, _posAdjust); // Handle dirty areas for foreground objects _spriteSlots.setDirtyAreas(); diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index c0f3790a23..f0ded634b1 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -289,7 +289,7 @@ public: void merge(int startIndex, int count); bool intersects(int idx1, int idx2); void mergeAreas(int idx1, int idx2); - void copy(M4Surface *dest, M4Surface *src, int yOffset); + void copy(M4Surface *dest, M4Surface *src, int yOffset, const Common::Point &posAdjust); }; enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2}; -- cgit v1.2.3 From a4ac9347d4bbac0ee8bef8786c9e23831ad60636 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 13 Jun 2010 21:43:13 +0000 Subject: Fixed regression from commit #49251, and added an explanation. Calls to kNewNode with 1 parameter are handled properly again. Fixes the demo of Phantasmagoria 1. Thanks to lskovlun and waltervn for spotting this svn-id: r49638 --- engines/sci/engine/klists.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 18d6638e92..050c8e515f 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -157,7 +157,9 @@ reg_t kDisposeList(EngineState *s, int argc, reg_t *argv) { reg_t kNewNode(EngineState *s, int argc, reg_t *argv) { reg_t nodeValue = argv[0]; - reg_t nodeKey = (argc == 2) ? argv[1] : NULL_REG; + // Some SCI32 games call this with 1 parameter (e.g. the demo of Phantasmagoria). + // Set the key to be the same as the value in this case + reg_t nodeKey = (argc == 2) ? argv[1] : argv[0]; s->r_acc = s->_segMan->newNode(nodeValue, nodeKey); debugC(2, kDebugLevelNodes, "New nodebase at %04x:%04x", PRINT_REG(s->r_acc)); -- cgit v1.2.3 From 01d53a62165d229b88db11647ffe40ff2502d7b4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 13 Jun 2010 22:01:10 +0000 Subject: Disabled two cases of findObjectByName() in SCI0 early games svn-id: r49639 --- engines/sci/engine/vm.cpp | 2 +- engines/sci/graphics/animate.cpp | 8 +++++--- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 1db9649a54..95ed13a3d3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -201,7 +201,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i // stopGroop object, which points to ego, to the new ego object. If this is not // done, ego's movement will not be updated properly, so the result is // unpredictable (for example in LSL5, Patti spins around instead of walking). - if (index == 0 && type == VAR_GLOBAL) { // global 0 is ego + if (index == 0 && type == VAR_GLOBAL && getSciVersion() > SCI_VERSION_0_EARLY) { // global 0 is ego reg_t stopGroopPos = segMan->findObjectByName("stopGroop"); if (!stopGroopPos.isNull()) { // does the game have a stopGroop object? // Find the "client" member variable of the stopGroop object, and update it diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 48715af53e..598724f2be 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -63,9 +63,11 @@ void GfxAnimate::init() { if (getSciVersion() <= SCI_VERSION_01) _ignoreFastCast = true; // Also if fastCast object exists at gamestartup, we can assume that the interpreter doesnt do kAnimate aborts - // (found in larry 1) - if (!_s->_segMan->findObjectByName("fastCast").isNull()) - _ignoreFastCast = true; + // (found in Larry 1) + if (getSciVersion() > SCI_VERSION_0_EARLY) { + if (!_s->_segMan->findObjectByName("fastCast").isNull()) + _ignoreFastCast = true; + } } void GfxAnimate::disposeLastCast() { -- cgit v1.2.3 From b5ebd40d614ab7b1c2f1408750c09f528b7ae2de Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 13 Jun 2010 22:15:30 +0000 Subject: The offset of script local variables is now calculated when the script is loaded, thus we no longer need to save it. Merged scriptInitialiseLocals() with scriptInitialiseLocalsZero() svn-id: r49640 --- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/savegame.h | 2 +- engines/sci/engine/script.cpp | 66 ++++++++++++++++++---------------------- engines/sci/engine/seg_manager.h | 12 ++------ engines/sci/engine/segment.cpp | 4 +++ 5 files changed, 37 insertions(+), 49 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 9c2ff76088..8c743189d7 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -566,7 +566,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { } } - s.syncAsSint32LE(_localsOffset); + s.skip(4, VER(9), VER(20)); // OBSOLETE: Used to be _localsOffset s.syncAsSint32LE(_localsSegment); s.syncAsSint32LE(_markedAsDeleted); diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 7be05381da..e7e8fff999 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -36,7 +36,7 @@ namespace Sci { struct EngineState; enum { - CURRENT_SAVEGAME_VERSION = 20, + CURRENT_SAVEGAME_VERSION = 21, MINIMUM_SAVEGAME_VERSION = 9 }; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 1f32e50b67..54edd38f90 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -159,41 +159,48 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller } } -void SegManager::scriptInitialiseLocalsZero(SegmentId seg, int count) { - Script *scr = getScript(seg); +void SegManager::scriptInitialiseLocals(SegmentId segmentId) { + Script *scr = getScript(segmentId); + uint16 count; - scr->_localsOffset = -count * 2; // Make sure it's invalid + if (getSciVersion() == SCI_VERSION_0_EARLY) { + // Old script block. There won't be a localvar block in this case. + // Instead, the script starts with a 16 bit int specifying the + // number of locals we need; these are then allocated and zeroed. + int localsCount = READ_LE_UINT16(scr->_buf); + if (localsCount) { + scr->_localsOffset = -localsCount * 2; // Make sure it's invalid + LocalVariables *locals = allocLocalsSegment(scr, localsCount); + if (locals) { + for (int i = 0; i < localsCount; i++) + locals->_locals[i] = NULL_REG; + } + } - LocalVariables *locals = allocLocalsSegment(scr, count); - if (locals) { - for (int i = 0; i < count; i++) - locals->_locals[i] = NULL_REG; + return; } -} -void SegManager::scriptInitialiseLocals(reg_t location) { - Script *scr = getScript(location.segment); - unsigned int count; + // Check if the script actually has local variables + if (scr->_localsOffset == 0) + return; - VERIFY(location.offset + 1 < (uint16)scr->getBufSize(), "Locals beyond end of script\n"); + VERIFY(scr->_localsOffset + 1 < (uint16)scr->getBufSize(), "Locals beyond end of script\n"); if (getSciVersion() >= SCI_VERSION_1_1) - count = READ_SCI11ENDIAN_UINT16(scr->_buf + location.offset - 2); + count = READ_SCI11ENDIAN_UINT16(scr->_buf + scr->_localsOffset - 2); else - count = (READ_LE_UINT16(scr->_buf + location.offset - 2) - 4) >> 1; + count = (READ_LE_UINT16(scr->_buf + scr->_localsOffset - 2) - 4) >> 1; // half block size - scr->_localsOffset = location.offset; - - if (!(location.offset + count * 2 + 1 < scr->getBufSize())) { - warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", location.offset, count, (uint)scr->getBufSize()); - count = (scr->getBufSize() - location.offset) >> 1; + if (!(scr->_localsOffset + count * 2 + 1 < (uint16)scr->getBufSize())) { + warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", scr->_localsOffset, count, (uint)scr->getBufSize()); + count = (scr->getBufSize() - scr->_localsOffset) >> 1; } LocalVariables *locals = allocLocalsSegment(scr, count); if (locals) { uint i; - const byte *base = (const byte *)(scr->_buf + location.offset); + const byte *base = (const byte *)(scr->_buf + scr->_localsOffset); for (i = 0; i < count; i++) locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); @@ -258,18 +265,7 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); uint16 curOffset = oldScriptHeader ? 2 : 0; - if (oldScriptHeader) { - // Old script block - // There won't be a localvar block in this case - // Instead, the script starts with a 16 bit int specifying the - // number of locals we need; these are then allocated and zeroed. - int localsCount = READ_LE_UINT16(scr->_buf); - if (localsCount) - segMan->scriptInitialiseLocalsZero(segmentId, localsCount); - } - - // Now do a first pass through the script objects to find the - // local variable blocks + // Now do a first pass through the script objects to find all the object classes do { objType = scr->getHeap(curOffset); @@ -280,9 +276,6 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { curOffset += 4; // skip header switch (objType) { - case SCI_OBJ_LOCALVARS: - segMan->scriptInitialiseLocals(make_reg(segmentId, curOffset)); - break; case SCI_OBJ_CLASS: { int classpos = curOffset - SCRIPT_OBJECT_MAGIC_OFFSET; int species = scr->getHeap(curOffset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET); @@ -365,10 +358,9 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNu scr->init(scriptNum, resMan); scr->load(resMan); + segMan->scriptInitialiseLocals(segmentId); if (getSciVersion() >= SCI_VERSION_1_1) { - int heapStart = scr->getScriptSize(); - segMan->scriptInitialiseLocals(make_reg(segmentId, heapStart + 4)); segMan->scriptInitialiseObjectsSci11(segmentId); scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); } else { diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 9bcdd80a62..62dcddbcbe 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -145,19 +145,11 @@ public: // to be used during script instantiation, // i.e. loading and linking. - /** - * Initializes a script's local variable block - * All variables are initialized to zero. - * @param seg Segment containing the script to initialize - * @param nr Number of local variables to allocate - */ - void scriptInitialiseLocalsZero(SegmentId seg, int nr); - /** * Initializes a script's local variable block according to a prototype - * @param location Location to initialize from + * @param segmentId Segment containing the script to initialize */ - void scriptInitialiseLocals(reg_t location); + void scriptInitialiseLocals(SegmentId segmentId); // 2. Clones diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 0e0a759d4b..4b3df11d8f 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -197,6 +197,7 @@ void Script::load(ResourceManager *resMan) { if (READ_LE_UINT16(_buf + 1 + 5) > 0) { _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + _localsOffset = _scriptSize + 4; } } else { _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); @@ -209,6 +210,9 @@ void Script::load(ResourceManager *resMan) { _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; _synonyms += 4; // skip header } + const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS); + if (localsBlock) + _localsOffset = localsBlock - _buf + 4; } } -- cgit v1.2.3 From d36f6638c0fd6e5aeaf8d8ac8665d5d2d8a2575f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 13 Jun 2010 22:48:49 +0000 Subject: Fixed compilation with the old music code svn-id: r49641 --- engines/sci/console.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index bd597aaa19..6c022bb631 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -852,6 +852,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { } bool Console::cmdShowInstruments(int argc, const char **argv) { +#ifndef USE_OLD_MUSIC_FUNCTIONS int songNumber = -1; if (argc == 2) @@ -1007,6 +1008,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { DebugPrintf("\n\n"); } +#endif return true; } -- cgit v1.2.3 From ae0a7a667504b3356f2355aadfa6add722749ca6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 14 Jun 2010 03:15:58 +0000 Subject: Added logic for animation sequences specifying a starting animation frame number svn-id: r49642 --- engines/m4/animation.cpp | 3 +++ engines/m4/mads_anim.cpp | 56 ++++++++++++++++++++++++++++++++++++++---------- engines/m4/mads_anim.h | 1 + 3 files changed, 49 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 9b6d5d1a6f..1d9b1161c2 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -328,6 +328,7 @@ void MadsAnimation::update() { // Handle starting any sound for this frame AnimMiscEntry &misc = _miscEntries[_currentFrame]; +printf("frame %d delay %d\n", _currentFrame, misc.numTicks); if (misc.soundNum) _vm->_sound->playSound(misc.soundNum); @@ -449,6 +450,8 @@ void MadsAnimation::setCurrentFrame(int frameNumber) { _currentFrame = frameNumber; _oldFrameEntry = 0; _freeFlag = false; + + _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer; } void MadsAnimation::load1(int frameNumber) { diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index c618ae57cc..c2e9ea4eee 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -459,7 +459,8 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): _transition = kTransitionNone; _activeAnimation = NULL; _bgLoadFlag = true; - + _startFrame = -1; + reset(); // Set up system palette colors @@ -536,6 +537,9 @@ void AnimviewView::updateState() { return; } + // Reset flags + _startFrame = -1; + readNextCommand(); } @@ -543,7 +547,15 @@ void AnimviewView::updateState() { } void AnimviewView::readNextCommand() { +static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes **** + while (!_script->eos() && !_script->err()) { + if (!tempFlag) { + tempFlag = true; + strncpy(_currentLine, _script->readLine().c_str(), 79); + strncpy(_currentLine, _script->readLine().c_str(), 79); + } + strncpy(_currentLine, _script->readLine().c_str(), 79); // Process any switches on the line @@ -581,6 +593,9 @@ void AnimviewView::readNextCommand() { _activeAnimation = new MadsAnimation(_vm, this); _activeAnimation->initialise(_currentLine, flags, &_backgroundSurface, &_codeSurface); + if (_startFrame != -1) + _activeAnimation->setCurrentFrame(_startFrame); + _spriteSlots.fullRefresh(); /* // Handle scene transition @@ -634,6 +649,7 @@ return; Switches are: (taken from the help of the original executable) -b Toggle background load status off/on. -c:char Specify sound card id letter. + -f:num Specify a specific starting frame number -g Stay in graphics mode on exit. -h[:ex] Disable EMS/XMS high memory support. -i Switch sound interrupts mode off/on. @@ -677,21 +693,39 @@ void AnimviewView::processCommand() { str_upper(commandStr); char *param = commandStr; - if (!strncmp(commandStr, "B", 1)) { + switch (commandStr[0]) { + case 'B': // Toggle background load flag _bgLoadFlag = !_bgLoadFlag; - } else if (!strncmp(commandStr, "X", 1)) { - //printf("X "); - } else if (!strncmp(commandStr, "W", 1)) { - //printf("W "); - } else if (!strncmp(commandStr, "R", 1)) { - param = param + 2; - //printf("R:%s ", param); - } else if (!strncmp(commandStr, "O", 1)) { + break; + + case 'F': + // Start animation at a specific frame + ++param; + assert(*param == ':'); + _startFrame = atoi(++param); + break; + + case 'O': param = param + 2; //printf("O:%i ", atoi(param)); _transition = atoi(param); - } else { + break; + + case 'R': + param = param + 2; + //printf("R:%s ", param); + break; + + case 'W': + //printf("W "); + break; + + case 'X': + //printf("X "); + break; + + default: error("Unknown response command: '%s'", commandStr); } } diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h index f18fe46f48..78cc8727f8 100644 --- a/engines/m4/mads_anim.h +++ b/engines/m4/mads_anim.h @@ -91,6 +91,7 @@ private: int _transition; MadsAnimation *_activeAnimation; bool _bgLoadFlag; + int _startFrame; void reset(); void readNextCommand(); -- cgit v1.2.3 From 466a151744618f89d6a0b53d23189af048d88831 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 14 Jun 2010 04:20:57 +0000 Subject: Fixes for memory leaks reported by Valgrind svn-id: r49643 --- engines/m4/graphics.cpp | 1 + engines/m4/m4.cpp | 1 + engines/m4/mads_scene.cpp | 7 +++++-- engines/m4/mads_views.cpp | 1 + 4 files changed, 8 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index fc5cb0f9f9..36de60af6c 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -74,6 +74,7 @@ M4Surface::~M4Surface() { _madsVm->_palette->deleteRange(_rgbList); delete _rgbList; } + free(); } void M4Surface::loadCodesM4(Common::SeekableReadStream *source) { diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index a5db6660d8..c30e946653 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -147,6 +147,7 @@ MadsM4Engine::~MadsM4Engine() { delete _random; delete _palette; delete _globals; + delete _sound; delete _resourceManager; } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index d910340930..269f33878c 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -678,7 +678,9 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su Common::String s(buffer2, 64); setNames.push_back(s); } - + + delete stream; + // Initialise a copy of the surfaces if they weren't provided bool dsFlag = false, ssFlag = false; int gfxSize = width * height; @@ -696,6 +698,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su dsFlag = true; } + // For Rex Nebular, read in the scene's compressed walk surface information if (_vm->getGameType() == GType_RexNebular) { assert(depthSurface); @@ -712,7 +715,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su destP += runLength; } - delete walkData; + free(walkData); delete stream; } diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 178fd90fd3..5c6c01293e 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -270,6 +270,7 @@ MadsTextDisplay::MadsTextDisplay(MadsView &owner): _owner(owner) { for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i) { MadsTextDisplayEntry rec; rec.active = false; + rec.expire = 0; _entries.push_back(rec); } } -- cgit v1.2.3 From 6fb462e6b05c5ead3fefe97e18d31f4835d5e321 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 14 Jun 2010 05:27:54 +0000 Subject: Further memory leak fixes reported by Valgrind svn-id: r49644 --- engines/m4/animation.cpp | 1 - engines/m4/events.cpp | 4 ++++ engines/m4/events.h | 1 + engines/m4/globals.cpp | 26 +++++++++++++------------- engines/m4/globals.h | 2 +- engines/m4/m4.cpp | 11 +++++++---- engines/m4/m4.h | 10 +++++++++- engines/m4/mads_menus.cpp | 7 +++---- engines/m4/scene.cpp | 1 + engines/m4/sound.cpp | 38 ++++++++++++++++++-------------------- engines/m4/sound.h | 2 +- 11 files changed, 58 insertions(+), 45 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 1d9b1161c2..a9d52a54c1 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -328,7 +328,6 @@ void MadsAnimation::update() { // Handle starting any sound for this frame AnimMiscEntry &misc = _miscEntries[_currentFrame]; -printf("frame %d delay %d\n", _currentFrame, misc.numTicks); if (misc.soundNum) _vm->_sound->playSound(misc.soundNum); diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp index c0ca412f11..65378c5d6a 100644 --- a/engines/m4/events.cpp +++ b/engines/m4/events.cpp @@ -57,6 +57,10 @@ Events::Events(MadsM4Engine *vm) : _vm(vm) { _console = new MadsConsole(_madsVm); } +Events::~Events() { + delete _console; +} + M4EventType Events::handleEvents() { static int oldX = -1, oldY = -1; static uint32 dclickTime = 0; diff --git a/engines/m4/events.h b/engines/m4/events.h index 43b61c8f0d..1c1418d5f8 100644 --- a/engines/m4/events.h +++ b/engines/m4/events.h @@ -78,6 +78,7 @@ private: public: bool quitFlag; Events(MadsM4Engine *vm); + virtual ~Events(); Common::Event &event() { return _event; } Common::EventType type() { return _event.type; } diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index 1768c71787..e63504ad73 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -351,16 +351,16 @@ void MadsGlobals::loadMadsMessagesInfo() { //printf("%i messages\n", count); for (int i = 0; i < count; i++) { - MessageItem *curMessage = new MessageItem(); - curMessage->id = messageS->readUint32LE(); - curMessage->offset = messageS->readUint32LE(); - curMessage->uncompSize = messageS->readUint16LE(); + MessageItem curMessage; + curMessage.id = messageS->readUint32LE(); + curMessage.offset = messageS->readUint32LE(); + curMessage.uncompSize = messageS->readUint16LE(); if (i > 0) - _madsMessages[i - 1]->compSize = curMessage->offset - _madsMessages[i - 1]->offset; + _madsMessages[i - 1].compSize = curMessage.offset - _madsMessages[i - 1].offset; if (i == count - 1) - curMessage->compSize = messageS->size() - curMessage->offset; + curMessage.compSize = messageS->size() - curMessage.offset; //printf("id: %i, offset: %i, uncomp size: %i\n", curMessage->id, curMessage->offset, curMessage->uncompSize); _madsMessages.push_back(curMessage); @@ -382,7 +382,7 @@ void MadsGlobals::loadMadsObjects() { int MadsGlobals::messageIndexOf(uint32 messageId) { for (uint i = 0; i < _madsMessages.size(); ++i) { - if (_madsMessages[i]->id == messageId) + if (_madsMessages[i].id == messageId) return i; } return -1; @@ -395,15 +395,15 @@ const char *MadsGlobals::loadMessage(uint index) { } FabDecompressor fab; - byte *compData = new byte[_madsMessages[index]->compSize]; - byte *buffer = new byte[_madsMessages[index]->uncompSize]; + byte *compData = new byte[_madsMessages[index].compSize]; + byte *buffer = new byte[_madsMessages[index].uncompSize]; Common::SeekableReadStream *messageS = _vm->res()->get("messages.dat"); - messageS->seek(_madsMessages[index]->offset, SEEK_SET); - messageS->read(compData, _madsMessages[index]->compSize); - fab.decompress(compData, _madsMessages[index]->compSize, buffer, _madsMessages[index]->uncompSize); + messageS->seek(_madsMessages[index].offset, SEEK_SET); + messageS->read(compData, _madsMessages[index].compSize); + fab.decompress(compData, _madsMessages[index].compSize, buffer, _madsMessages[index].uncompSize); - for (int i = 0; i < _madsMessages[index]->uncompSize - 1; i++) + for (int i = 0; i < _madsMessages[index].uncompSize - 1; i++) if (buffer[i] == '\0') buffer[i] = '\n'; _vm->res()->toss("messages.dat"); diff --git a/engines/m4/globals.h b/engines/m4/globals.h index de6e716ece..1714d223ce 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -235,7 +235,7 @@ private: MadsEngine *_vm; Common::Array _madsVocab; Common::Array _madsQuotes; - Common::Array _madsMessages; + Common::Array _madsMessages; MadsObjectArray _madsObjects; Common::List _visitedScenes; public: diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index c30e946653..446f2bf974 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -148,6 +148,7 @@ MadsM4Engine::~MadsM4Engine() { delete _palette; delete _globals; delete _sound; + delete _driver; delete _resourceManager; } @@ -158,11 +159,11 @@ Common::Error MadsM4Engine::run() { MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(midiDriver); if (native_mt32) - driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); + _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); - _midi = new MidiPlayer(this, driver); + _midi = new MidiPlayer(this, _driver); _midi->setGM(true); _midi->setNativeMT32(native_mt32); @@ -513,7 +514,6 @@ Common::Error MadsEngine::run() { // Set up needed common functionality MadsM4Engine::run(); - _scene = new MadsScene(this); _palette->setMadsSystemPalette(); _mouse->init("cursor.ss", NULL); @@ -538,9 +538,12 @@ Common::Error MadsEngine::run() { //printf("%s\n----------\n", _globals->loadMessage(i)); if ((getGameType() == GType_RexNebular) || (getGameType() == GType_DragonSphere)) { + _scene = NULL; loadMenu(MAIN_MENU); } else { + _scene = new MadsScene(this); + if (getGameType() == GType_DragonSphere) { _scene->loadScene(FIRST_SCENE); } else if (getGameType() == GType_Phantom) { diff --git a/engines/m4/m4.h b/engines/m4/m4.h index 9937107668..f5ddcc28be 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -29,6 +29,7 @@ #include "common/scummsys.h" #include "common/util.h" #include "common/random.h" +#include "sound/mididrv.h" #include "engines/engine.h" @@ -123,7 +124,7 @@ enum { struct M4GameDescription; -#define GAME_FRAME_DELAY 50 +#define GAME_FRAME_DELAY 20 #define VALIDATE_MADS assert(!_vm->isM4()) @@ -144,6 +145,7 @@ protected: void shutdown(); + MidiDriver *_driver; MidiPlayer *_midi; public: @@ -219,6 +221,12 @@ public: MadsGlobals *globals() { return (MadsGlobals *)_globals; } MadsScene *scene() { return (MadsScene *)_scene; } + void startScene(int sceneNum) { + if (!_scene) + _scene = new MadsScene(this); + _scene->show(); + _scene->loadScene(101); + } }; class M4Engine : public MadsM4Engine { diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index 94894e78be..43b9031692 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -293,7 +293,7 @@ int RexMainMenuView::getHighlightedItem(int x, int y) { } void RexMainMenuView::handleAction(MadsGameAction action) { - MadsM4Engine *vm = _vm; + MadsEngine *vm = (MadsEngine *)_vm; vm->_mouse->cursorOff(); vm->_viewManager->deleteView(this); @@ -303,8 +303,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) { // Load a sample starting scene - note that, currently, calling loadScene automatically // removes this menu screen from being displayed vm->_mouse->cursorOn(); - vm->_scene->show(); - vm->_scene->loadScene(101); + vm->startScene(101); return; case SHOW_INTRO: @@ -325,7 +324,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) { // Activate the scene display with the specified scene bool altAdvert = vm->_random->getRandomNumber(1000) >= 500; - vm->_scene->loadScene(altAdvert ? 995 : 996); + vm->startScene(altAdvert ? 995 : 996); vm->_viewManager->addView(vm->_scene); vm->_viewManager->refreshAll(); diff --git a/engines/m4/scene.cpp b/engines/m4/scene.cpp index 15c68f276c..e78d7f865e 100644 --- a/engines/m4/scene.cpp +++ b/engines/m4/scene.cpp @@ -55,6 +55,7 @@ Scene::Scene(MadsM4Engine *vm, SceneResources *res): View(vm, Common::Rect(0, 0, Scene::~Scene() { leaveScene(); + _vm->_scene = NULL; } void Scene::loadScene(int sceneNumber) { diff --git a/engines/m4/sound.cpp b/engines/m4/sound.cpp index 69ab8c0516..e0fbd2f7a9 100644 --- a/engines/m4/sound.cpp +++ b/engines/m4/sound.cpp @@ -197,20 +197,20 @@ void Sound::loadDSRFile(const char *fileName) { //printf("DSR has %i entries\n", _dsrFile.entryCount); for (int i = 0; i < _dsrFile.entryCount; i++) { - DSREntry* newEntry = new DSREntry(); - newEntry->frequency = fileStream->readUint16LE(); - newEntry->channels = fileStream->readUint32LE(); - newEntry->compSize = fileStream->readUint32LE(); - newEntry->uncompSize = fileStream->readUint32LE(); - newEntry->offset = fileStream->readUint32LE(); + DSREntry newEntry; + newEntry.frequency = fileStream->readUint16LE(); + newEntry.channels = fileStream->readUint32LE(); + newEntry.compSize = fileStream->readUint32LE(); + newEntry.uncompSize = fileStream->readUint32LE(); + newEntry.offset = fileStream->readUint32LE(); _dsrFile.dsrEntries.push_back(newEntry); /* printf("%i: ", i); printf("frequency: %i ", newEntry->frequency); printf("channels: %i ", newEntry->channels); - printf("comp: %i ", newEntry->compSize); - printf("uncomp: %i ", newEntry->uncompSize); + printf("comp: %i ", newEntry.compSize); + printf("uncomp: %i ", newEntry.uncompSize); printf("offset: %i ", newEntry->offset); printf("\n"); */ @@ -225,9 +225,7 @@ void Sound::unloadDSRFile() { if (!_dsrFileLoaded) return; - for (int i = 0; i < _dsrFile.entryCount; i++) { - _dsrFile.dsrEntries.remove_at(0); - } + _dsrFile.dsrEntries.clear(); _dsrFile.entryCount = 0; strcpy(_dsrFile.fileName, ""); @@ -251,28 +249,28 @@ void Sound::playDSRSound(int soundIndex, int volume, bool loop) { // Get sound data FabDecompressor fab; - byte *compData = new byte[_dsrFile.dsrEntries[soundIndex]->compSize]; - byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex]->uncompSize]; + byte *compData = new byte[_dsrFile.dsrEntries[soundIndex].compSize]; + byte *buffer = new byte[_dsrFile.dsrEntries[soundIndex].uncompSize]; Common::SeekableReadStream *fileStream = _vm->res()->get(_dsrFile.fileName); - fileStream->seek(_dsrFile.dsrEntries[soundIndex]->offset, SEEK_SET); - fileStream->read(compData, _dsrFile.dsrEntries[soundIndex]->compSize); + fileStream->seek(_dsrFile.dsrEntries[soundIndex].offset, SEEK_SET); + fileStream->read(compData, _dsrFile.dsrEntries[soundIndex].compSize); _vm->res()->toss(_dsrFile.fileName); - fab.decompress(compData, _dsrFile.dsrEntries[soundIndex]->compSize, - buffer, _dsrFile.dsrEntries[soundIndex]->uncompSize); + fab.decompress(compData, _dsrFile.dsrEntries[soundIndex].compSize, + buffer, _dsrFile.dsrEntries[soundIndex].uncompSize); // Play sound Audio::AudioStream *stream = Audio::makeLoopingAudioStream( Audio::makeRawStream(buffer, - _dsrFile.dsrEntries[soundIndex]->uncompSize, - _dsrFile.dsrEntries[soundIndex]->frequency, Audio::FLAG_UNSIGNED), + _dsrFile.dsrEntries[soundIndex].uncompSize, + _dsrFile.dsrEntries[soundIndex].frequency, Audio::FLAG_UNSIGNED), loop ? 0 : 1); _mixer->playStream(Audio::Mixer::kSFXSoundType, &handle->handle, stream, -1, volume); /* // Dump the sound file FILE *destFile = fopen("sound.raw", "wb"); - fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex]->uncompSize, 1, destFile); + fwrite(_dsrFile.dsrEntries[soundIndex]->data, _dsrFile.dsrEntries[soundIndex].uncompSize, 1, destFile); fclose(destFile); */ } diff --git a/engines/m4/sound.h b/engines/m4/sound.h index 7d442a73cc..5587810506 100644 --- a/engines/m4/sound.h +++ b/engines/m4/sound.h @@ -65,7 +65,7 @@ struct DSREntry { struct DSRFile { char fileName[20]; int entryCount; - Common::Array dsrEntries; + Common::Array dsrEntries; }; class MadsM4Engine; -- cgit v1.2.3 From 58487da20bf0115cfdefc2769c831c64b22d524c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 14 Jun 2010 06:33:24 +0000 Subject: Moved the actionNouns array from the scene to the globals object, since the scene will no longer be active during animation sequences svn-id: r49646 --- engines/m4/animation.cpp | 4 ++-- engines/m4/globals.cpp | 2 ++ engines/m4/globals.h | 1 + engines/m4/mads_scene.cpp | 2 -- engines/m4/mads_scene.h | 1 - engines/m4/mads_views.cpp | 6 +++--- 6 files changed, 8 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index a9d52a54c1..c39a1f0cd2 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -264,7 +264,7 @@ void MadsAnimation::load(const Common::String &filename, int abortTimers) { _abortMode = _madsVm->scene()->_abortTimersMode2; for (int i = 0; i < 3; ++i) - _actionNouns[i] = _madsVm->scene()->actionNouns[i]; + _actionNouns[i] = _madsVm->globals()->actionNouns[i]; // Initialise kernel message list for (uint i = 0; i < _messages.size(); ++i) @@ -436,7 +436,7 @@ void MadsAnimation::update() { if (_abortMode != ABORTMODE_1) { // Copy the noun list for (int i = 0; i < 3; ++i) - _madsVm->scene()->actionNouns[i] = _actionNouns[i]; + _madsVm->globals()->actionNouns[i] = _actionNouns[i]; } } } diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index e63504ad73..b9039e3afd 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -282,6 +282,8 @@ MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) { playerSpriteChanged = false; dialogType = DIALOG_NONE; sceneNumber = -1; + for (int i = 0; i < 3; ++i) + actionNouns[i] = 0; } MadsGlobals::~MadsGlobals() { diff --git a/engines/m4/globals.h b/engines/m4/globals.h index 1714d223ce..3a986ee294 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -249,6 +249,7 @@ public: MadsDialogType dialogType; int sceneNumber; int previousScene; + uint16 actionNouns[3]; void loadMadsVocab(); uint32 getVocabSize() { return _madsVocab.size(); } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 269f33878c..428b92c657 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -55,8 +55,6 @@ MadsScene::MadsScene(MadsEngine *vm): _sceneResources(), Scene(vm, &_sceneResour MadsView::_bgSurface = Scene::_backgroundSurface; MadsView::_depthSurface = Scene::_walkSurface; _interfaceSurface = new MadsInterfaceView(vm); - for (int i = 0; i < 3; ++i) - actionNouns[i] = 0; } MadsScene::~MadsScene() { diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index 0269de75c8..c4c6dedc0e 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -107,7 +107,6 @@ private: void setAction(); public: char _aaName[100]; - uint16 actionNouns[3]; public: MadsScene(MadsEngine *vm); virtual ~MadsScene(); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 5c6c01293e..af4177e6bb 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -404,7 +404,7 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f rec.abortMode = _owner._abortTimersMode2; for (int i = 0; i < 3; ++i) - rec.actionNouns[i] = _madsVm->scene()->actionNouns[i]; + rec.actionNouns[i] = _madsVm->globals()->actionNouns[i]; if (flags & KMSG_OWNER_TIMEOUT) rec.frameTimer = _owner._ticksAmount + _owner._newTimeout; @@ -504,7 +504,7 @@ void MadsKernelMessageList::processText(int msgIndex) { if (_owner._abortTimersMode != ABORTMODE_1) { for (int i = 0; i < 3; ++i) - _madsVm->scene()->actionNouns[i] = msg.actionNouns[i]; + _madsVm->globals()->actionNouns[i] = msg.actionNouns[i]; } } } @@ -943,7 +943,7 @@ int MadsSequenceList::add(int spriteListIndex, int v0, int frameIndex, int trigg _entries[seqIndex].abortMode = _owner._abortTimersMode2; for (int i = 0; i < 3; ++i) - _entries[seqIndex].actionNouns[i] = _madsVm->scene()->actionNouns[i]; + _entries[seqIndex].actionNouns[i] = _madsVm->globals()->actionNouns[i]; return seqIndex; } -- cgit v1.2.3 From cfdbfaa28eb29cb17185d3d3d1ddde8c89a369c1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 08:36:52 +0000 Subject: SCI: Limit the screen refresh rate to 60fps svn-id: r49647 --- engines/sci/engine/savegame.cpp | 1 + engines/sci/engine/state.h | 1 + engines/sci/event.cpp | 10 ++++++++-- engines/sci/sci.cpp | 2 +- 4 files changed, 11 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 8c743189d7..a7310d2b6a 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -877,6 +877,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // Time state: s->lastWaitTime = g_system->getMillis(); s->gameStartTime = g_system->getMillis(); + s->_screenUpdateTime = g_system->getMillis(); #ifdef USE_OLD_MUSIC_FUNCTIONS s->_sound._it = NULL; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 1b1a1fa86c..b47b739007 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -113,6 +113,7 @@ public: uint32 gameStartTime; /**< The time at which the interpreter was started */ uint32 lastWaitTime; /**< The last time the game invoked Wait() */ + uint32 _screenUpdateTime; /**< The last time the game updated the screen */ void wait(int16 ticks); diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index cdddb26ca4..ed9c4bfd0d 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -319,8 +319,14 @@ sciEvent EventManager::get(unsigned int mask) { //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; sciEvent event = { 0, 0, 0, 0 }; - // Update the screen here, since it's called very often - g_system->updateScreen(); + // Update the screen here, since it's called very often. + // Throttle the screen update rate to 60fps. + uint32 curTime = g_system->getMillis(); + uint32 duration = curTime - g_sci->getEngineState()->_screenUpdateTime; + if (duration >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } // Get all queued events from graphics driver do { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9e928b82d9..ee2f5845a2 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -325,7 +325,7 @@ bool SciEngine::initGame() { _vocabulary->parser_base = make_reg(_gamestate->_segMan->getSysStringsSegment(), SYS_STRING_PARSER_BASE); } - _gamestate->gameStartTime = _gamestate->lastWaitTime = g_system->getMillis(); + _gamestate->gameStartTime = _gamestate->lastWaitTime = _gamestate->_screenUpdateTime = g_system->getMillis(); srand(g_system->getMillis()); // Initialize random number generator -- cgit v1.2.3 From cd77cb96fc85ba2f681337630c4374ce0565927f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 12:44:57 +0000 Subject: Some cleanup of the script locals code svn-id: r49649 --- engines/sci/engine/script.cpp | 50 ++++++++------------------------------ engines/sci/engine/seg_manager.cpp | 6 ++--- engines/sci/engine/seg_manager.h | 2 +- engines/sci/engine/segment.cpp | 24 +++++++++++++++++- engines/sci/engine/segment.h | 6 ++++- 5 files changed, 42 insertions(+), 46 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 54edd38f90..6dfd39a496 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -161,49 +161,19 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller void SegManager::scriptInitialiseLocals(SegmentId segmentId) { Script *scr = getScript(segmentId); - uint16 count; - - if (getSciVersion() == SCI_VERSION_0_EARLY) { - // Old script block. There won't be a localvar block in this case. - // Instead, the script starts with a 16 bit int specifying the - // number of locals we need; these are then allocated and zeroed. - int localsCount = READ_LE_UINT16(scr->_buf); - if (localsCount) { - scr->_localsOffset = -localsCount * 2; // Make sure it's invalid - LocalVariables *locals = allocLocalsSegment(scr, localsCount); - if (locals) { - for (int i = 0; i < localsCount; i++) - locals->_locals[i] = NULL_REG; - } - } - - return; - } - - // Check if the script actually has local variables - if (scr->_localsOffset == 0) - return; - VERIFY(scr->_localsOffset + 1 < (uint16)scr->getBufSize(), "Locals beyond end of script\n"); - - if (getSciVersion() >= SCI_VERSION_1_1) - count = READ_SCI11ENDIAN_UINT16(scr->_buf + scr->_localsOffset - 2); - else - count = (READ_LE_UINT16(scr->_buf + scr->_localsOffset - 2) - 4) >> 1; - // half block size - - if (!(scr->_localsOffset + count * 2 + 1 < (uint16)scr->getBufSize())) { - warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", scr->_localsOffset, count, (uint)scr->getBufSize()); - count = (scr->getBufSize() - scr->_localsOffset) >> 1; - } - - LocalVariables *locals = allocLocalsSegment(scr, count); + LocalVariables *locals = allocLocalsSegment(scr); if (locals) { - uint i; - const byte *base = (const byte *)(scr->_buf + scr->_localsOffset); + if (getSciVersion() > SCI_VERSION_0_EARLY) { + const byte *base = (const byte *)(scr->_buf + scr->getLocalsOffset()); - for (i = 0; i < count; i++) - locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); + for (uint16 i = 0; i < scr->getLocalsCount(); i++) + locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); + } else { + // In SCI0 early, locals are set at run time, thus zero them all here + for (uint16 i = 0; i < scr->getLocalsCount(); i++) + locals->_locals[i] = NULL_REG; + } } } diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 4d3e6f754e..8d51b27099 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -377,8 +377,8 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) { return segment; } -LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { - if (!count) { // No locals +LocalVariables *SegManager::allocLocalsSegment(Script *scr) { + if (!scr->getLocalsCount()) { // No locals scr->_localsSegment = 0; scr->_localsBlock = NULL; return NULL; @@ -395,7 +395,7 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr, int count) { scr->_localsBlock = locals; locals->script_id = scr->_nr; - locals->_locals.resize(count); + locals->_locals.resize(scr->getLocalsCount()); return locals; } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 62dcddbcbe..ec89e42f9c 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -478,7 +478,7 @@ private: private: SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid); - LocalVariables *allocLocalsSegment(Script *scr, int count); + LocalVariables *allocLocalsSegment(Script *scr); int deallocate(SegmentId seg, bool recursive); void createClassTable(); diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 4b3df11d8f..c32823a7c2 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -100,6 +100,7 @@ Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { _localsOffset = 0; _localsSegment = 0; _localsBlock = NULL; + _localsCount = 0; _markedAsDeleted = false; } @@ -122,6 +123,7 @@ void Script::init(int script_nr, ResourceManager *resMan) { _localsOffset = 0; _localsBlock = NULL; + _localsCount = 0; _codeBlocks.clear(); @@ -198,6 +200,7 @@ void Script::load(ResourceManager *resMan) { _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); _localsOffset = _scriptSize + 4; + _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); } } else { _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); @@ -211,8 +214,27 @@ void Script::load(ResourceManager *resMan) { _synonyms += 4; // skip header } const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS); - if (localsBlock) + if (localsBlock) { _localsOffset = localsBlock - _buf + 4; + _localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size + } + } + + if (getSciVersion() > SCI_VERSION_0_EARLY) { + // Does the script actually have locals? If not, set the locals offset to 0 + if (!_localsCount) + _localsOffset = 0; + + if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { + warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", _localsOffset, _localsCount, _bufSize); + _localsCount = (_bufSize - _localsOffset) >> 1; + } + } else { + // Old script block. There won't be a localvar block in this case. + // Instead, the script starts with a 16 bit int specifying the + // number of locals we need; these are then allocated and zeroed. + _localsCount = READ_LE_UINT16(_buf); + _localsOffset = -_localsCount * 2; // Make sure it's invalid } } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index f1b6dccaa2..8759c630e8 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -364,6 +364,9 @@ private: Common::Array _codeBlocks; + int _localsOffset; + uint16 _localsCount; + public: /** * Table for objects, contains property variables. @@ -371,7 +374,8 @@ public: */ ObjMap _objects; - int _localsOffset; + int getLocalsOffset() const { return _localsOffset; } + uint16 getLocalsCount() const { return _localsCount; } SegmentId _localsSegment; /**< The local variable segment */ LocalVariables *_localsBlock; -- cgit v1.2.3 From 2a78b8279930212337c446948cc9a2943d685c94 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 13:13:02 +0000 Subject: Fixed a bug with commit #49640 svn-id: r49650 --- engines/sci/engine/segment.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index c32823a7c2..c5afe57eea 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -196,12 +196,12 @@ void Script::load(ResourceManager *resMan) { _numSynonyms = 0; if (getSciVersion() >= SCI_VERSION_1_1) { - if (READ_LE_UINT16(_buf + 1 + 5) > 0) { + if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table? _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); - _localsOffset = _scriptSize + 4; - _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); } + _localsOffset = _scriptSize + 4; + _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); } else { _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); if (_exportTable) { -- cgit v1.2.3 From 5230930d9577726d6f64fa8ffa73690314fd0a56 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 13:41:06 +0000 Subject: Silenced warning svn-id: r49651 --- engines/sci/engine/segment.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index c5afe57eea..99fcb1b821 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -226,7 +226,7 @@ void Script::load(ResourceManager *resMan) { _localsOffset = 0; if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { - warning("Locals extend beyond end of script: offset %04x, count %x vs size %x", _localsOffset, _localsCount, _bufSize); + warning("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); _localsCount = (_bufSize - _localsOffset) >> 1; } } else { -- cgit v1.2.3 From 4f3bb60cd59f7b24a4c1d29de7ba790d262b16ee Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 13:53:15 +0000 Subject: Really silence the warning with _bufSize svn-id: r49652 --- engines/sci/engine/segment.cpp | 2 +- engines/sci/engine/segment.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 99fcb1b821..492e928e31 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -161,7 +161,7 @@ void Script::init(int script_nr, ResourceManager *resMan) { } // As mentioned above, the script and the heap together should not exceed 64KB - if (_bufSize > 65535) + if (script->size + heap->size > 65535) error("Script and heap sizes combined exceed 64K. This means a fundamental " "design bug was made regarding SCI1.1 and newer games.\nPlease " "report this error to the ScummVM team"); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 8759c630e8..045cb119a3 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -354,7 +354,7 @@ protected: private: size_t _scriptSize; size_t _heapSize; - size_t _bufSize; + uint16 _bufSize; const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ uint16 _numExports; /**< Number of entries in the exports table */ -- cgit v1.2.3 From 4d517ed0e9870ef75b7b0c3eeda9659563d3ace9 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:50:23 +0000 Subject: Extended advancedDetector with depth parameter. Now AD can search nested directories. By default it is turned off, but there is new parameter to ADParameters struct. Usually value of 2 is good enough for all purposes. svn-id: r49653 --- engines/advancedDetector.cpp | 42 +++++++++++++++++++++++++++----------- engines/advancedDetector.h | 7 +++++++ engines/agi/detection.cpp | 4 +++- engines/agos/detection.cpp | 4 +++- engines/cine/detection.cpp | 4 +++- engines/cruise/detection.cpp | 4 +++- engines/draci/detection.cpp | 4 +++- engines/drascula/detection.cpp | 4 +++- engines/gob/detection.cpp | 4 +++- engines/groovie/detection.cpp | 4 +++- engines/kyra/detection.cpp | 4 +++- engines/lure/detection.cpp | 4 +++- engines/m4/detection.cpp | 4 +++- engines/made/detection.cpp | 4 +++- engines/mohawk/detection.cpp | 4 +++- engines/parallaction/detection.cpp | 4 +++- engines/saga/detection.cpp | 4 +++- engines/sci/detection.cpp | 4 +++- engines/teenagent/detection.cpp | 3 ++- engines/tinsel/detection.cpp | 4 +++- engines/touche/detection.cpp | 4 +++- engines/tucker/detection.cpp | 3 ++- 22 files changed, 95 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index b149b43ad7..f4932a1055 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -340,24 +340,24 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms); -static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) { - FileMap allFiles; - SizeMD5Map filesSizeMD5; - - const ADGameFileDescription *fileDesc; - const ADGameDescription *g; - const byte *descPtr; +static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) { + if (depth == 0) + return; if (fslist.empty()) - return ADGameDescList(); - Common::FSNode parent = fslist.begin()->getParent(); - debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); + return; // First we compose a hashmap of all files in fslist. // Includes nifty stuff like removing trailing dots and ignoring case. for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { - if (file->isDirectory()) - continue; + if (file->isDirectory()) { + Common::FSList files; + + if (!file->getChildren(files, Common::FSNode::kListAll)) + continue; + + composeFileHashMap(files, allFiles, depth - 1); + } Common::String tstr = file->getName(); @@ -367,6 +367,24 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p allFiles[tstr] = *file; // Record the presence of this file } +} + +static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams ¶ms, Common::Language language, Common::Platform platform, const Common::String &extra) { + FileMap allFiles; + SizeMD5Map filesSizeMD5; + + const ADGameFileDescription *fileDesc; + const ADGameDescription *g; + const byte *descPtr; + + if (fslist.empty()) + return ADGameDescList(); + Common::FSNode parent = fslist.begin()->getParent(); + debug(3, "Starting detection in dir '%s'", parent.getPath().c_str()); + + // First we compose a hashmap of all files in fslist. + // Includes nifty stuff like removing trailing dots and ignoring case. + composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth)); // Check which files are included in some ADGameDescription *and* present // in fslist. Compute MD5s and file sizes for these files. diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index 370d958ce6..a48dd0c1d2 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -190,6 +190,13 @@ struct ADParams { * enum for the list. */ uint32 guioptions; + + /** + * + * Maximum depth of directories to look up + * If set to 0, the depth is 1 level + */ + uint32 depth; }; diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index e72647d5e2..1c2638fc89 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -979,7 +979,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + // Maximum directory depth + 1 }; } // End of namespace Agi diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index 39974f9d53..d22ee720d7 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -102,7 +102,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 1 }; using namespace AGOS; diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index fcfa1f7f20..1cf9ed5fad 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -569,7 +569,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + // Maximum directory depth + 1 }; class CineMetaEngine : public AdvancedMetaEngine { diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index e1f12b734e..9088b8261e 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -237,7 +237,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI + Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + // Maximum directory depth + 1 }; class CruiseMetaEngine : public AdvancedMetaEngine { diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index c3204fc656..39834ab5fa 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -94,7 +94,9 @@ const ADParams detectionParams = { // Flags 0, // Global GUI options - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class DraciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index 76d48b7b89..a0781e0bff 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -264,7 +264,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOMIDI + Common::GUIO_NOMIDI, + // Maximum directory depth + 1 }; class DrasculaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 1f8bfdc138..feb76fe091 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -5094,7 +5094,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 1 }; class GobMetaEngine : public AdvancedMetaEngine { diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index ec401e7d24..1f7156b2fc 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -176,7 +176,9 @@ static const ADParams detectionParams = { // Flags kADFlagUseExtraAsHint, // Additional GUI options (for every game} - Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX + Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX, + // Maximum directory depth + 1 }; diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 6e9359e7fc..90a107099f 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -1226,7 +1226,9 @@ const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; } // End of anonymous namespace diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index 36c1cf237d..d8c7b483f8 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -196,7 +196,9 @@ static const ADParams detectionParams = { // Flags kADFlagUseExtraAsHint, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH, + // Maximum directory depth + 1 }; class LureMetaEngine : public AdvancedMetaEngine { diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index 9493226c1a..80a899f1ac 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -400,7 +400,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOMIDI + Common::GUIO_NOMIDI, + // Maximum directory depth + 1 }; class M4MetaEngine : public AdvancedMetaEngine { diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 1dfc0c3f83..081bb98006 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -493,7 +493,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class MadeMetaEngine : public AdvancedMetaEngine { diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 7f2e0cb312..44c3bc4f6d 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -1011,7 +1011,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game) - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class MohawkMetaEngine : public AdvancedMetaEngine { diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index e5e2b22644..2ecaf1c2d6 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -240,7 +240,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD + Common::GUIO_NOLAUNCHLOAD, + // Maximum directory depth + 1 }; class ParallactionMetaEngine : public AdvancedMetaEngine { diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index 1c2c6bacff..b57b056806 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -122,7 +122,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class SagaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 579414b3ea..7f0a27c14f 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -310,7 +310,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class SciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp index 258bd982ed..4c61e20b7a 100644 --- a/engines/teenagent/detection.cpp +++ b/engines/teenagent/detection.cpp @@ -91,7 +91,8 @@ static const ADParams detectionParams = { "teenagent", 0, 0, - Common::GUIO_NONE + Common::GUIO_NONE, + 1 }; #define MAX_SAVES 20 diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index 70a2f475ee..a70b75f136 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -637,7 +637,9 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class TinselMetaEngine : public AdvancedMetaEngine { diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 65a6a29bcc..72f87a2f3f 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -134,7 +134,9 @@ static const ADParams detectionParams = { Touche::fileBasedFallback, // file-based detection data to enable not yet known versions to start kADFlagPrintWarningOnFileBasedFallback, // Additional GUI options (for every game} - Common::GUIO_NONE + Common::GUIO_NONE, + // Maximum directory depth + 1 }; class ToucheMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index b4f30cb7fd..7f88a8ff2f 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -114,7 +114,8 @@ static const ADParams detectionParams = { "tucker", 0, 0, - Common::GUIO_NONE + Common::GUIO_NONE, + 1 }; static const ADGameDescription tuckerDemoGameDescription = { -- cgit v1.2.3 From d59c312b0890d4ad9b97c4cc0280e00fac69d725 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:50:53 +0000 Subject: Mohawk: Added support for running Riven off DVD layout. Uses new directory depth feature of AdvancedDetector. Set directory depth to 2 and added Assets1/ directory. As a result, DVD layout which does not have any game data file in top level directory gets detected and runs well. svn-id: r49654 --- engines/mohawk/detection.cpp | 2 +- engines/mohawk/riven.cpp | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 44c3bc4f6d..6f66398971 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -1013,7 +1013,7 @@ static const ADParams detectionParams = { // Additional GUI options (for every game) Common::GUIO_NONE, // Maximum directory depth - 1 + 2 }; class MohawkMetaEngine : public AdvancedMetaEngine { diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index c646855bc7..f1536b3204 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -57,6 +57,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio SearchMan.addSubDirectoryMatching(gameDataDir, "all"); SearchMan.addSubDirectoryMatching(gameDataDir, "data"); SearchMan.addSubDirectoryMatching(gameDataDir, "exe"); + SearchMan.addSubDirectoryMatching(gameDataDir, "assets1"); SearchMan.addSubDirectoryMatching(gameDataDir, "assets2"); g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426); -- cgit v1.2.3 From e281f2599a8ad608b61be3a7129f951223cad9f6 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:51:18 +0000 Subject: Implement safeguard for negative depth values in AdvancedDetector. svn-id: r49655 --- engines/advancedDetector.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index f4932a1055..061eec2faf 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -341,7 +341,7 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms); static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) { - if (depth == 0) + if (depth <= 0) return; if (fslist.empty()) -- cgit v1.2.3 From ca161920a4dcf26a6d8773dec5d95141b0383df2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:51:46 +0000 Subject: SCUMM: Fix bug #1438631. Bug #1438631: "SCUMM: Detecting mac version of indy3/loom broken" fixed by implementing recursive directory lookup similar to what was done for AdvancedDetector, since SCUMM engine does not use it. svn-id: r49656 --- engines/scumm/detection.cpp | 25 +++++++++++++++++++++---- 1 file changed, 21 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 7275caaa1e..d8b758c8b2 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -381,10 +381,12 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF } } -static void detectGames(const Common::FSList &fslist, Common::List &results, const char *gameid) { - DescMap fileMD5Map; - DetectorResult dr; - char md5str[32+1]; +static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth) { + if (depth <= 0) + return; + + if (fslist.empty()) + return; for (Common::FSList::const_iterator file = fslist.begin(); file != fslist.end(); ++file) { if (!file->isDirectory()) { @@ -392,8 +394,23 @@ static void detectGames(const Common::FSList &fslist, Common::ListgetName()] = d; + } else { + Common::FSList files; + + if (file->getChildren(files, Common::FSNode::kListAll)) { + composeFileHashMap(files, fileMD5Map, depth - 1); + } } } +} + +static void detectGames(const Common::FSList &fslist, Common::List &results, const char *gameid) { + DescMap fileMD5Map; + DetectorResult dr; + char md5str[32+1]; + + // Dive one level down since mac indy3/loom has its files split into directories. See Bug #1438631 + composeFileHashMap(fslist, fileMD5Map, 2); // Iterate over all filename patterns. for (const GameFilenamePattern *gfp = gameFilenamesTable; gfp->gameid; ++gfp) { -- cgit v1.2.3 From 6916e547a3cd3330bfc5da7df3fe2c74e64eae76 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:52:13 +0000 Subject: AGOS: Fix bug #1777795. Bug #1777795: "SIMON1: Acorn CD MD5s" fixed by specifying directory depth for AdvancedDetector to 2. svn-id: r49657 --- engines/agos/detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index d22ee720d7..9a23dde426 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -104,7 +104,7 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOLAUNCHLOAD, // Maximum directory depth - 1 + 2 }; using namespace AGOS; -- cgit v1.2.3 From 1c3e96ac122dd82b4dbd253c169f50013429e157 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Mon, 14 Jun 2010 14:52:49 +0000 Subject: Split out Mohawk detection tables into separate file. svn-id: r49658 --- engines/mohawk/detection.cpp | 872 +------------------------------------ engines/mohawk/detection_tables.h | 895 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 896 insertions(+), 871 deletions(-) create mode 100644 engines/mohawk/detection_tables.h (limited to 'engines') diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 6f66398971..a01f4a8759 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -121,877 +121,7 @@ static const PlainGameDescriptor mohawkGames[] = { {0, 0} }; - -namespace Mohawk { - -static const MohawkGameDescription gameDescriptions[] = { - // Myst - // English Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst Demo - // English Windows 3.11 - // From CD-ROM Today July, 1994 - { - { - "myst", - "Demo", - AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_MYST, - GF_DEMO, - 0, - }, - - // Myst - // German Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // German Windows 3.11 - // From LordHoto - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // Spanish Windows ? - // From jvprat - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"), - Common::ES_ESP, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // Japanese Windows 3.11 - // From clone2727 - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"), - Common::JA_JPN, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Myst - // French Windows 3.11 - // From Strangerke - { - { - "myst", - "", - AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0, - }, - - // Making of Myst - // English Windows 3.11 - // From clone2727 - { - { - "MakingOfMyst", - "", - AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0, - }, - - // Making of Myst - // Japanese Windows 3.11 - // From clone2727 - { - { - "MakingOfMyst", - "", - AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"), - Common::JA_JPN, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0, - }, - - // Myst Masterpiece Edition - // English Windows - // From clone2727 - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // English Windows - // From clone2727 - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // German Windows - // From DrMcCoy (Included in "Myst: Die Trilogie") - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Myst Masterpiece Edition - // French Windows - // From gamin (Included in "Myst: La Trilogie") - { - { - "myst", - "Masterpiece Edition", - AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.0 (5CD) - // From clone2727 - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.03 (5CD) - // From ST - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.? (5CD) - // From jvprat - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"), - Common::ES_ESP, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.? (DVD, From "Myst 10th Anniversary Edition") - // From Clone2727 - { - { - "riven", - "DVD", - AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version 1.0 (DVD, From "Myst: Die Trilogie") - // From DrMcCoy - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"), - Common::DE_DEU, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version ? (DVD, From "Myst: La Trilogie") - // From gamin - { - { - "riven", - "", - AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0, - }, - - // Riven: The Sequel to Myst - // Version ? (Demo, From "Prince of Persia Collector's Edition") - // From Clone2727 - { - { - "riven", - "Demo", - AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DEMO, - 0, - }, - -#ifdef DETECT_BRODERBUND_TITLES - { - { - "zoombini", - "", - AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_ZOOMBINI, - GF_HASMIDI, - 0 - }, - - { - { - "csworld", - "v3.0", - AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSWORLD, - 0, - 0 - }, - - { - { - "csworld", - "v3.5", - AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSWORLD, - 0, - 0 - }, - - { - { - "csamtrak", - "", - AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSAMTRAK, - 0, - 0 - }, - - { - { - "maggiess", - "", - AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAGGIESS, - 0, - 0 - }, - - { - { - "jamesmath", - "", - AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_JAMESMATH, - GF_HASMIDI, - 0 - }, - - // This is in the NEWDATA folder, so I assume it's a newer version ;) - { - { - "jamesmath", - "", - AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_JAMESMATH, - GF_HASMIDI, - 1 - }, - - { - { - "treehouse", - "", - AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_TREEHOUSE, - GF_HASMIDI, - 0 - }, - - { - { - "greeneggs", - "", - AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - // 32-bit version of the previous entry - { - { - "greeneggs", - "", - AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - { - { - "1stdegree", - "", - AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_1STDEGREE, - GF_HASMIDI, - 0 - }, - - // In The 1st Degree - // French Windows - // From Strangerke - { - { - "1stdegree", - "", - AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"), - Common::FR_FRA, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_1STDEGREE, - GF_HASMIDI, - 0 - }, - - { - { - "csusa", - "", - AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_CSUSA, - 0, - 0 - }, - - { - { - "tortoise", - "Demo v1.0", - AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "tortoise", - "Demo v1.1", - AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthur", - "", - AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - 0, - 0 - }, - - { - { - "arthur", - "Demo", - AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthur", - "Demo", - AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo v1.0", - AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo v1.1", - AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "grandma", - "Demo", - AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "ruff", - "Demo", - AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "ruff", - "Demo", - AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "newkid", - "Demo v1.0", - AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "newkid", - "Demo v1.1", - AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_DEMO, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV1, - GF_DEMO, - 0 - }, - - { - { - "arthurrace", - "", - AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, - - // 32-bit version of the previous entry - { - { - "arthurrace", - "", - AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"), - Common::EN_ANY, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_LIVINGBOOKSV3, - 0, - 0 - }, -#endif - - { AD_TABLE_END_MARKER, 0, 0, 0 } -}; - -////////////////////////////// -//Fallback detection -////////////////////////////// - -static const MohawkGameDescription fallbackDescs[] = { - { - { - "myst", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - 0, - 0 - }, - - { - { - "MakingOfMyst", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MAKINGOF, - 0, - 0 - }, - - { - { - "myst", - "unknown (Masterpiece Edition)", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_MYST, - GF_ME, - 0 - }, - - { - { - "riven", - "unknown", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - 0, - 0 - }, - - { - { - "riven", - "unknown (DVD)", - AD_ENTRY1(0, 0), - Common::UNK_LANG, - Common::kPlatformWindows, - ADGF_NO_FLAGS, - Common::GUIO_NONE - }, - GType_RIVEN, - GF_DVD, - 0 - } -}; - -static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[0], { "MYST.DAT", 0 } }, - { &fallbackDescs[1], { "MAKING.DAT", 0 } }, - { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original - { &fallbackDescs[3], { "a_Data.MHK", 0 } }, - { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } }, - { 0, { 0 } } -}; - -} // End of namespace Mohawk +#include "mohawk/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h new file mode 100644 index 0000000000..ea72574978 --- /dev/null +++ b/engines/mohawk/detection_tables.h @@ -0,0 +1,895 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +namespace Mohawk { + +static const MohawkGameDescription gameDescriptions[] = { + // Myst + // English Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "ae3258c9c90128d274aa6a790b3ad181"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst Demo + // English Windows 3.11 + // From CD-ROM Today July, 1994 + { + { + "myst", + "Demo", + AD_ENTRY1("DEMO.DAT", "c39303dd53fb5c4e7f3c23231c606cd0"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_MYST, + GF_DEMO, + 0, + }, + + // Myst + // German Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "4beb3366ed3f3b9bfb6e81a14a43bdcc"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // German Windows 3.11 + // From LordHoto + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "e0937cca1ab125e48e30dc3cd5046ddf"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // Spanish Windows ? + // From jvprat + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "f7e7d7ca69934f1351b5acd4fe4d44c2"), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // Japanese Windows 3.11 + // From clone2727 + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "032c88e3b7e8db4ca475e7b7db9a66bb"), + Common::JA_JPN, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Myst + // French Windows 3.11 + // From Strangerke + { + { + "myst", + "", + AD_ENTRY1("MYST.DAT", "d631d42567a941c67c78f2e491f4ea58"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0, + }, + + // Making of Myst + // English Windows 3.11 + // From clone2727 + { + { + "MakingOfMyst", + "", + AD_ENTRY1("MAKING.DAT", "f6387e8f0f7b8a3e42c95294315d6a0e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0, + }, + + // Making of Myst + // Japanese Windows 3.11 + // From clone2727 + { + { + "MakingOfMyst", + "", + AD_ENTRY1("MAKING.DAT", "03ff62607e64419ab2b6ebf7b7bcdf63"), + Common::JA_JPN, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0, + }, + + // Myst Masterpiece Edition + // English Windows + // From clone2727 + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // English Windows + // From clone2727 + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "c4cae9f143b5947262e6cb2397e1617e"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // German Windows + // From DrMcCoy (Included in "Myst: Die Trilogie") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "f88e0ace66dbca78eebdaaa1d3314ceb"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Myst Masterpiece Edition + // French Windows + // From gamin (Included in "Myst: La Trilogie") + { + { + "myst", + "Masterpiece Edition", + AD_ENTRY1("MYST.DAT", "aea81633b2d2ae498f09072fb87263b6"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.0 (5CD) + // From clone2727 + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "71145fdecbd68a0cfc292c2fbddf8e08"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.03 (5CD) + // From ST + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "d8ccae34a0e3c709135a73f449b783be"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.? (5CD) + // From jvprat + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "249e8c995d191b03ee94c892c0eac775"), + Common::ES_ESP, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.? (DVD, From "Myst 10th Anniversary Edition") + // From Clone2727 + { + { + "riven", + "DVD", + AD_ENTRY1("a_Data.MHK", "08fcaa5d5a2a01d7a5a6960f497212fe"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version 1.0 (DVD, From "Myst: Die Trilogie") + // From DrMcCoy + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "a5fe1c91a6033eb6ee54b287578b74b9"), + Common::DE_DEU, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version ? (DVD, From "Myst: La Trilogie") + // From gamin + { + { + "riven", + "", + AD_ENTRY1("a_Data.MHK", "aff2a384aaa9a0e0ec51010f708c5c04"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0, + }, + + // Riven: The Sequel to Myst + // Version ? (Demo, From "Prince of Persia Collector's Edition") + // From Clone2727 + { + { + "riven", + "Demo", + AD_ENTRY1("a_Data.MHK", "bae6b03bd8d6eb350d35fd13f0e3139f"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DEMO, + 0, + }, + +#ifdef DETECT_BRODERBUND_TITLES + { + { + "zoombini", + "", + AD_ENTRY1("ZOOMBINI.MHK", "98b758fec55104c096cfd129048be9a6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_ZOOMBINI, + GF_HASMIDI, + 0 + }, + + { + { + "csworld", + "v3.0", + AD_ENTRY1("C2K.MHK", "605fe88380848031bbd0ff84ade6fe40"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSWORLD, + 0, + 0 + }, + + { + { + "csworld", + "v3.5", + AD_ENTRY1("C2K.MHK", "d4857aeb0f5e2e0c4ac556aa74f38c23"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSWORLD, + 0, + 0 + }, + + { + { + "csamtrak", + "", + AD_ENTRY1("AMTRAK.MHK", "2f95301f0bb950d555bb7b0e3b1b7eb1"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSAMTRAK, + 0, + 0 + }, + + { + { + "maggiess", + "", + AD_ENTRY1("MAGGIESS.MHK", "08f75fc8c0390e68fdada5ddb35d0355"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAGGIESS, + 0, + 0 + }, + + { + { + "jamesmath", + "", + AD_ENTRY1("BRODER.MHK", "007299da8b2c6e8ec1cde9598c243024"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_JAMESMATH, + GF_HASMIDI, + 0 + }, + + // This is in the NEWDATA folder, so I assume it's a newer version ;) + { + { + "jamesmath", + "", + AD_ENTRY1("BRODER.MHK", "53c000938a50dca92860fd9b546dd276"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_JAMESMATH, + GF_HASMIDI, + 1 + }, + + { + { + "treehouse", + "", + AD_ENTRY1("MAINROOM.MHK", "12f51894d7f838af639ea9bf1bc8f45b"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_TREEHOUSE, + GF_HASMIDI, + 0 + }, + + { + { + "greeneggs", + "", + AD_ENTRY1("GREEN.LB", "5df8438138186f89e71299d7b4f88d06"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + // 32-bit version of the previous entry + { + { + "greeneggs", + "", + AD_ENTRY1("GREEN32.LB", "5df8438138186f89e71299d7b4f88d06"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + { + { + "1stdegree", + "", + AD_ENTRY1("AL236_1.MHK", "3ba145492a7b8b4dee0ef4222c5639c3"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_1STDEGREE, + GF_HASMIDI, + 0 + }, + + // In The 1st Degree + // French Windows + // From Strangerke + { + { + "1stdegree", + "", + AD_ENTRY1("AL236_1.MHK", "0e0c70b1b702b6ddca61a1192ada1282"), + Common::FR_FRA, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_1STDEGREE, + GF_HASMIDI, + 0 + }, + + { + { + "csusa", + "", + AD_ENTRY1("USAC2K.MHK", "b8c9d3a2586f62bce3a48b50d7a700e9"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_CSUSA, + 0, + 0 + }, + + { + { + "tortoise", + "Demo v1.0", + AD_ENTRY1("TORTOISE.512", "75d9a2f8339e423604a0c6e8177600a6"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "tortoise", + "Demo v1.1", + AD_ENTRY1("TORTOISE.512", "a38c99360e2bea3bfdec418469aef022"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "", + AD_ENTRY1("PAGES.512", "1550a361454ec452fe7d2328aac2003c"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, + + { + { + "arthur", + "Demo", + AD_ENTRY1("PAGES.512", "a4d68cef197af1416921ca5b2e0c1e31"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthur", + "Demo", + AD_ENTRY1("Bookoutline", "7e2691611ff4c7b89c05221736628059"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo v1.0", + AD_ENTRY1("PAGES.512", "95d9f4b035bf5d15c57a9189f231b0f8"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo v1.1", + AD_ENTRY1("GRANDMA.512", "72a4d5fb1b3f06b5f75425635d42ce2e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "grandma", + "Demo", + AD_ENTRY1("Bookoutline", "553c93891b9631d1e1d269599e1efa6c"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "ruff", + "Demo", + AD_ENTRY1("RUFF.512", "2ba1aa65177c816e156db648c398d362"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "ruff", + "Demo", + AD_ENTRY1("Ruff's Bone Demo", "22553ac2ceb2a166bdf1def6ad348532"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "newkid", + "Demo v1.0", + AD_ENTRY1("NEWKID.512", "2b9d94763a50d514c04a3af488934f73"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "newkid", + "Demo v1.1", + AD_ENTRY1("NEWKID.512", "41e975b7390c626f8d1058a34f9d9b2e"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthurrace", + "", + AD_ENTRY1("RACE.LB", "1645f36bcb36e440d928e920aa48c373"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, + + // 32-bit version of the previous entry + { + { + "arthurrace", + "", + AD_ENTRY1("RACE32.LB", "292a05bc48c1dd9583821a4181a02ef2"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV3, + 0, + 0 + }, +#endif + + { AD_TABLE_END_MARKER, 0, 0, 0 } +}; + +////////////////////////////// +//Fallback detection +////////////////////////////// + +static const MohawkGameDescription fallbackDescs[] = { + { + { + "myst", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + 0, + 0 + }, + + { + { + "MakingOfMyst", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MAKINGOF, + 0, + 0 + }, + + { + { + "myst", + "unknown (Masterpiece Edition)", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_MYST, + GF_ME, + 0 + }, + + { + { + "riven", + "unknown", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + 0, + 0 + }, + + { + { + "riven", + "unknown (DVD)", + AD_ENTRY1(0, 0), + Common::UNK_LANG, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_RIVEN, + GF_DVD, + 0 + } +}; + +static const ADFileBasedFallback fileBased[] = { + { &fallbackDescs[0], { "MYST.DAT", 0 } }, + { &fallbackDescs[1], { "MAKING.DAT", 0 } }, + { &fallbackDescs[2], { "MYST.DAT", "Help.dat", 0 } }, // Help system doesn't exist in original + { &fallbackDescs[3], { "a_Data.MHK", 0 } }, + { &fallbackDescs[4], { "a_Data.MHK", "t_Data1.MHK" , 0 } }, + { 0, { 0 } } +}; + +} // End of Namespace Mohawk -- cgit v1.2.3 From 95f55f3b05f2bb3074afba81ee1e1b2c02735203 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 15:49:11 +0000 Subject: Hopefully fixed kOnMe (SCI2) and implemented kIsOnMe (SCI2.1). GK1 and the demo of Phantasmagoria 1 should now be responding to mouse clicks and movement correctly svn-id: r49659 --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel32.cpp | 53 ++++++++++++++++++++++++++++++++++++++++- 3 files changed, 54 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d418fb7998..d1b6ce72bc 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -386,7 +386,7 @@ SciKernelFunction kfunct_mappers[] = { { "Save", kSave, ".*" }, { "List", kList, ".*" }, { "Robot", kRobot, ".*" }, - { "IsOnMe", kOnMe, "iio.*" }, // TODO: this seems right, but verify... + { "IsOnMe", kIsOnMe, "iio.*" }, #endif diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 722473a85b..10225729d7 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -437,6 +437,7 @@ reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); #endif diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index f279d9a66f..139d4188a0 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -33,6 +33,7 @@ #include "sci/graphics/gui.h" #include "sci/graphics/gui32.h" #include "sci/graphics/frameout.h" +#include "sci/graphics/screen.h" #include "common/system.h" @@ -786,13 +787,63 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { // TODO: argv[3] - it's usually 0 Common::Rect nsRect; + // Get the bounding rectangle of the object + nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + // If these are 0, read them from nsLeft, nsTop. This is madness... + if (nsRect.left == 0 && nsRect.top == 0) { + nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); + nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); + } + nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); + nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); + + /* + warning("kOnMe: (%d, %d) on object %04x:%04x (%s), rect (%d, %d, %d, %d), parameter %d", + argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2]), + nsRect.left, nsRect.top, nsRect.right, nsRect.bottom, + argv[3].toUint16()); + */ + + return make_reg(0, nsRect.contains(x, y)); +} + +reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { + // Tests if the cursor is on the passed object, after adjusting the coordinates + // of the object according to the object's plane + + uint16 x = argv[0].toUint16(); + uint16 y = argv[1].toUint16(); + reg_t targetObject = argv[2]; + // TODO: argv[3] - it's usually 0 + Common::Rect nsRect; + // Get the bounding rectangle of the object nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); - //warning("kOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); + // Get the object's plane + reg_t planeObject = readSelector(s->_segMan, targetObject, SELECTOR(plane)); + uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY)); + uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX)); + uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top)); + uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left)); + planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; + planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; + + // Adjust the bounding rectangle of the object by the object's actual X, Y coordinates + uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY); + itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX); + itemY += planeTop; + itemX += planeLeft; + + nsRect.translate(itemX, itemY); + + //warning("kIsOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); return make_reg(0, nsRect.contains(x, y)); } -- cgit v1.2.3 From b04269e7e4ebaf36e654f0604602dd64dee48211 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 16:04:28 +0000 Subject: Fixed GK1 again, including the inventory screen svn-id: r49660 --- engines/sci/engine/kernel32.cpp | 18 +++++++++++------- 1 file changed, 11 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 139d4188a0..2b00daf34a 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -788,16 +788,20 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { Common::Rect nsRect; // Get the bounding rectangle of the object - nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); - nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - // If these are 0, read them from nsLeft, nsTop. This is madness... - if (nsRect.left == 0 && nsRect.top == 0) { - nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); - nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); - } + nsRect.left = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsLeft)); + nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); + uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + if (nsRect.left == itemY && nsRect.top == itemX) { + // FIXME: Why is this happening?? + // Swap the values, as they're inversed(eh???) + nsRect.left = itemX; + nsRect.top = itemY; + } + /* warning("kOnMe: (%d, %d) on object %04x:%04x (%s), rect (%d, %d, %d, %d), parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2]), -- cgit v1.2.3 From 60eced7a81c37d3db7c5fffee2d34463f8313e9d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 16:57:43 +0000 Subject: Cleanup svn-id: r49662 --- engines/sci/engine/kscripts.cpp | 13 ------------- 1 file changed, 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 722d0175d1..c6d73556ba 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -160,19 +160,6 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } - // QFG3 clears clones with underbits set - //if (readSelectorValue(victim_addr, underBits)) - // warning("Clone %04x:%04x was cleared with underBits set", PRINT_REG(victim_addr)); - -#if 0 - if (s->dyn_views) { // Free any widget associated with the clone - GfxWidget *widget = gfxw_set_id(gfxw_remove_ID(s->dyn_views, offset), GFXW_NO_ID); - - if (widget && s->bg_widgets) - s->bg_widgets->add(GFXWC(s->bg_widgets), widget); - } -#endif - victim_obj->markAsFreed(); return s->r_acc; -- cgit v1.2.3 From 303c7b0a8dd0fb120f1fa1ec0abb03b27912e8a5 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 14 Jun 2010 16:58:15 +0000 Subject: Ignore and remove invalid plane and item objects in kFrameout. Fixes loading in-game in GK1. svn-id: r49663 --- engines/sci/graphics/frameout.cpp | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 3cc5ca5447..d794fad39e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -126,6 +126,14 @@ void GfxFrameout::kernelFrameout() { for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { planeObject = _planes[planeNr]; + + // Remove any invalid planes + if (!_segMan->isObject(planeObject)) { + _planes.remove_at(planeNr); + planeNr--; + continue; + } + planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); if (planePriority == -1) // Plane currently not meant to be shown @@ -161,6 +169,14 @@ void GfxFrameout::kernelFrameout() { itemEntry = itemData; for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { itemObject = _screenItems[itemNr]; + + // Remove any invalid items + if (!_segMan->isObject(itemObject)) { + _screenItems.remove_at(itemNr); + itemNr--; + continue; + } + itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane)); if (planeObject == itemPlane) { // Found an item on current plane -- cgit v1.2.3 From 86878450ee26cbf2b4f79e5e54787fe5cce2a10e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 19:37:19 +0000 Subject: Cleanup of the SCI0 object initialization code svn-id: r49666 --- engines/sci/engine/script.cpp | 148 ++++++++++++++++++------------------------ 1 file changed, 63 insertions(+), 85 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 6dfd39a496..c1810df679 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -192,8 +192,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { return; } - _classTable[species].reg.segment = seg; - _classTable[species].reg.offset = classpos; + setClassOffset(species, make_reg(seg, classpos)); } seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; } @@ -231,85 +230,69 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { int objType; - uint32 objLength = 0; + reg_t addr; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - uint16 curOffset = oldScriptHeader ? 2 : 0; - // Now do a first pass through the script objects to find all the object classes - - do { - objType = scr->getHeap(curOffset); - if (!objType) - break; - - objLength = scr->getHeap(curOffset + 2); - curOffset += 4; // skip header - - switch (objType) { - case SCI_OBJ_CLASS: { - int classpos = curOffset - SCRIPT_OBJECT_MAGIC_OFFSET; - int species = scr->getHeap(curOffset - SCRIPT_OBJECT_MAGIC_OFFSET + SCRIPT_SPECIES_OFFSET); - if (species < 0 || species >= (int)segMan->classTableSize()) { - if (species == (int)segMan->classTableSize()) { - // Happens in the LSL2 demo - warning("Applying workaround for an off-by-one invalid species access"); - segMan->resizeClassTable(segMan->classTableSize() + 1); - } else { - error("Invalid species %d(0x%x) not in interval " - "[0,%d) while instantiating script at segment %d\n", - species, species, segMan->classTableSize(), - segmentId); - return; + // The script is initialized in 2 passes. + // Pass 1: creates a lookup table of all used classes + // Pass 2: loads classes and objects + + for (uint16 pass = 0; pass <= 1; pass++) { + uint16 objLength = 0; + uint16 curOffset = oldScriptHeader ? 2 : 0; + + do { + objType = scr->getHeap(curOffset); + if (!objType) + break; + + objLength = scr->getHeap(curOffset + 2); + curOffset += 4; // skip header + addr = make_reg(segmentId, curOffset);; + + switch (objType) { + case SCI_OBJ_CODE: + if (pass == 0) + scr->scriptAddCodeBlock(addr); + break; + case SCI_OBJ_OBJECT: + case SCI_OBJ_CLASS: + if (pass == 0 && objType == SCI_OBJ_CLASS) { + int classpos = curOffset + 8; // SCRIPT_OBJECT_MAGIC_OFFSET + int species = scr->getHeap(classpos); + + if (species == (int)segMan->classTableSize()) { + // Happens in the LSL2 demo + warning("Applying workaround for an off-by-one invalid species access"); + segMan->resizeClassTable(segMan->classTableSize() + 1); + } else if (species < 0 || species > (int)segMan->classTableSize()) { + error("Invalid species %d(0x%x) not in interval " + "[0,%d) while instantiating script at segment %d\n", + species, species, segMan->classTableSize(), + segmentId); + return; + } + + segMan->setClassOffset(species, make_reg(segmentId, classpos)); + } else if (pass == 1) { + Object *obj = scr->scriptObjInit(addr); + obj->initSpecies(segMan, addr); + + if (!obj->initBaseObject(segMan, addr)) { + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + scr->scriptObjRemove(addr); + } } - } - - segMan->setClassOffset(species, make_reg(segmentId, classpos)); - // Set technical class position-- into the block allocated for it - } - break; - - default: - break; - } - - curOffset += objLength - 4; - } while (objType != 0 && curOffset < scr->getScriptSize() - 2); - - // And now a second pass to adjust objects and class pointers, and the general pointers - objLength = 0; - curOffset = oldScriptHeader ? 2 : 0; - - do { - objType = scr->getHeap(curOffset); - if (!objType) - break; - - objLength = scr->getHeap(curOffset + 2); - curOffset += 4; // skip header + break; - reg_t addr = make_reg(segmentId, curOffset); - - switch (objType) { - case SCI_OBJ_CODE: - scr->scriptAddCodeBlock(addr); - break; - case SCI_OBJ_OBJECT: - case SCI_OBJ_CLASS: { // object or class? - Object *obj = scr->scriptObjInit(addr); - obj->initSpecies(segMan, addr); - - if (!obj->initBaseObject(segMan, addr)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); + default: + break; } - } // if object or class - break; - default: - break; - } - curOffset += objLength - 4; - } while (objType != 0 && curOffset < scr->getScriptSize() - 2); + curOffset += objLength - 4; + } while (objType != 0 && curOffset < scr->getScriptSize() - 2); + } // for + } int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) { @@ -411,16 +394,11 @@ void script_uninstantiate(SegManager *segMan, int script_nr) { script_uninstantiate_sci0(segMan, script_nr, segment); // FIXME: Add proper script uninstantiation for SCI 1.1 - if (scr->getLockers()) - return; // if xxx.lockers > 0 - - // Otherwise unload it completely - // Explanation: I'm starting to believe that this work is done by SCI itself. - scr->markDeleted(); - - debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); - - return; + if (!scr->getLockers()) { + // The actual script deletion seems to be done by SCI scripts themselves + scr->markDeleted(); + debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); + } } -- cgit v1.2.3 From 1fde7f1abceb5f7c52982e9b2bf18188037b63d5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 20:45:00 +0000 Subject: Removed the code used for tracking script code block relocations in SCI0-SCI1 games, as we don't actually relocate these blocks, and it was used solely for verification of the exports table. The issue that this warning was created for should no longer occur svn-id: r49669 --- engines/sci/engine/script.cpp | 9 +++---- engines/sci/engine/segment.cpp | 57 +++++++++--------------------------------- engines/sci/engine/segment.h | 13 ---------- 3 files changed, 16 insertions(+), 63 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index c1810df679..cb112a90f9 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -179,7 +179,10 @@ void SegManager::scriptInitialiseLocals(SegmentId segmentId) { void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + const byte *seeker = scr->_heapStart;; + uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + seeker += entrySize; // skip first entry + seeker += 4; // skip header while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) { // -info- selector @@ -251,10 +254,6 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { addr = make_reg(segmentId, curOffset);; switch (objType) { - case SCI_OBJ_CODE: - if (pass == 0) - scr->scriptAddCodeBlock(addr); - break; case SCI_OBJ_OBJECT: case SCI_OBJ_CLASS: if (pass == 0 && objType == SCI_OBJ_CLASS) { diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 492e928e31..879cbc22ee 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -115,7 +115,6 @@ void Script::freeScript() { _bufSize = 0; _objects.clear(); - _codeBlocks.clear(); } void Script::init(int script_nr, ResourceManager *resMan) { @@ -125,8 +124,6 @@ void Script::init(int script_nr, ResourceManager *resMan) { _localsBlock = NULL; _localsCount = 0; - _codeBlocks.clear(); - _markedAsDeleted = false; _nr = script_nr; @@ -188,8 +185,6 @@ void Script::load(ResourceManager *resMan) { memcpy(_heapStart, heap->data, heap->size); } - _codeBlocks.clear(); - _exportTable = 0; _numExports = 0; _synonyms = 0; @@ -310,13 +305,6 @@ bool Script::relocateLocal(SegmentId segment, int location) { return false; } -void Script::scriptAddCodeBlock(reg_t location) { - CodeBlock cb; - cb.pos = location; - cb.size = READ_SCI11ENDIAN_UINT16(_buf + location.offset - 2); - _codeBlocks.push_back(cb); -} - void Script::relocate(reg_t block) { byte *heap = _buf; uint16 heapSize = (uint16)_bufSize; @@ -333,13 +321,14 @@ void Script::relocate(reg_t block) { int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); int exportIndex = 0; + int pos = 0; for (int i = 0; i < count; i++) { - int pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - // This occurs in SCI01/SCI1 games where every usually one export - // value is zero. It seems that in this situation, we should skip - // the export and move to the next one, though the total count - // of valid exports remains the same + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + // This occurs in SCI01/SCI1 games where usually one export value + // is zero. It seems that in this situation, we should skip the + // export and move to the next one, though the total count of valid + // exports remains the same if (!pos) { exportIndex++; pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; @@ -347,37 +336,15 @@ void Script::relocate(reg_t block) { error("Script::relocate(): Consecutive zero exports found"); } + // In SCI0-SCI1, script local variables, objects and code are relocated. We only relocate + // locals and objects here, and ignore relocation of code blocks. In SCI1.1 and newer + // versions, only locals and objects are relocated. if (!relocateLocal(block.segment, pos)) { - bool done = false; - uint k; - - ObjMap::iterator it; + // Not a local? It's probably an object or code block. If it's an object, relocate it. const ObjMap::iterator end = _objects.end(); - for (it = _objects.begin(); !done && it != end; ++it) { + for (ObjMap::iterator it = _objects.begin(); it != end; ++it) if (it->_value.relocate(block.segment, pos, _scriptSize)) - done = true; - } - - // Sanity check for SCI0-SCI1 - if (getSciVersion() < SCI_VERSION_1_1) { - for (k = 0; !done && k < _codeBlocks.size(); k++) { - if (pos >= _codeBlocks[k].pos.offset && - pos < _codeBlocks[k].pos.offset + _codeBlocks[k].size) - done = true; - } - } - - if (!done) { - debug("While processing relocation block %04x:%04x:\n", PRINT_REG(block)); - debug("Relocation failed for index %04x (%d/%d)\n", pos, exportIndex + 1, count); - if (_localsBlock) - debug("- locals: %d at %04x\n", _localsBlock->_locals.size(), _localsOffset); - else - debug("- No locals\n"); - for (it = _objects.begin(), k = 0; it != end; ++it, ++k) - debug("- obj#%d at %04x w/ %d vars\n", k, it->_value.getPos().offset, it->_value.getVarCount()); - debug("Trying to continue anyway...\n"); - } + break; } exportIndex++; diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 045cb119a3..02d4809b70 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -331,11 +331,6 @@ private: reg_t _pos; /**< Object offset within its script; for clones, this is their base */ }; -struct CodeBlock { - reg_t pos; - int size; -}; - typedef Common::HashMap ObjMap; class Script : public SegmentObj { @@ -362,8 +357,6 @@ private: const byte *_synonyms; /**< Synonyms block or 0 if not present*/ uint16 _numSynonyms; /**< Number of entries in the synonyms block */ - Common::Array _codeBlocks; - int _localsOffset; uint16 _localsCount; @@ -402,12 +395,6 @@ public: Object *getObject(uint16 offset); const Object *getObject(uint16 offset) const; - /** - * Informs the segment manager that a code block must be relocated - * @param location Start of block to relocate - */ - void scriptAddCodeBlock(reg_t location); - /** * Initializes an object within the segment manager * @param obj_pos Location (segment, offset) of the object. It must -- cgit v1.2.3 From a6a482b83cb8f924f920ac16c8a48a321e89ecc9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 14 Jun 2010 22:35:49 +0000 Subject: SCI: Added a version of allNotesOff() which sends messages only to the channels used by the associated song instead of all channels svn-id: r49673 --- engines/sci/sound/midiparser_sci.cpp | 34 ++++++++++++++++++++++++++++++++++ engines/sci/sound/midiparser_sci.h | 2 ++ 2 files changed, 36 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index bb353da780..c74a7eae11 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -325,6 +325,40 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { }// switch (info.command()) } +void MidiParser_SCI::allNotesOff() { + if (!_driver) + return; + + int i, j; + + // Turn off all active notes + for (i = 0; i < 128; ++i) { + for (j = 0; j < 16; ++j) { + if ((_active_notes[i] & (1 << j)) && isChannelUsed(j)){ + _driver->send(0x80 | j, i, 0); + } + } + } + + // Turn off all hanging notes + for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { + if (_hanging_notes[i].time_left) { + _driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); + _hanging_notes[i].time_left = 0; + } + } + _hanging_notes_count = 0; + + // To be sure, send an "All Note Off" event (but not all MIDI devices + // support this...). + + for (i = 0; i < 16; ++i) { + if (isChannelUsed(i)) + _driver->send(0xB0 | i, 0x7b, 0); // All notes off + } + + memset(_active_notes, 0, sizeof(_active_notes)); +} byte MidiParser_SCI::midiGetNextChannel(long ticker) { byte curr = 0xFF; diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 8384c74cf6..80401460d2 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -71,6 +71,8 @@ public: jumpToTick(0); } + void allNotesOff(); + void remapChannel(byte channel, byte newChannel) { assert(channel < 0xF); // don't touch special SCI channel 15 assert(newChannel < 0xF); // don't touch special SCI channel 15 -- cgit v1.2.3 From e93f8902a89cb969fd344e49e7086213c8609dbf Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 07:20:53 +0000 Subject: Cleanup of the savegame code: - Added a saveLoadWithSerializer() method to the reg_t class - Moved SegManager::reconstructClones() inside savegame.cpp - Moved SoundCommandParser::syncPlayList() and SoundCommandParser::reconstructPlayList() inside savegame.cpp svn-id: r49683 --- engines/sci/engine/savegame.cpp | 103 +++++++++++++++++++++++++++++-------- engines/sci/engine/seg_manager.cpp | 33 ------------ engines/sci/engine/vm_types.h | 6 +++ engines/sci/sound/soundcmd.cpp | 34 ------------ 4 files changed, 87 insertions(+), 89 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index a7310d2b6a..34457a819f 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -36,6 +36,7 @@ #include "sci/engine/state.h" #include "sci/engine/message.h" #include "sci/engine/savegame.h" +#include "sci/engine/selector.h" #include "sci/engine/vm_types.h" #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/graphics/gui.h" @@ -77,11 +78,6 @@ SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorT static void sync_songlib(Common::Serializer &s, SongLibrary &obj); #endif -static void sync_reg_t(Common::Serializer &s, reg_t &obj) { - s.syncAsUint16LE(obj.segment); - s.syncAsUint16LE(obj.offset); -} - #ifdef USE_OLD_MUSIC_FUNCTIONS static void syncSong(Common::Serializer &s, Song &obj) { s.syncAsSint32LE(obj._handle); @@ -132,7 +128,7 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { fadeTickerStep = 0; } else { // A bit more optimized saving - sync_reg_t(s, soundObj); + soundObj.saveLoadWithSerializer(s); s.syncAsSint16LE(resourceId); s.syncAsSint16LE(dataInc); s.syncAsSint16LE(ticker); @@ -217,7 +213,7 @@ void syncArray(Common::Serializer &s, Common::Array &arr) { template <> void syncWithSerializer(Common::Serializer &s, reg_t &obj) { - sync_reg_t(s, obj); + obj.saveLoadWithSerializer(s); } void SegManager::saveLoadWithSerializer(Common::Serializer &s) { @@ -297,7 +293,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { template <> void syncWithSerializer(Common::Serializer &s, Class &obj) { s.syncAsSint32LE(obj.script); - sync_reg_t(s, obj.reg); + obj.reg.saveLoadWithSerializer(s); } static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) { @@ -396,7 +392,7 @@ void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { void Object::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_flags); - sync_reg_t(s, _pos); + _pos.saveLoadWithSerializer(s); s.skip(4, VER(9), VER(12)); // OBSOLETE: Used to be variable_names_nr s.syncAsSint32LE(_methodCount); // that's actually a uint16 @@ -414,18 +410,18 @@ template <> void syncWithSerializer(Common::Serializer &s, Table::Entry &obj) { s.syncAsSint32LE(obj.next_free); - sync_reg_t(s, obj.first); - sync_reg_t(s, obj.last); + obj.first.saveLoadWithSerializer(s); + obj.last.saveLoadWithSerializer(s); } template <> void syncWithSerializer(Common::Serializer &s, Table::Entry &obj) { s.syncAsSint32LE(obj.next_free); - sync_reg_t(s, obj.pred); - sync_reg_t(s, obj.succ); - sync_reg_t(s, obj.key); - sync_reg_t(s, obj.value); + obj.pred.saveLoadWithSerializer(s); + obj.succ.saveLoadWithSerializer(s); + obj.key.saveLoadWithSerializer(s); + obj.value.saveLoadWithSerializer(s); } #ifdef ENABLE_SCI32 @@ -459,7 +455,7 @@ void syncWithSerializer(Common::Serializer &s, Table >::Entry &o if (s.isSaving()) value = obj.getValue(i); - sync_reg_t(s, value); + value.saveLoadWithSerializer(s); if (s.isLoading()) obj.setValue(i, value); @@ -692,6 +688,40 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { } #endif +void SoundCommandParser::syncPlayList(Common::Serializer &s) { +#ifndef USE_OLD_MUSIC_FUNCTIONS + _music->saveLoadWithSerializer(s); +#endif +} + +void SoundCommandParser::reconstructPlayList(int savegame_version) { +#ifndef USE_OLD_MUSIC_FUNCTIONS + Common::StackLock lock(_music->_mutex); + + const MusicList::iterator end = _music->getPlayListEnd(); + for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { + if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) { + (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion); + _music->soundInitSnd(*i); + } else { + (*i)->soundRes = 0; + } + if ((*i)->status == kSoundPlaying) { + if (savegame_version < 14) { + (*i)->dataInc = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(dataInc)); + (*i)->signal = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal)); + + if (_soundVersion >= SCI_VERSION_1_LATE) + (*i)->volume = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol)); + } + + cmdPlaySound((*i)->soundObj, 0); + } + } + +#endif +} + #ifdef ENABLE_SCI32 void ArrayTable::saveLoadWithSerializer(Common::Serializer &ser) { if (ser.getVersion() < 18) @@ -735,7 +765,13 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename return 0; } -// TODO: Move thie function to a more appropriate place, such as vm.cpp or script.cpp +void SegManager::reconstructStack(EngineState *s) { + DataStack *stack = (DataStack *)(_heap[findSegmentByType(SEG_TYPE_STACK)]); + s->stack_base = stack->_entries; + s->stack_top = s->stack_base + stack->_capacity; +} + +// TODO: Move this function to a more appropriate place, such as vm.cpp or script.cpp void SegManager::reconstructScripts(EngineState *s) { uint i; @@ -771,12 +807,35 @@ void SegManager::reconstructScripts(EngineState *s) { } } -void SegManager::reconstructStack(EngineState *s) { - SegmentId stack_seg = findSegmentByType(SEG_TYPE_STACK); - DataStack *stack = (DataStack *)(_heap[stack_seg]); +void SegManager::reconstructClones() { + for (uint i = 0; i < _heap.size(); i++) { + SegmentObj *mobj = _heap[i]; + if (mobj && mobj->getType() == SEG_TYPE_CLONES) { + CloneTable *ct = (CloneTable *)mobj; + + for (uint j = 0; j < ct->_table.size(); j++) { + // Check if the clone entry is used + uint entryNum = (uint)ct->first_free; + bool isUsed = true; + while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) { + if (entryNum == j) { + isUsed = false; + break; + } + entryNum = ct->_table[entryNum].next_free; + } - s->stack_base = stack->_entries; - s->stack_top = stack->_entries + stack->_capacity; + if (!isUsed) + continue; + + CloneTable::Entry &seeker = ct->_table[j]; + const Object *baseObj = getObject(seeker.getSpeciesSelector()); + seeker.cloneFromObject(baseObj); + if (!baseObj) + warning("Clone entry without a base class: %d", j); + } // end for + } // end if + } // end for } #ifdef USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 8d51b27099..96670b5aeb 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -476,39 +476,6 @@ Clone *SegManager::allocateClone(reg_t *addr) { return &(table->_table[offset]); } -void SegManager::reconstructClones() { - for (uint i = 0; i < _heap.size(); i++) { - if (_heap[i]) { - SegmentObj *mobj = _heap[i]; - if (mobj->getType() == SEG_TYPE_CLONES) { - CloneTable *ct = (CloneTable *)mobj; - - for (uint j = 0; j < ct->_table.size(); j++) { - // Check if the clone entry is used - uint entryNum = (uint)ct->first_free; - bool isUsed = true; - while (entryNum != ((uint) CloneTable::HEAPENTRY_INVALID)) { - if (entryNum == j) { - isUsed = false; - break; - } - entryNum = ct->_table[entryNum].next_free; - } - - if (!isUsed) - continue; - - CloneTable::Entry &seeker = ct->_table[j]; - const Object *baseObj = getObject(seeker.getSpeciesSelector()); - seeker.cloneFromObject(baseObj); - if (!baseObj) - warning("Clone entry without a base class: %d", j); - } // end for - } // end if - } // end if - } // end for -} - List *SegManager::allocateList(reg_t *addr) { ListTable *table; int offset; diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 29dc798c35..614b6f247d 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -27,6 +27,7 @@ #define SCI_ENGINE_VM_TYPES_H #include "common/scummsys.h" +#include "common/serializer.h" namespace Sci { @@ -56,6 +57,11 @@ struct reg_t { int16 toSint16() const { return (int16) offset; } + + void saveLoadWithSerializer(Common::Serializer &s) { + s.syncAsUint16LE(segment); + s.syncAsUint16LE(offset); + } }; static inline reg_t make_reg(SegmentId segment, uint16 offset) { diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 71fc2b7ef0..e317796aad 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -1088,40 +1088,6 @@ void SoundCommandParser::clearPlayList() { #endif } -void SoundCommandParser::syncPlayList(Common::Serializer &s) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - _music->saveLoadWithSerializer(s); -#endif -} - -void SoundCommandParser::reconstructPlayList(int savegame_version) { -#ifndef USE_OLD_MUSIC_FUNCTIONS - Common::StackLock lock(_music->_mutex); - - const MusicList::iterator end = _music->getPlayListEnd(); - for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { - if ((*i)->resourceId && _resMan->testResource(ResourceId(kResourceTypeSound, (*i)->resourceId))) { - (*i)->soundRes = new SoundResource((*i)->resourceId, _resMan, _soundVersion); - _music->soundInitSnd(*i); - } else { - (*i)->soundRes = 0; - } - if ((*i)->status == kSoundPlaying) { - if (savegame_version < 14) { - (*i)->dataInc = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(dataInc)); - (*i)->signal = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal)); - - if (_soundVersion >= SCI_VERSION_1_LATE) - (*i)->volume = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol)); - } - - cmdPlaySound((*i)->soundObj, 0); - } - } - -#endif -} - void SoundCommandParser::printPlayList(Console *con) { #ifndef USE_OLD_MUSIC_FUNCTIONS _music->printPlayList(con); -- cgit v1.2.3 From 60d8cc5180c4033978e1bb38e6cc26dab8a126b2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 07:21:52 +0000 Subject: Removed the now unused EngineState parameter of script_adjust_opcode_formats(), as well as an obsolete TODO svn-id: r49684 --- engines/sci/engine/script.cpp | 3 +-- engines/sci/engine/script.h | 2 +- engines/sci/sci.cpp | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index cb112a90f9..19e0b6f81a 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -95,8 +95,7 @@ opcode_format g_opcode_formats[128][4] = { // TODO: script_adjust_opcode_formats should probably be part of the // constructor (?) of a VirtualMachine or a ScriptManager class. -void script_adjust_opcode_formats(EngineState *s) { - // TODO: Check that this is correct +void script_adjust_opcode_formats() { if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) { g_opcode_formats[op_lofsa][0] = Script_Offset; g_opcode_formats[op_lofss][0] = Script_Offset; diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index e94e9f64e6..fe92dabe58 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -202,7 +202,7 @@ enum sci_opcodes { extern opcode_format g_opcode_formats[128][4]; -void script_adjust_opcode_formats(EngineState *s); +void script_adjust_opcode_formats(); } // End of namespace Sci diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index ee2f5845a2..e8847f380b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -229,7 +229,7 @@ Common::Error SciEngine::run() { _kernel->loadKernelNames(_features); // Must be called after game_init() - script_adjust_opcode_formats(_gamestate); + script_adjust_opcode_formats(); SciVersion soundVersion = _features->detectDoSoundType(); -- cgit v1.2.3 From 0dab9e0e1f39b856a0b996dfa2c3103fe0dbfe2f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 07:25:09 +0000 Subject: Reorganized functions a bit svn-id: r49685 --- engines/sci/engine/savegame.cpp | 55 +++++++++++++++++++++-------------------- 1 file changed, 28 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 34457a819f..89bfa5302d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -738,33 +738,6 @@ void StringTable::saveLoadWithSerializer(Common::Serializer &ser) { } #endif -#pragma mark - - - -int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { - TimeDate curTime; - g_system->getTimeAndDate(curTime); - - SavegameMetadata meta; - meta.savegame_version = CURRENT_SAVEGAME_VERSION; - meta.savegame_name = savename; - meta.game_version = version; - meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); - meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); - - if (s->executionStackBase) { - warning("Cannot save from below kernel function"); - return 1; - } - - Common::Serializer ser(0, fh); - sync_SavegameMetadata(ser, meta); - Graphics::saveThumbnail(*fh); - s->saveLoadWithSerializer(ser); // FIXME: Error handling? - - return 0; -} - void SegManager::reconstructStack(EngineState *s) { DataStack *stack = (DataStack *)(_heap[findSegmentByType(SEG_TYPE_STACK)]); s->stack_base = stack->_entries; @@ -874,6 +847,34 @@ static void reconstruct_sounds(EngineState *s) { } #endif + +#pragma mark - + + +int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { + TimeDate curTime; + g_system->getTimeAndDate(curTime); + + SavegameMetadata meta; + meta.savegame_version = CURRENT_SAVEGAME_VERSION; + meta.savegame_name = savename; + meta.game_version = version; + meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); + meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); + + if (s->executionStackBase) { + warning("Cannot save from below kernel function"); + return 1; + } + + Common::Serializer ser(0, fh); + sync_SavegameMetadata(ser, meta); + Graphics::saveThumbnail(*fh); + s->saveLoadWithSerializer(ser); // FIXME: Error handling? + + return 0; +} + void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { #ifdef USE_OLD_MUSIC_FUNCTIONS SongLibrary temp; -- cgit v1.2.3 From 9a1db3f77092f13829604701b419ffc38577388b Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Tue, 15 Jun 2010 08:21:39 +0000 Subject: Add support for SCI32 segment types to seg_table and vr debug commands svn-id: r49686 --- engines/sci/console.cpp | 58 ++++++++++++++++++++++++++++++++---------- engines/sci/engine/segment.cpp | 2 +- engines/sci/engine/segment.h | 1 + 3 files changed, 47 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 6c022bb631..a3e33b13c8 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1095,6 +1095,14 @@ bool Console::cmdSaveGame(int argc, const char **argv) { delete out; } + out->finalize(); + if (out->err()) { + delete out; + warning("Writing the savegame failed."); + } else { + delete out; + } + return true; } @@ -1420,6 +1428,16 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { DebugPrintf("F string fragments"); break; +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); + break; + + case SEG_TYPE_STRING: + DebugPrintf("T SCI32 strings (%d)", (*(StringTable *)mobj).entries_used); + break; +#endif + default: DebugPrintf("I Invalid (type = %x)", mobj->getType()); break; @@ -2180,26 +2198,40 @@ bool Console::cmdViewReference(int argc, const char **argv) { printObject(reg); break; case KSIG_REF: { - int size; - const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); - size = block.maxSize; + switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { + case SEG_TYPE_STRING: { + const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); + Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); + break; + } + case SEG_TYPE_ARRAY: { + const SciArray *array = _engine->_gamestate->_segMan->lookupArray(reg); + Common::hexdump((const byte *) array->getRawData(), array->getSize(), 16, 0); + break; + } + default: { + int size; + const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); + size = block.maxSize; - DebugPrintf("raw data\n"); + DebugPrintf("raw data\n"); - if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { - DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); - reg_end = NULL_REG; - } + if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { + DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); + reg_end = NULL_REG; + } - if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) - size = reg_end.offset - reg.offset; + if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) + size = reg_end.offset - reg.offset; - if (reg_end.segment != 0) - DebugPrintf("Block size less than or equal to %d\n", size); + if (reg_end.segment != 0) + DebugPrintf("Block size less than or equal to %d\n", size); - Common::hexdump(block.raw, size, 16, 0); + Common::hexdump(block.raw, size, 16, 0); + } } break; + } case KSIG_ARITHMETIC: DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); break; diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 879cbc22ee..a6154e7512 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -435,7 +435,7 @@ bool Script::isValidOffset(uint16 offset) const { SegmentRef Script::dereference(reg_t pointer) { if (pointer.offset > _bufSize) { - warning("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", + error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", PRINT_REG(pointer), (uint)_bufSize); return SegmentRef(); } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 02d4809b70..61f1c7b3c9 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -802,6 +802,7 @@ public: byte getType() const { return _type; } uint32 getSize() const { return _size; } T *getRawData() { return _data; } + const T *getRawData()const { return _data; } protected: int8 _type; -- cgit v1.2.3 From 0ad3bedf9880b51e40459df4e33547bf234eeb4f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 08:25:51 +0000 Subject: Added a signature of the game itself inside saved games (the size of script 0, as well as the offset of the game object, which are unique for each game), to prevent users from loading saved games across different versions of the same game. In the cases where we can't load a saved game, throw a nice GUI dialog instead of a console warning svn-id: r49687 --- engines/sci/engine/savegame.cpp | 35 +++++++++++++++++++++++++++++++++-- engines/sci/engine/savegame.h | 4 +++- 2 files changed, 36 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 89bfa5302d..155c5fad86 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -53,6 +53,8 @@ #include "sci/graphics/gui32.h" #endif +#include "gui/message.h" + namespace Sci { @@ -307,6 +309,13 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) s.skip(4, VER(9), VER(9)); // obsolete: used to be game version s.syncAsSint32LE(obj.savegame_date); s.syncAsSint32LE(obj.savegame_time); + if (s.getVersion() < 22) { + obj.game_object_offset = 0; + obj.script0_size = 0; + } else { + s.syncAsUint16LE(obj.game_object_offset); + s.syncAsUint16LE(obj.script0_size); + } } void EngineState::saveLoadWithSerializer(Common::Serializer &s) { @@ -862,6 +871,10 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename meta.savegame_date = ((curTime.tm_mday & 0xFF) << 24) | (((curTime.tm_mon + 1) & 0xFF) << 16) | ((curTime.tm_year + 1900) & 0xFFFF); meta.savegame_time = ((curTime.tm_hour & 0xFF) << 16) | (((curTime.tm_min) & 0xFF) << 8) | ((curTime.tm_sec) & 0xFF); + Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); + meta.script0_size = script0->size; + meta.game_object_offset = g_sci->getGameObject().offset; + if (s->executionStackBase) { warning("Cannot save from below kernel function"); return 1; @@ -892,15 +905,33 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { if ((meta.savegame_version < MINIMUM_SAVEGAME_VERSION) || (meta.savegame_version > CURRENT_SAVEGAME_VERSION)) { + /* if (meta.savegame_version < MINIMUM_SAVEGAME_VERSION) - warning("Old savegame version detected- can't load"); + warning("Old savegame version detected, unable to load it"); else - warning("Savegame version is %d- maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION); + warning("Savegame version is %d, maximum supported is %0d", meta.savegame_version, CURRENT_SAVEGAME_VERSION); + */ + + GUI::MessageDialog dialog("The format of this saved game is obsolete, unable to load it", "OK"); + dialog.runModal(); s->r_acc = make_reg(0, 1); // signal failure return; } + if (meta.game_object_offset > 0 && meta.script0_size > 0) { + Resource *script0 = g_sci->getResMan()->findResource(ResourceId(kResourceTypeScript, 0), false); + if (script0->size != meta.script0_size || g_sci->getGameObject().offset != meta.game_object_offset) { + //warning("This saved game was created with a different version of the game, unable to load it"); + + GUI::MessageDialog dialog("This saved game was created with a different version of the game, unable to load it", "OK"); + dialog.runModal(); + + s->r_acc = make_reg(0, 1); // signal failure + return; + } + } + if (meta.savegame_version >= 12) { // We don't need the thumbnail here, so just read it and discard it Graphics::Surface *thumbnail = new Graphics::Surface(); diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index e7e8fff999..c8c7738fdf 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -36,7 +36,7 @@ namespace Sci { struct EngineState; enum { - CURRENT_SAVEGAME_VERSION = 21, + CURRENT_SAVEGAME_VERSION = 22, MINIMUM_SAVEGAME_VERSION = 9 }; @@ -47,6 +47,8 @@ struct SavegameMetadata { Common::String game_version; int savegame_date; int savegame_time; + uint16 game_object_offset; + uint16 script0_size; }; -- cgit v1.2.3 From ba3c43498b12b4c5855030bea7ab9e613c55d4ac Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 08:39:03 +0000 Subject: - Swapped the return value of gamestate_save (false = failed, true = succeeded) - Removed some duplicate code inside Console::cmdSaveGame() svn-id: r49688 --- engines/sci/console.cpp | 10 +--------- engines/sci/detection.cpp | 2 +- engines/sci/engine/kfile.cpp | 2 +- engines/sci/engine/savegame.cpp | 6 +++--- engines/sci/engine/savegame.h | 2 +- 5 files changed, 7 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index a3e33b13c8..0c017af281 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1085,7 +1085,7 @@ bool Console::cmdSaveGame(int argc, const char **argv) { } // TODO: enable custom descriptions? force filename into a specific format? - if (gamestate_save(_engine->_gamestate, out, "debugging", version)) { + if (!gamestate_save(_engine->_gamestate, out, "debugging", version)) { DebugPrintf("Saving the game state to '%s' failed\n", argv[1]); } else { out->finalize(); @@ -1095,14 +1095,6 @@ bool Console::cmdSaveGame(int argc, const char **argv) { delete out; } - out->finalize(); - if (out->err()) { - delete out; - warning("Writing the savegame failed."); - } else { - delete out; - } - return true; } diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 7f0a27c14f..b402f7cc0b 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -659,7 +659,7 @@ Common::Error SciEngine::saveGameState(int slot, const char *desc) { return Common::kWritingFailed; } - if (gamestate_save(_gamestate, out, desc, version)) { + if (!gamestate_save(_gamestate, out, desc, version)) { warning("Saving the game state to '%s' failed", fileName.c_str()); return Common::kWritingFailed; } else { diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 3e0ecd1a28..ad188f503a 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -543,7 +543,7 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - if (gamestate_save(s, out, game_description.c_str(), version.c_str())) { + if (!gamestate_save(s, out, game_description.c_str(), version.c_str())) { warning("Saving the game failed."); s->r_acc = NULL_REG; } else { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 155c5fad86..d2bd955793 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -860,7 +860,7 @@ static void reconstruct_sounds(EngineState *s) { #pragma mark - -int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { +bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename, const char *version) { TimeDate curTime; g_system->getTimeAndDate(curTime); @@ -877,7 +877,7 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename if (s->executionStackBase) { warning("Cannot save from below kernel function"); - return 1; + return false; } Common::Serializer ser(0, fh); @@ -885,7 +885,7 @@ int gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savename Graphics::saveThumbnail(*fh); s->saveLoadWithSerializer(ser); // FIXME: Error handling? - return 0; + return true; } void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index c8c7738fdf..aa22d42135 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -59,7 +59,7 @@ struct SavegameMetadata { * @param savename The description of the savegame * @return 0 on success, 1 otherwise */ -int gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version); +bool gamestate_save(EngineState *s, Common::WriteStream *save, const char *savename, const char *version); /** * Restores a game state from a directory. -- cgit v1.2.3 From e64eb71ce86663c479bbbb94072fee94a015eecb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 09:11:26 +0000 Subject: Properly reconstruct the running stack when restoring (a regression from commits #49376 and #49525), some formatting svn-id: r49689 --- engines/sci/engine/savegame.cpp | 1 + engines/sci/engine/segment.h | 2 +- engines/sci/engine/state.cpp | 4 ++-- 3 files changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d2bd955793..02fdde5622 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -994,6 +994,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { #endif s->abortScriptProcessing = kAbortLoadGame; + s->shrinkStackToBase(); } bool get_savegame_metadata(Common::SeekableReadStream *stream, SavegameMetadata *meta) { diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 61f1c7b3c9..253d94cc53 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -802,7 +802,7 @@ public: byte getType() const { return _type; } uint32 getSize() const { return _size; } T *getRawData() { return _data; } - const T *getRawData()const { return _data; } + const T *getRawData() const { return _data; } protected: int8 _type; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 41f263bb62..1c8113e5e4 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -90,13 +90,13 @@ void EngineState::reset(bool isRestoring) { _fileHandles.resize(5); - stack_base = 0; - stack_top = 0; abortScriptProcessing = kAbortNone; } executionStackBase = 0; _executionStackPosChanged = false; + stack_base = 0; + stack_top = 0; restAdjust = 0; -- cgit v1.2.3 From 13aba8747a8293388640211233375cc4e7ecaf95 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 10:09:42 +0000 Subject: Throttle screen updates to 60fps in some screen transition effects as well svn-id: r49690 --- engines/sci/event.cpp | 4 +--- engines/sci/graphics/paint16.cpp | 14 ++++++++++++-- engines/sci/graphics/transitions.cpp | 16 ++++++++++++---- 3 files changed, 25 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index ed9c4bfd0d..7a55555a70 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -321,9 +321,7 @@ sciEvent EventManager::get(unsigned int mask) { // Update the screen here, since it's called very often. // Throttle the screen update rate to 60fps. - uint32 curTime = g_system->getMillis(); - uint32 duration = curTime - g_sci->getEngineState()->_screenUpdateTime; - if (duration >= 1000 / 60) { + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { g_system->updateScreen(); g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); } diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index ff4f3bec52..6a13f792cb 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -561,11 +561,21 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) { if (directions & SCI_SHAKE_DIRECTION_VERTICAL) _screen->setVerticalShakePos(10); // TODO: horizontal shakes - g_system->updateScreen(); + + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + _gui->wait(3); if (directions & SCI_SHAKE_DIRECTION_VERTICAL) _screen->setVerticalShakePos(0); - g_system->updateScreen(); + + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + _gui->wait(3); } } diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 1976326aa9..f73525caaf 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -440,8 +440,12 @@ void GfxTransitions::scroll(int16 number) { } stepNr++; } - if ((stepNr & 1) == 0) - g_system->updateScreen(); + if ((stepNr & 1) == 0) { + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + } break; case SCI_TRANSITIONS_SCROLL_RIGHT: @@ -461,8 +465,12 @@ void GfxTransitions::scroll(int16 number) { } stepNr++; } - if ((stepNr & 1) == 0) - g_system->updateScreen(); + if ((stepNr & 1) == 0) { + if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { + g_system->updateScreen(); + g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); + } + } break; case SCI_TRANSITIONS_SCROLL_UP: -- cgit v1.2.3 From 28f6f7a3f0225406162b3dbf009ace4500f6e87c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:14:04 +0000 Subject: Split out detection tables for Cine engine svn-id: r49691 --- engines/cine/detection.cpp | 491 +------------------------------------- engines/cine/detection_tables.h | 513 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 514 insertions(+), 490 deletions(-) create mode 100644 engines/cine/detection_tables.h (limited to 'engines') diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index 1cf9ed5fad..bcc4951140 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -23,8 +23,6 @@ * */ - - #include "base/plugins.h" #include "engines/advancedDetector.h" @@ -62,494 +60,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {0, 0, Common::kPlatformUnknown} }; -namespace Cine { - -using Common::GUIO_NONE; - -static const CINEGameDescription gameDescriptions[] = { - { - { - "fw", - "", - AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - // This is a CD version of Future Wars published by Sony. - // This version has a crypted AUTO00.PRC. - { - { - "fw", - "Sony CD version", - { - { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1}, - { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1}, - { NULL, 0, NULL, 0} - }, - Common::EN_USA, - Common::kPlatformPC, - ADGF_CD, - GUIO_NONE - }, - GType_FW, - GF_CD | GF_CRYPTED_BOOT_PRC, - }, - - { - // This is the version included in the UK "Classic Collection" - { - "fw", - "", - AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"), - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { // Amiga "Interplay" labeled version - { - "fw", - "", - AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"), - Common::EN_USA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"), - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - GF_ALT_FONT, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"), - Common::ES_ESP, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"), - Common::FR_FRA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"), - Common::IT_ITA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "Demo", - { - { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1}, - { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_DEMO, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"), - Common::EN_ANY, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "fw", - "", - AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"), - Common::FR_FRA, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_FW, - 0, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"), - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - // This is a 16 color PC version (It came on three 720kB 3.5" disks). - // The protagonist is named John Glames in this version. - { - "os", - "", - AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"), - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"), - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"), - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - GF_CD, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "256 colors", - { - { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1}, - { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1}, - { NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - GF_CD, - }, - - { - { - "os", - "256 colors", - AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "alt", - AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"), - Common::EN_USA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"), - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"), - Common::ES_ESP, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"), - Common::FR_FRA, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "Demo", - AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"), - Common::EN_GRB, - Common::kPlatformAmiga, - ADGF_DEMO, - GUIO_NONE - }, - GType_OS, - GF_DEMO, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"), - Common::EN_GRB, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { - { - "os", - "", - AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"), - Common::FR_FRA, - Common::kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GType_OS, - 0, - }, - - { AD_TABLE_END_MARKER, 0, 0 } -}; - -} // End of namespace Cine +#include "cine/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure diff --git a/engines/cine/detection_tables.h b/engines/cine/detection_tables.h new file mode 100644 index 0000000000..6e450ebc80 --- /dev/null +++ b/engines/cine/detection_tables.h @@ -0,0 +1,513 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +namespace Cine { + +using Common::GUIO_NONE; + +static const CINEGameDescription gameDescriptions[] = { + { + { + "fw", + "", + AD_ENTRY1("part01", "61d003202d301c29dd399acfb1354310"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + // This is a CD version of Future Wars published by Sony. + // This version has a crypted AUTO00.PRC. + { + { + "fw", + "Sony CD version", + { + { "AUTO00.PRC", 0, "4fe1e7930b38e3c63f0f2474d471bf8f", -1}, + { "PART01", 0, "61d003202d301c29dd399acfb1354310", -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_USA, + Common::kPlatformPC, + ADGF_CD, + GUIO_NONE + }, + GType_FW, + GF_CD | GF_CRYPTED_BOOT_PRC, + }, + + { + // This is the version included in the UK "Classic Collection" + { + "fw", + "", + AD_ENTRY1("part01", "91d7271155520eae6915a9dd2dac120c"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "f5e98fcca3fb5e7afa284c81c39d8b14"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "570109f965c7f53984b98c83d86eb206"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "5d1acb97abe9591f9008e00d07add95a"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "57afd280b598b4180fda6689fbedc4b8"), + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { // Amiga "Interplay" labeled version + { + "fw", + "", + AD_ENTRY1("part01", "a17a5eb15200c63276d486a88263ccd0"), + Common::EN_USA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "3a87a913e0e33963a48a7f822ca0eb0e"), + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + GF_ALT_FONT, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "5ad0007ccd5f7b3dd6b15ea7f281f9e1"), + Common::ES_ESP, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "460f2da8793bc581a2d4b6fc19ccb5ae"), + Common::FR_FRA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "1c8e5207743172134409ac58860021af"), + Common::IT_ITA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "Demo", + { + { "demo", 0, "0f50767cd964e302d3af0ba2528df8c4", -1}, + { "demo.prc", 0, "d2ac3a743d288359c63644ea7071edae", -1}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "36050db13af57e462ca1adc4df99de4e"), + Common::EN_ANY, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "fw", + "", + AD_ENTRY1("part01", "ef245573b7dab0d4825ceb98e37cef4d"), + Common::FR_FRA, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_FW, + 0, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "d6752e7d25924cb866b61eb7cb0c8b56"), + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + // This is a 16 color PC version (It came on three 720kB 3.5" disks). + // The protagonist is named John Glames in this version. + { + "os", + "", + AD_ENTRY1("procs1", "9629129b86979fa592c1787385bf3695"), + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "d8c3a9d05a63e4cfa801826a7063a126"), + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "862a75d76fb7fffec30e52be9ad1c474"), + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + GF_CD, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "39b91ae35d1297ce0a76a1a803ca1593"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "74c2dabd9d212525fca8875a5f6d8994"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "256 colors", + { + { "procs1", 0, "74c2dabd9d212525fca8875a5f6d8994", -1}, + { "sds1", 0, "75443ba39cdc95667e07d7118e5c151c", -1}, + { NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + GF_CD, + }, + + { + { + "os", + "256 colors", + AD_ENTRY1("procs00", "f143567f08cfd1a9b1c9a41c89eadfef"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs1", "da066e6b8dd93f2502c2a3755f08dc12"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "a9da5531ead0ebf9ad387fa588c0cbb0"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "alt", + AD_ENTRY1("procs0", "8a429ced2f4acff8a15ae125174042e8"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "d5f27e33fc29c879f36f15b86ccfa58c"), + Common::EN_USA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "8b7dce249821d3a62b314399c4334347"), + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "35fc295ddd0af9da932d256ba799a4b0"), + Common::ES_ESP, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "d4ea4a97e01fa67ea066f9e785050ed2"), + Common::FR_FRA, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "Demo", + AD_ENTRY1("demo", "8d3a750d1c840b1b1071e42f9e6f6aa2"), + Common::EN_GRB, + Common::kPlatformAmiga, + ADGF_DEMO, + GUIO_NONE + }, + GType_OS, + GF_DEMO, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "1501d5ae364b2814a33ed19347c3fcae"), + Common::EN_GRB, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { + { + "os", + "", + AD_ENTRY1("procs0", "2148d25de3219dd4a36580ca735d0afa"), + Common::FR_FRA, + Common::kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GType_OS, + 0, + }, + + { AD_TABLE_END_MARKER, 0, 0 } +}; + +} // End of namespace Cine -- cgit v1.2.3 From 977b1561d4a13b980ab293316133c9e029b348b8 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:14:38 +0000 Subject: Split out detection tables for Gob engine svn-id: r49692 --- engines/gob/detection.cpp | 4989 +-------------------------------------- engines/gob/detection_tables.h | 5013 ++++++++++++++++++++++++++++++++++++++++ 2 files changed, 5014 insertions(+), 4988 deletions(-) create mode 100644 engines/gob/detection_tables.h (limited to 'engines') diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index feb76fe091..3d83f12e39 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -87,4994 +87,7 @@ static const ADObsoleteGameID obsoleteGameIDsTable[] = { {0, 0, kPlatformUnknown} }; -namespace Gob { - -using Common::GUIO_NOSPEECH; -using Common::GUIO_NOSUBTITLES; -using Common::GUIO_NONE; - -static const GOBGameDescription gameDescriptions[] = { - { // Supplied by Florian Zeitz on scummvm-devel - { - "gob1", - "EGA", - AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesEGA, - 0, 0, 0 - }, - { - { - "gob1", - "EGA", - AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesEGA, - 0, 0, 0 - }, - { // Supplied by Theruler76 in bug report #1201233 - { - "gob1", - "VGA", - AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891864 - { - "gob1", - "VGA", - AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raina in the forums - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), - EN_ANY, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - EN_ANY, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - DE_DEU, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - IT_ITA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob1", - "", - AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), - ES_ESP, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "gob1", - "", - { - {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob1", - "", - { - {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, - {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.000 version. - { - "gob1cd", - "v1.000", - AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // CD 1.02 version. Multilingual - { - "gob1cd", - "v1.02", - AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob1cd", - "v1.02", - AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob1", - "Demo", - AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "Interactive Demo", - AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2785958 - { - "gob1", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob1", - "", - AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121), - FR_FRA, - kPlatformCDi, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesAdLib, - 0, "AVT003.TOT", 0 - }, - { // Supplied by fac76 in bug report #1883808 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2602057 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"), - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by bgk in bug report #1706861 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by fac76 in bug report #1673397 - { - "gob2", - "", - { - {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443}, - {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, - {0, 0, 0, 0} - }, - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by koalet in bug report #2478585 - { - "gob2", - "", - { - {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275}, - {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891867 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by blackwhiteeagle in bug report #1605235 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2602017 - { - "gob2", - "", - AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by arcepi in bug report #1659884 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "", - { - {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob2", - "", - AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2cd", - "v1.000", - AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2cd", - "v2.01", - AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob2cd", - "v1.02", - AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob2", - "Non-Interactive Demo", - AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, "usa.tot", 0 - }, - { - { - "gob2", - "Interactive Demo", - AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob2", - "Interactive Demo", - AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by polluks in bug report #1895126 - { - "gob2", - "Interactive Demo", - AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063), - UNK_LANG, - kPlatformAmiga, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - { - {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, - {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by vampir_raziel in bug report #1658373 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2563539 - { - "ween", - "", - { - {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458}, - {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by pwigren in bug report #1764174 - { - "ween", - "", - { - {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, - {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cybot_tmin in bug report #1667743 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "", - AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cartman_ on #scummvm - { - "ween", - "", - AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by glorfindel in bugreport #1722142 - { - "ween", - "", - AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "ween", - "Demo", - AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, "show.tot", 0 - }, - { - { - "ween", - "Demo", - AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"), - EN_USA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWeen, - kFeaturesAdLib, - 0, "show.tot", 0 - }, - { - { - "bargon", - "", - AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by Trekky in the forums - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109), - FR_FRA, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by cesardark in bug #1681649 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by paul66 in bug #1692667 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by pwigren in bugreport #1764174 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by kizkoool in bugreport #2089734 - { - "bargon", - "", - AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { // Supplied by glorfindel in bugreport #1722142 - { - "bargon", - "Fanmade", - AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - { - {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490}, - {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248}, - {0, 0, 0, 0} - }, - UNK_LANG, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { // Found in french ADI 2 Francais-Maths CM1 - { - "littlered", - "", - AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib | kFeaturesEGA, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by cartman_ on #scummvm - { - "lit", - "", - AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2105220 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by koalet in bug report #2479034 - { - "lit", - "", - { - {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310}, - {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2093672 - { - "lit", - "", - AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "", - AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in french ADI 2.6 Francais-Maths 4e - { - "lit", - "", - AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit1", - "Full install", - { - {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, - {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit1", - "Light install", - { - {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, - {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit2", - "Light install", - AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit2", - "Full install", - { - {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318}, - {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "lit", - "Demo", - AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - "demo.stk", "demo.tot", 0 - }, - { - { - "lit", - "Non-interactive Demo", - AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - "demo.stk", "demo.tot", 0 - }, - { - { - "fascination", - "CD Version (Censored)", - AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES - }, - kGameTypeFascination, - kFeaturesCD, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "intro.stk", 0, 0 - }, - { // Supplied by sanguine - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { // Supplied by windlepoons in bug report #2809247 - { - "fascination", - "VGA 3 disks edition", - AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "VGA", - AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesAdLib, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005), - FR_FRA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931), - IT_ITA, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "fascination", - "", - AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964), - EN_ANY, - kPlatformAtariST, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { - { - "geisha", - "", - AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { - { - "geisha", - "", - AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582), - HE_ISR, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by raziel_ in bug report #1891869 - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by fac76 in bug report #1742716 - { - "gob3", - "", - { - {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084}, - {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, - {0, 0, 0, 0} - }, - EN_GRB, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by paul66 in bug report #1652352 - { - "gob3", - "", - AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by Paranoimia on #scummvm - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"), - RU_RUS, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Supplied by SiRoCs in bug report #2098621 - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), - EN_GRB, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesNone, - 0, "menu.tot", 0 - }, - { - { - "gob3", - "", - AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), - DE_DEU, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesNone, - 0, "menu.tot", 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "", - { - {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, - {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { // Found in Found in french ADI 2.5 Anglais Multimedia 5e - { - "gob3", - "", - AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3cd", - "v1.000", - AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 - { - "gob3cd", - "v1.02", - AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - HU_HUN, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2810082 - { - "gob3cd", - "v1.02", - AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo", - AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo 2", - AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Interactive Demo 3", - AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561), - EN_ANY, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "gob3", - "Non-interactive Demo", - AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"), - UNK_LANG, - kPlatformPC, - ADGF_DEMO, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesCD, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - EN_USA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - DE_DEU, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - IT_ITA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - ES_ESP, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "", - AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), - FR_FRA, - kPlatformWindows, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "inca2", - "Non-Interactive Demo", - { - {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804}, - {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999}, - {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871}, - {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719}, - {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609}, - {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709}, - {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250}, - {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312}, - {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637}, - {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330}, - {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeInca2, - kFeaturesAdLib | kFeaturesBATDemo, - 0, 0, 7 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by DjDiabolik in bug report #1971294 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2098838 - { - "woodruff", - "", - AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979), - PL_POL, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { - { - "woodruff", - "Non-Interactive Demo", - { - {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 1 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "", - AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864), - EN_USA, - kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - 0, 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774), - UNK_LANG, - kPlatformWindows, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - "lda1.stk", 0, 0 - }, - { - { - "dynasty", - "Demo", - AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724), - DE_DEU, - kPlatformWindows, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeDynasty, - kFeatures640, - "lda1.stk", 0, 0 - }, - { - { - "urban", - "", - AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436), - EN_USA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by gamin in the forums - { - "urban", - "", - AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by jvprat on #scummvm - { - "urban", - "", - AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { // Supplied by goodoldgeorg in bug report #2770340 - { - "urban", - "", - AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeatures640, - 0, 0, 0 - }, - { - { - "urban", - "Non-Interactive Demo", - { - {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87}, - {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237}, - {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeUrban, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 2 - }, - { - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "Pack mes histoires anim\xE9""es", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by scoriae in the forums - { - "playtoons1", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, - {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210}, - {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937}, - {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228}, - {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242}, - {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719}, - {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 3 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, - {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 4 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, - {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533}, - {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786}, - {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, - {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 5 - }, - { - { - "playtoons1", - "Non-Interactive Demo", - { - {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, - {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619}, - {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838}, - {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, - {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, - {0, 0, 0, 0} - }, - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 6 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, - {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, - {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by scoriae in the forums - { - "playtoons2", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, - {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "Pack mes histoires anim\xE9""es", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, - {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791}, - {0, 0, 0, 0} - }, - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { // Supplied by Hkz on #scummvm - { - "playtoons3", - "", - { - {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, - {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons4", - "", - { - {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, - {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { //Supplied by goodoldgeorg in bug report #2820006 - { - "playtoons4", - "", - { - {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, - {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtoons5", - "", - { - {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, - {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "bambou", - "", - { - {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238}, - {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBambou, - kFeatures640, - "intro.stk", "intro.tot", 0 - }, - { - { - "playtnck1", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtnck2", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "playtnck3", - "", - { - {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, - {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056}, - {0, 0, 0, 0} - }, - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - "intro2.stk", 0, 0 - }, - { - { - "adi2", - "Adi 2.0 for Teachers", - AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeaturesNone, - "adi2.stk", "ediintro.tot", 0 - }, - { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified. - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified. - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132), - EN_ANY, - kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeaturesNone, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2", - AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132), - ES_ESP, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.5", - AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.5", - AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.6", - AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.6", - AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Adi 2.7.1", - AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", "ediintro.tot", 0 - }, - { - { - "adi2", - "Non-Interactive Demo", - { - {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168}, - {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723}, - {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731}, - {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511}, - {0, 0, 0, 0} - }, - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi2, - kFeatures640 | kFeaturesSCNDemo, - 0, 0, 1 - }, - { - { - "adi4", - "Addy 4 Grundschule Basis CD", - AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Addy 4 Sekundarstufe Basis CD", - AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0", - AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 Limited Edition", - AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.10", - AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144), - EN_GRB, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.10", - AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.11", - AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "Addy 4.21", - AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "ADI 4.21", - AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 Interactive Demo", - AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "adi4", - "Adi 4.0 / Adibou 2 Demo", - AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0), - FR_FRA, - kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - kGameTypeAdi4, - kFeatures640, - 0, 0, 0 - }, - { - { - "ajworld", - "", - AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628), - EN_ANY, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "adibou1", - "ADIBOU 1 Environnement 4-7 ans", - AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdibou1, - kFeaturesAdLib, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2", - AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "Le Jardin Magique d'Adibou", - AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - DE_DEU, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIB\xD9 2", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - IT_ITA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU Version Decouverte", - AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.10 Environnement", - AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.11 Environnement", - AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.12 Environnement", - AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOU 2.13s Environnement", - AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { - { - "adibou2", - "ADIBOO 2.14 Environnement", - AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874), - FR_FRA, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeAdibou2, - kFeaturesNone, - 0, 0, 0 - }, - { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0} -}; - -static const GOBGameDescription fallbackDescs[] = { - { //0 - { - "gob1", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesNone, - 0, 0, 0 - }, - { //1 - { - "gob1cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob1, - kFeaturesCD, - 0, 0, 0 - }, - { //2 - { - "gob2", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { //3 - { - "gob2mac", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesAdLib, - 0, 0, 0 - }, - { //4 - { - "gob2cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob2, - kFeaturesCD, - 0, 0, 0 - }, - { //5 - { - "bargon", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBargon, - kFeaturesNone, - 0, 0, 0 - }, - { //6 - { - "gob3", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesAdLib, - 0, 0, 0 - }, - { //7 - { - "gob3cd", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGob3, - kFeaturesCD, - 0, 0, 0 - }, - { //8 - { - "woodruff", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeWoodruff, - kFeatures640, - 0, 0, 0 - }, - { //9 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { //10 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesAdLib, - 0, 0, 0 - }, - { //11 - { - "lostintime", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeLostInTime, - kFeaturesCD, - 0, 0, 0 - }, - { //12 - { - "urban", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeUrban, - kFeaturesCD, - 0, 0, 0 - }, - { //13 - { - "playtoons1", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //14 - { - "playtoons2", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //15 - { - "playtoons3", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //16 - { - "playtoons4", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //17 - { - "playtoons5", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //18 - { - "playtoons construction kit", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypePlaytoons, - kFeatures640, - 0, 0, 0 - }, - { //19 - { - "bambou", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeBambou, - kFeatures640, - 0, 0, 0 - }, - { //20 - { - "fascination", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeFascination, - kFeaturesNone, - "disk0.stk", 0, 0 - }, - { //21 - { - "geisha", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeGeisha, - kFeaturesNone, - "disk1.stk", "intro.tot", 0 - }, - { //22 - { - "adi2", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi2, - kFeatures640, - "adi2.stk", 0, 0 - }, - { //23 - { - "adi4", - "", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSUBTITLES | GUIO_NOSPEECH - }, - kGameTypeAdi4, - kFeatures640, - "adif41.stk", 0, 0 - }, - { //24 - { - "coktelplayer", - "unknown", - AD_ENTRY1(0, 0), - UNK_LANG, - kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - kGameTypeUrban, - kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo, - "", "", 8 - } -}; - -static const ADFileBasedFallback fileBased[] = { - { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, - { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", 0 } }, - { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, - { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } }, - { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, - { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } }, - { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } }, - { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } }, - { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } }, - { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, - { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } }, - { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, - { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } }, - { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } }, - { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } }, - { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } }, - { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } }, - { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } }, - { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, - { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, - { &fallbackDescs[22], { "adi2.stk", 0 } }, - { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, - { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, - { 0, { 0 } } -}; - -} +#include "gob/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h new file mode 100644 index 0000000000..20edb9fbc3 --- /dev/null +++ b/engines/gob/detection_tables.h @@ -0,0 +1,5013 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +namespace Gob { + +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSUBTITLES; +using Common::GUIO_NONE; + +static const GOBGameDescription gameDescriptions[] = { + { // Supplied by Florian Zeitz on scummvm-devel + { + "gob1", + "EGA", + AD_ENTRY1("intro.stk", "c65e9cc8ba23a38456242e1f2b1caad4"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesEGA, + 0, 0, 0 + }, + { + { + "gob1", + "EGA", + AD_ENTRY1("intro.stk", "f9233283a0be2464248d83e14b95f09c"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesEGA, + 0, 0, 0 + }, + { // Supplied by Theruler76 in bug report #1201233 + { + "gob1", + "VGA", + AD_ENTRY1("intro.stk", "26a9118c0770fa5ac93a9626761600b2"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891864 + { + "gob1", + "VGA", + AD_ENTRY1s("intro.stk", "e157cb59c6d330ca70d12ab0ef1dd12b", 288972), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raina in the forums + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "6d837c6380d8f4d984c9f6cc0026df4f", 192712), + EN_ANY, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + EN_ANY, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + DE_DEU, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + IT_ITA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob1", + "", + AD_ENTRY1("intro.stk", "00a42a7d2d22e6b6ab1b8c673c4ed267"), + ES_ESP, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "gob1", + "", + { + {"intro.stk", 0, "f5f028ee39c456fa51fa63b606583918", 313472}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob1", + "", + { + {"intro.stk", 0, "e157cb59c6d330ca70d12ab0ef1dd12b", 288972}, + {"musmac1.mid", 0, "4f66903b33df8a20edd4c748809c0b56", 8161}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "f5f028ee39c456fa51fa63b606583918", 313472), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.000 version. + { + "gob1cd", + "v1.000", + AD_ENTRY1("intro.stk", "2fbf4b5b82bbaee87eb45d4404c28998"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // CD 1.02 version. Multilingual + { + "gob1cd", + "v1.02", + AD_ENTRY1("intro.stk", "8bd873137b6831c896ee8ad217a6a398"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob1cd", + "v1.02", + AD_ENTRY1s("intro.stk", "40d4a53818f4fce3f5997d02c3fafe73", 4049248), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob1", + "Demo", + AD_ENTRY1("intro.stk", "972f22c6ff8144a6636423f0354ca549"), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "Interactive Demo", + AD_ENTRY1("intro.stk", "e72bd1e3828c7dec4c8a3e58c48bdfdb"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "a796096280d5efd48cf8e7dfbe426eb5", 193595), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2785958 + { + "gob1", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "35a098571af9a03c04e2303aec7c9249", 116582), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob1", + "", + AD_ENTRY1s("intro.stk", "0e022d3f2481b39e9175d37b2c6ad4c6", 2390121), + FR_FRA, + kPlatformCDi, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesAdLib, + 0, "AVT003.TOT", 0 + }, + { // Supplied by fac76 in bug report #1883808 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "eebf2810122cfd17399260cd1468e994", 554014), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "d28b9e9b41f31acfa58dcd12406c7b2c"), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2602057 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "686c88f7302a80b744aae9f8413e853d"), + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by bgk in bug report #1706861 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "4b13c02d1069b86bcfec80f4e474b98b", 554680), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by fac76 in bug report #1673397 + { + "gob2", + "", + { + {"intro.stk", 0, "b45b984ee8017efd6ea965b9becd4d66", 828443}, + {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, + {0, 0, 0, 0} + }, + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by koalet in bug report #2478585 + { + "gob2", + "", + { + {"intro.stk", 0, "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275}, + {"musmac1.mid", 0, "7f96f491448c7a001b32df89cf8d2af2", 1658}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "b45b984ee8017efd6ea965b9becd4d66"), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "dedb5d31d8c8050a8cf77abedcc53dae"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891867 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "25a99827cd59751a80bed9620fb677a0", 893302), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "a13ecb4f6d8fd881ebbcc02e45cb5475", 837275), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by blackwhiteeagle in bug report #1605235 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "3e4e7db0d201587dd2df4003b2993ef6"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "a13892cdf4badda85a6f6fb47603a128"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2602017 + { + "gob2", + "", + AD_ENTRY1("intro.stk", "c47faf1d406504e6ffe63243610bb1f4"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + AD_ENTRY1("intro.stk", "cd3e1df8b273636ee32e34b7064f50e8"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by arcepi in bug report #1659884 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "5f53c56e3aa2f1e76c2e4f0caa15887f", 829232), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "285d7340f98ebad65d465585da12910b", 837286}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "25a99827cd59751a80bed9620fb677a0", 893302}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "", + { + {"intro.stk", 0, "6efac0a14c0de4d57dde8592456c8acf", 845172}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "24489330a1d67ff978211f574822a5a6", 883756), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob2", + "", + AD_ENTRY1s("intro.stk", "285d7340f98ebad65d465585da12910b", 837286), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2cd", + "v1.000", + AD_ENTRY1("intro.stk", "9de5fbb41cf97182109e5fecc9d90347"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2cd", + "v2.01", + AD_ENTRY1("intro.stk", "24a6b32757752ccb1917ce92fd7c2a04"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob2cd", + "v1.02", + AD_ENTRY1s("intro.stk", "5ba85a4769a1ab03a283dd694588d526", 5006236), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob2", + "Non-Interactive Demo", + AD_ENTRY1("intro.stk", "8b1c98ff2ab2e14f47a1b891e9b92217"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, "usa.tot", 0 + }, + { + { + "gob2", + "Interactive Demo", + AD_ENTRY1("intro.stk", "cf1c95b2939bd8ff58a25c756cb6125e"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob2", + "Interactive Demo", + AD_ENTRY1("intro.stk", "4b278c2678ea01383fd5ca114d947eea"), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by polluks in bug report #1895126 + { + "gob2", + "Interactive Demo", + AD_ENTRY1s("intro.stk", "9fa85aea959fa8c582085855fbd99346", 553063), + UNK_LANG, + kPlatformAmiga, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + { + {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, + {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "257fe669705ac4971efdfd5656eef16a", 457719), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "dffd1ab98fe76150d6933329ca6f4cc4", 459458), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by vampir_raziel in bug report #1658373 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "af83debf2cbea21faa591c7b4608fe92", 458192), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2563539 + { + "ween", + "", + { + {"intro.stk", 0, "dffd1ab98fe76150d6933329ca6f4cc4", 459458}, + {"ween.ins", 0, "d2cb24292c9ddafcad07e23382027218", 87800}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by pwigren in bug report #1764174 + { + "ween", + "", + { + {"intro.stk", 0, "bfd9d02faf3d8d60a2cf744f95eb48dd", 456570}, + {"music__5.snd", 0, "7d1819b9981ecddd53d3aacbc75f1cc8", 13446}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "e6d13fb3b858cb4f78a8780d184d5b2c"), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "2bb8878a8042244dd2b96ff682381baa"), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1s("intro.stk", "de92e5c6a8c163007ffceebef6e67f7d", 7117568), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cybot_tmin in bug report #1667743 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "6d60f9205ecfbd8735da2ee7823a70dc", 7014426), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "", + AD_ENTRY1("intro.stk", "4b10525a3782aa7ecd9d833b5c1d308b"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cartman_ on #scummvm + { + "ween", + "", + AD_ENTRY1("intro.stk", "63170e71f04faba88673b3f510f9c4c8"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by glorfindel in bugreport #1722142 + { + "ween", + "", + AD_ENTRY1s("intro.stk", "8b57cd510da8a3bbd99e3a0297a8ebd1", 7018771), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "ween", + "Demo", + AD_ENTRY1("intro.stk", "2e9c2898f6bf206ede801e3b2e7ee428"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, "show.tot", 0 + }, + { + { + "ween", + "Demo", + AD_ENTRY1("intro.stk", "15fb91a1b9b09684b28ac75edf66e504"), + EN_USA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWeen, + kFeaturesAdLib, + 0, "show.tot", 0 + }, + { + { + "bargon", + "", + AD_ENTRY1("intro.stk", "da3c54be18ab73fbdb32db24624a9c23"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by Trekky in the forums + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "2f54b330d21f65b04b7c1f8cca76426c", 262109), + FR_FRA, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by cesardark in bug #1681649 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "11103b304286c23945560b391fd37e7d", 3181890), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by paul66 in bug #1692667 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by pwigren in bugreport #1764174 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "569d679fe41d49972d34c9fce5930dda", 269825), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by kizkoool in bugreport #2089734 + { + "bargon", + "", + AD_ENTRY1s("intro.stk", "00f6b4e2ee26e5c40b488e2df5adcf03", 3975580), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { // Supplied by glorfindel in bugreport #1722142 + { + "bargon", + "Fanmade", + AD_ENTRY1s("intro.stk", "da3c54be18ab73fbdb32db24624a9c23", 3181825), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "0b72992f5d8b5e6e0330572a5753ea25", 256490), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + { + {"intro.stk", 0, "0b72992f5d8b5e6e0330572a5753ea25", 256490}, + {"mod.babayaga", 0, "43484cde74e0860785f8e19f0bc776d1", 60248}, + {0, 0, 0, 0} + }, + UNK_LANG, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "113a16877e4f72037d9714be1c2b0221", 1187522), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { // Found in french ADI 2 Francais-Maths CM1 + { + "littlered", + "", + AD_ENTRY1s("intro.stk", "5c15b37ed27ac2470854e9e09374d50e", 1248610), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib | kFeaturesEGA, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "7b7f48490dedc8a7cb999388e2fadbe3", 3930674), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "e0767783ff662ed93665446665693aef", 4371238), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by cartman_ on #scummvm + { + "lit", + "", + AD_ENTRY1s("intro.stk", "f1f78b663893b58887add182a77df151", 3944090), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2105220 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "cd322cb3c64ef2ba2f2134aa2122cfe9", 3936700), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by koalet in bug report #2479034 + { + "lit", + "", + { + {"intro.stk", 0, "af98bcdc70e1f1c1635577fd726fe7f1", 3937310}, + {"musmac1.mid", 0, "ae7229bb09c6abe4e60a2768b24bc890", 9398}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "6263d09e996c1b4e84ef2d650b820e57", 4831170), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2093672 + { + "lit", + "", + AD_ENTRY1s("intro.stk", "795be7011ec31bf5bb8ce4efdb9ee5d3", 4838904), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4207330), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "", + AD_ENTRY1s("intro.stk", "0ddf39cea1ec30ecc8bfe444ebd7b845", 4219382), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in french ADI 2.6 Francais-Maths 4e + { + "lit", + "", + AD_ENTRY1s("intro.stk", "58ee9583a4fb837f02d9a58e5f442656", 3937120), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit1", + "Full install", + { + {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, + {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 4396644}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit1", + "Light install", + { + {"intro.stk", 0, "93c91bc9e783d00033042ae83144d7dd", 72318}, + {"partie2.itk", 0, "78f00bd8eb9e680e6289bba0130b1b33", 664064}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit2", + "Light install", + AD_ENTRY1s("intro.stk", "17acbb212e62addbe48dc8f2282c98cb", 72318), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit2", + "Full install", + { + {"intro.stk", 0, "17acbb212e62addbe48dc8f2282c98cb", 72318}, + {"partie4.itk", 0, "6ce4967e0c79d7daeabc6c1d26783d4c", 2612087}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "lit", + "Demo", + AD_ENTRY1("demo.stk", "c06f8cc20eb239d4c71f225ce3093edf"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + "demo.stk", "demo.tot", 0 + }, + { + { + "lit", + "Non-interactive Demo", + AD_ENTRY1("demo.stk", "2eba8abd9e3878c57307576012dd2fec"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + "demo.stk", "demo.tot", 0 + }, + { + { + "fascination", + "CD Version (Censored)", + AD_ENTRY1s("disk0.stk", "9c61e9c22077f72921f07153e37ccf01", 545953), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES + }, + kGameTypeFascination, + kFeaturesCD, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "a50a8495e1b2d67699fb562cb98fc3e2", 1064387), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("intro.stk", "d6e45ce548598727e2b5587a99718eba", 1055909), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "intro.stk", 0, 0 + }, + { // Supplied by sanguine + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "c14330d052fe4da5a441ac9d81bc5891", 1061955), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { // Supplied by windlepoons in bug report #2809247 + { + "fascination", + "VGA 3 disks edition", + AD_ENTRY1s("disk0.stk", "3a24e60a035250189643c86a9ceafb97", 1062480), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "VGA", + AD_ENTRY1s("disk0.stk", "e8ab4f200a2304849f462dc901705599", 183337), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesAdLib, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "68b1c01564f774c0b640075fbad1b695", 189968), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "7062117e9c5adfb6bfb2dac3ff74df9e", 189951), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "55c154e5a3e8e98afebdcff4b522e1eb", 190005), + FR_FRA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "7691827fff35df7799f14cfd6be178ad", 189931), + IT_ITA, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "fascination", + "", + AD_ENTRY1s("disk0.stk", "aff9fcc619f4dd19eae228affd0d34c8", 189964), + EN_ANY, + kPlatformAtariST, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { + { + "geisha", + "", + AD_ENTRY1s("disk1.stk", "6eebbb98ad90cd3c44549fc2ab30f632", 212153), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { + { + "geisha", + "", + AD_ENTRY1s("disk1.stk", "f4d4d9d20f7ad1f879fc417d47faba89", 336732), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "32b0f57f5ae79a9ae97e8011df38af42", 157084), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "904fc32032295baa3efb3a41f17db611", 178582), + HE_ISR, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by raziel_ in bug report #1891869 + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "16b014bf32dbd6ab4c5163c44f56fed1", 445104), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "16b014bf32dbd6ab4c5163c44f56fed1", 445104}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by fac76 in bug report #1742716 + { + "gob3", + "", + { + {"intro.stk", 0, "32b0f57f5ae79a9ae97e8011df38af42", 157084}, + {"musmac1.mid", 0, "834e55205b710d0af5f14a6f2320dd8e", 8661}, + {0, 0, 0, 0} + }, + EN_GRB, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "1e2f64ec8dfa89f42ee49936a27e66e7"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by paul66 in bug report #1652352 + { + "gob3", + "", + AD_ENTRY1("intro.stk", "f6d225b25a180606fa5dbe6405c97380"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "e42a4f2337d6549487a80864d7826972"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by Paranoimia on #scummvm + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "fe8144daece35538085adb59c2d29613", 159402), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "4e3af248a48a2321364736afab868527"), + RU_RUS, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "8d28ce1591b0e9cc79bf41cad0fc4c9c"), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Supplied by SiRoCs in bug report #2098621 + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "d3b72938fbbc8159198088811f9e6d19", 160382), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), + EN_GRB, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesNone, + 0, "menu.tot", 0 + }, + { + { + "gob3", + "", + AD_ENTRY1("intro.stk", "bd679eafde2084d8011f247e51b5a805"), + DE_DEU, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesNone, + 0, "menu.tot", 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "edd7403e5dc2a14459d2665a4c17714d", 209534}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "", + { + {"intro.stk", 0, "428e2de130cf3b303c938924539dc50d", 324420}, + {"musmac1.mid", 0, "948c546cad3a9de5bff3fe4107c82bf1", 6404}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { // Found in Found in french ADI 2.5 Anglais Multimedia 5e + { + "gob3", + "", + AD_ENTRY1s("intro.stk", "edd7403e5dc2a14459d2665a4c17714d", 209534), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3cd", + "v1.000", + AD_ENTRY1("intro.stk", "6f2c226c62dd7ab0ab6f850e89d3fc47"), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by paul66 and noizert in bug reports #1652352 and #1691230 + { + "gob3cd", + "v1.02", + AD_ENTRY1("intro.stk", "c3e9132ea9dc0fb866b6d60dcda10261"), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + HU_HUN, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2810082 + { + "gob3cd", + "v1.02", + AD_ENTRY1s("intro.stk", "bfd7d4c6fedeb2cfcc8baa4d5ddb1f74", 616220), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo", + AD_ENTRY1("intro.stk", "7aebd94e49c2c5c518c9e7b74f25de9d"), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo 2", + AD_ENTRY1("intro.stk", "e5dcbc9f6658ebb1e8fe26bc4da0806d"), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Interactive Demo 3", + AD_ENTRY1s("intro.stk", "9e20ad7b471b01f84db526da34eaf0a2", 395561), + EN_ANY, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "gob3", + "Non-interactive Demo", + AD_ENTRY1("intro.stk", "b9b898fccebe02b69c086052d5024a55"), + UNK_LANG, + kPlatformPC, + ADGF_DEMO, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "47c3b452767c4f49ea7b109143e77c30", 916828), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesCD, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "1fa92b00fe80a20f34ec34a8e2fa869e", 923072), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + EN_USA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + DE_DEU, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + IT_ITA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + ES_ESP, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "", + AD_ENTRY1s("intro.stk", "d33011df8758ac64ca3dca77c7719001", 908612), + FR_FRA, + kPlatformWindows, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "inca2", + "Non-Interactive Demo", + { + {"cons.imd", 0, "f896ba0c4a1ac7f7260d342655980b49", 17804}, + {"conseil.imd", 0, "aaedd5482d5b271e233e86c5a03cf62e", 33999}, + {"int.imd", 0, "6308222fcefbcb20925f01c1aff70dee", 30871}, + {"inter.imd", 0, "39bd6d3540f3bedcc97293f352c7f3fc", 191719}, + {"machu.imd", 0, "c0bc8211d93b467bfd063b63fe61b85c", 34609}, + {"post.imd", 0, "d75cad0e3fc22cb0c8b6faf597f509b2", 1047709}, + {"posta.imd", 0, "2a5b3fe75681ddf4d21ac724db8111b4", 547250}, + {"postb.imd", 0, "24260ce4e80a4c472352b76637265d09", 868312}, + {"postc.imd", 0, "24accbcc8b83a9c2be4bd82849a2bd29", 415637}, + {"tum.imd", 0, "0993d4810ec9deb3f77c5e92095320fd", 20330}, + {"tumi.imd", 0, "bf53f229480d694de0947fe3366fbec6", 248952}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeInca2, + kFeaturesAdLib | kFeaturesBATDemo, + 0, 0, 7 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "dccf9d31cb720b34d75487408821b77e", 20296390), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "b50fee012a5abcd0ac2963e1b4b56bec", 20298108), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "5f5f4e0a72c33391e67a47674b120cc6", 20296422), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "270529d9b8cce770b1575908a3800b52", 20296452), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "f4c344023b073782d2fddd9d8b515318", 7069736), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by DjDiabolik in bug report #1971294 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "60348a87651f92e8492ee070556a96d8", 7069736), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2098838 + { + "woodruff", + "", + AD_ENTRY1s("intro.stk", "08a96bf061af1fa4f75c6a7cc56b60a4", 20734979), + PL_POL, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { + { + "woodruff", + "Non-Interactive Demo", + { + {"demo.scn", 0, "16bb85fc5f8e519147b60475dbf33962", 89}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 1 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "6190e32404b672f4bbbc39cf76f41fda", 2511470), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "61e4069c16e27775a6cc6d20f529fb36", 2511300), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "b3f8472484b7a1df94557b51e7b6fca0", 2322644), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "", + AD_ENTRY1s("intro.stk", "bdbdac8919200a5e71ffb9fb0709f704", 2446652), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("intro.stk", "464538a17ed39755d7f1ba9c751af1bd", 1847864), + EN_USA, + kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + 0, 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("lda1.stk", "0e56a899357cbc0bf503260fd2dd634e", 15032774), + UNK_LANG, + kPlatformWindows, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + "lda1.stk", 0, 0 + }, + { + { + "dynasty", + "Demo", + AD_ENTRY1s("lda1.stk", "8669ea2e9a8239c070dc73958fbc8753", 15567724), + DE_DEU, + kPlatformWindows, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeDynasty, + kFeatures640, + "lda1.stk", 0, 0 + }, + { + { + "urban", + "", + AD_ENTRY1s("intro.stk", "3ab2c542bd9216ae5d02cc6f45701ae1", 1252436), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by gamin in the forums + { + "urban", + "", + AD_ENTRY1s("intro.stk", "b991ed1d31c793e560edefdb349882ef", 1276408), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by jvprat on #scummvm + { + "urban", + "", + AD_ENTRY1s("intro.stk", "4ec3c0864e2b54c5b4ccf9f6ad96528d", 1253328), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { // Supplied by goodoldgeorg in bug report #2770340 + { + "urban", + "", + AD_ENTRY1s("intro.stk", "4bd31979ea3d77a58a358c09000a85ed", 1253018), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640, + 0, 0, 0 + }, + { + { + "urban", + "Non-Interactive Demo", + { + {"wdemo.s24", 0, "14ac9bd51db7a075d69ddb144904b271", 87}, + {"demo.vmd", 0, "65d04715d871c292518b56dd160b0161", 9091237}, + {"urband.vmd", 0, "60343891868c91854dd5c82766c70ecc", 922461}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeUrban, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 2 + }, + { + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "Pack mes histoires anim\xE9""es", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"archi.stk", 0, "8d44b2a0d4e3139471213f9f0ed21e81", 5524674}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by scoriae in the forums + { + "playtoons1", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"archi.stk", 0, "00d8274519dfcf8a0d8ae3099daea0f8", 5532135}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"play123.scn", 0, "4689a31f543915e488c3bc46ea358add", 258}, + {"archi.vmd", 0, "a410fcc8116bc173f038100f5857191c", 5617210}, + {"chato.vmd", 0, "5a10e39cb66c396f2f9d8fb35e9ac016", 5445937}, + {"genedeb.vmd", 0, "3bb4a45585f88f4d839efdda6a1b582b", 1244228}, + {"generik.vmd", 0, "b46bdd64b063e86927fb2826500ad512", 603242}, + {"genespi.vmd", 0, "b7611916f32a370ae9832962fc17ef72", 758719}, + {"spirou.vmd", 0, "8513dbf7ac51c057b21d371d6b217b47", 2550788}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 3 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"e.scn", 0, "8a0db733c3f77be86e74e8242e5caa61", 124}, + {"demarchg.vmd", 0, "d14a95da7d8792faf5503f649ffcbc12", 5619415}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 4 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"i.scn", 0, "8b3294474d39970463663edd22341730", 285}, + {"demarita.vmd", 0, "84c8672b91c7312462603446e224bfec", 5742533}, + {"dembouit.vmd", 0, "7a5fdf0a4dbdfe72e31dd489ea0f8aa2", 3536786}, + {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, + {"demoita.vmd", 0, "b4c0622d14c8749965cd0f5dfca4cf4b", 1183566}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 5 + }, + { + { + "playtoons1", + "Non-Interactive Demo", + { + {"s.scn", 0, "1f527010626b5490761f16ba7a6f639a", 251}, + {"demaresp.vmd", 0, "3f860f944056842b35a5fd05416f208e", 5720619}, + {"demboues.vmd", 0, "3a0caa10c98ef92a15942f8274075b43", 3535838}, + {"demo5.vmd", 0, "2abb7b6a26406c984f389f0b24b5e28e", 13290970}, + {"wooddem3.vmd", 0, "a1700596172c2d4e264760030c3a3d47", 8994250}, + {0, 0, 0, 0} + }, + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 6 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, + {"spirou.stk", 0, "5d9c7644d0c47840169b4d016765cc1a", 9816201}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "55a85036dd93cce93532d8f743d90074", 17467154}, + {"spirou.stk", 0, "e3e1b6148dd72fafc3637f1a8e5764f5", 9812043}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"spirou.stk", 0, "91080dc148de1bbd6a97321c1a1facf3", 9817086}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by scoriae in the forums + { + "playtoons2", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"spirou.stk", 0, "993737f112ca6a9b33c814273280d832", 9825760}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "8c98e9a11be9bb203a55e8c6e68e519b", 25574338}, + {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"chato.stk", 0, "8fc8d0da5b3e758908d1d7298d497d0b", 6041026}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "Pack mes histoires anim\xE9""es", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"chato.stk", 0, "4fa4ed96a427c344e9f916f9f236598d", 6033793}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "c5ca2a288cdaefca9556cd9ae4b579cf", 25158926}, + {"chato.stk", 0, "3c6cb3ac8a5a7cf681a19971a92a748d", 6033791}, + {0, 0, 0, 0} + }, + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { // Supplied by Hkz on #scummvm + { + "playtoons3", + "", + { + {"playtoon.stk", 0, "4772c96be88a57f0561519e4a1526c62", 24406262}, + {"chato.stk", 0, "bdef407387112bfcee90e664865ac3af", 6033867}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "b7f5afa2dc1b0f75970b7c07d175db1b", 24340406}, + {"manda.stk", 0, "92529e0b927191d9898a34c2892e9a3a", 6485072}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { //Supplied by goodoldgeorg in bug report #2820006 + { + "playtoons4", + "", + { + {"playtoon.stk", 0, "9e513e993a5b0e2496add3f50c08764b", 30448506}, + {"manda.stk", 0, "69a79c9f61b2618e482726f2ff68078d", 6499208}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtoons5", + "", + { + {"playtoon.stk", 0, "55f0293202963854192e39474e214f5f", 30448474}, + {"wakan.stk", 0, "f493bf82851bc5ba74d57de6b7e88df8", 5520153}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "bambou", + "", + { + {"intro.stk", 0, "2f8db6963ff8d72a8331627ebda918f4", 3613238}, + {"bambou.itk", 0, "0875914d31126d0749313428f10c7768", 114440192}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBambou, + kFeatures640, + "intro.stk", "intro.tot", 0 + }, + { + { + "playtnck1", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "906d67b3e438d5e95ec7ea9e781a94f3", 3000320}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtnck2", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "74eeb075bd2cb47b243349730264af01", 3213312}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "playtnck3", + "", + { + {"playtoon.stk", 0, "5f9aae29265f1f105ad8ec195dff81de", 68382024}, + {"dan.itk", 0, "9a8f62809eca5a52f429b5b6a8e70f8f", 2861056}, + {0, 0, 0, 0} + }, + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + "intro2.stk", 0, 0 + }, + { + { + "adi2", + "Adi 2.0 for Teachers", + AD_ENTRY1s("adi2.stk", "da6f1fb68bff32260c5eecdf9286a2f5", 1533168), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeaturesNone, + "adi2.stk", "ediintro.tot", 0 + }, + { // Found in french ADI 2 Francais-Maths CM1. Exact version not specified. + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "23f279615c736dc38320f1348e70c36e", 10817668), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { // Found in french ADI 2 Francais-Maths CE2. Exact version not specified. + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "d4162c4298f9423ecc1fb04965557e90", 11531214), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "29694c5a649298a42f87ae731d6d6f6d", 311132), + EN_ANY, + kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeaturesNone, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2", + AD_ENTRY1s("adi2.stk", "2a40bb48ccbd4e6fb3f7f0fc2f069d80", 17720132), + ES_ESP, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.5", + AD_ENTRY1s("adi2.stk", "fcac60e6627f37aee219575b60859de9", 16944268), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.5", + AD_ENTRY1s("adi2.stk", "072d5e2d7826a7c055865568ebf918bb", 16934596), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.6", + AD_ENTRY1s("adi2.stk", "2fb940eb8105b12871f6b88c8c4d1615", 16780058), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.6", + AD_ENTRY1s("adi2.stk", "fde7d98a67dbf859423b6473796e932a", 18044780), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Adi 2.7.1", + AD_ENTRY1s("adi2.stk", "6fa5dffebf5c7243c6af6b8c188ee00a", 19278008), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", "ediintro.tot", 0 + }, + { + { + "adi2", + "Non-Interactive Demo", + { + {"demo.scn", 0, "8b5ba359fd87d586ad39c1754bf6ea35", 168}, + {"demadi2t.vmd", 0, "08a1b18cfe2015d3b43270da35cc813d", 7250723}, + {"demarch.vmd", 0, "4c4a4616585d40ef3df209e3c3911062", 5622731}, + {"demobou.vmd", 0, "2208b9855775564d15c4a5a559da0aec", 3550511}, + {0, 0, 0, 0} + }, + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi2, + kFeatures640 | kFeaturesSCNDemo, + 0, 0, 1 + }, + { + { + "adi4", + "Addy 4 Grundschule Basis CD", + AD_ENTRY1s("intro.stk", "d2f0fb8909e396328dc85c0e29131ba8", 5847588), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Addy 4 Sekundarstufe Basis CD", + AD_ENTRY1s("intro.stk", "367340e59c461b4fa36651cd74e32c4e", 5847378), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "a3c35d19b2d28ea261d96321d208cb5a", 6021466), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "44491d85648810bc6fcf84f9b3aa47d5", 5834944), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0", + AD_ENTRY1s("intro.stk", "29374c0e3c10b17dd8463b06a55ad093", 6012072), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 Limited Edition", + AD_ENTRY1s("intro.stk", "ebbbc5e28a4adb695535ed989c1b8d66", 5929644), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.10", + AD_ENTRY1s("intro.stk", "3e3fa9656e37d802027635ace88c4cc5", 5359144), + EN_GRB, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.10", + AD_ENTRY1s("intro.stk", "6afc2590856433b9f5295b032f2b205d", 5923112), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.11", + AD_ENTRY1s("intro.stk", "6296e4be4e0c270c24d1330881900c7f", 5921234), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "Addy 4.21", + AD_ENTRY1s("intro.stk", "534f0b674cd4830df94a9c32c4ea7225", 6878034), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "ADI 4.21", + AD_ENTRY1s("intro.stk", "c5b9f6222c0b463f51dab47317c5b687", 5950490), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 Interactive Demo", + AD_ENTRY1s("intro.stk", "89ace204dbaac001425c73f394334f6f", 2413102), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "adi4", + "Adi 4.0 / Adibou 2 Demo", + AD_ENTRY1s("intro.stk", "d41d8cd98f00b204e9800998ecf8427e", 0), + FR_FRA, + kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + kGameTypeAdi4, + kFeatures640, + 0, 0, 0 + }, + { + { + "ajworld", + "", + AD_ENTRY1s("intro.stk", "e453bea7b28a67c930764d945f64d898", 3913628), + EN_ANY, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "adibou1", + "ADIBOU 1 Environnement 4-7 ans", + AD_ENTRY1s("intro.stk", "6db110188fcb7c5208d9721b5282682a", 4805104), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdibou1, + kFeaturesAdLib, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2", + AD_ENTRY1s("intro.stk", "94ae7004348dc8bf99c23a9a6ef81827", 956162), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "Le Jardin Magique d'Adibou", + AD_ENTRY1s("intro.stk", "a8ff86f3cc40dfe5898e0a741217ef27", 956328), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + DE_DEU, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIB\xD9 2", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + IT_ITA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU Version Decouverte", + AD_ENTRY1s("intro.stk", "558c14327b79ed39214b49d567a75e33", 8737856), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.10 Environnement", + AD_ENTRY1s("intro.stk", "f2b797819aeedee557e904b0b5ccd82e", 8736454), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.11 Environnement", + AD_ENTRY1s("intro.stk", "7b1f1f6f6477f54401e95d913f75e333", 8736904), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.12 Environnement", + AD_ENTRY1s("intro.stk", "1e49c39a4a3ce6032a84b712539c2d63", 8738134), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOU 2.13s Environnement", + AD_ENTRY1s("intro.stk", "092707829555f27706920e4cacf1fada", 8737958), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { + { + "adibou2", + "ADIBOO 2.14 Environnement", + AD_ENTRY1s("intro.stk", "ff63637e3cb7f0a457edf79457b1c6b3", 9333874), + FR_FRA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeAdibou2, + kFeaturesNone, + 0, 0, 0 + }, + { AD_TABLE_END_MARKER, kGameTypeNone, kFeaturesNone, 0, 0, 0} +}; + +static const GOBGameDescription fallbackDescs[] = { + { //0 + { + "gob1", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesNone, + 0, 0, 0 + }, + { //1 + { + "gob1cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob1, + kFeaturesCD, + 0, 0, 0 + }, + { //2 + { + "gob2", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { //3 + { + "gob2mac", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesAdLib, + 0, 0, 0 + }, + { //4 + { + "gob2cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob2, + kFeaturesCD, + 0, 0, 0 + }, + { //5 + { + "bargon", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBargon, + kFeaturesNone, + 0, 0, 0 + }, + { //6 + { + "gob3", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesAdLib, + 0, 0, 0 + }, + { //7 + { + "gob3cd", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGob3, + kFeaturesCD, + 0, 0, 0 + }, + { //8 + { + "woodruff", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeWoodruff, + kFeatures640, + 0, 0, 0 + }, + { //9 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { //10 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesAdLib, + 0, 0, 0 + }, + { //11 + { + "lostintime", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeLostInTime, + kFeaturesCD, + 0, 0, 0 + }, + { //12 + { + "urban", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeaturesCD, + 0, 0, 0 + }, + { //13 + { + "playtoons1", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //14 + { + "playtoons2", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //15 + { + "playtoons3", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //16 + { + "playtoons4", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //17 + { + "playtoons5", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //18 + { + "playtoons construction kit", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypePlaytoons, + kFeatures640, + 0, 0, 0 + }, + { //19 + { + "bambou", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeBambou, + kFeatures640, + 0, 0, 0 + }, + { //20 + { + "fascination", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeFascination, + kFeaturesNone, + "disk0.stk", 0, 0 + }, + { //21 + { + "geisha", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeGeisha, + kFeaturesNone, + "disk1.stk", "intro.tot", 0 + }, + { //22 + { + "adi2", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi2, + kFeatures640, + "adi2.stk", 0, 0 + }, + { //23 + { + "adi4", + "", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeAdi4, + kFeatures640, + "adif41.stk", 0, 0 + }, + { //24 + { + "coktelplayer", + "unknown", + AD_ENTRY1(0, 0), + UNK_LANG, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + kGameTypeUrban, + kFeaturesAdLib | kFeatures640 | kFeaturesSCNDemo, + "", "", 8 + } +}; + +static const ADFileBasedFallback fileBased[] = { + { &fallbackDescs[ 0], { "intro.stk", "disk1.stk", "disk2.stk", "disk3.stk", "disk4.stk", 0 } }, + { &fallbackDescs[ 1], { "intro.stk", "gob.lic", 0 } }, + { &fallbackDescs[ 2], { "intro.stk", 0 } }, + { &fallbackDescs[ 2], { "intro.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[ 3], { "intro.stk", "disk2.stk", "disk3.stk", "musmac1.mid", 0 } }, + { &fallbackDescs[ 4], { "intro.stk", "gobnew.lic", 0 } }, + { &fallbackDescs[ 5], { "intro.stk", "scaa.imd", "scba.imd", "scbf.imd", 0 } }, + { &fallbackDescs[ 6], { "intro.stk", "imd.itk", 0 } }, + { &fallbackDescs[ 7], { "intro.stk", "mus_gob3.lic", 0 } }, + { &fallbackDescs[ 8], { "intro.stk", "woodruff.itk", 0 } }, + { &fallbackDescs[ 9], { "intro.stk", "commun1.itk", 0 } }, + { &fallbackDescs[10], { "intro.stk", "commun1.itk", "musmac1.mid", 0 } }, + { &fallbackDescs[11], { "intro.stk", "commun1.itk", "lost.lic", 0 } }, + { &fallbackDescs[12], { "intro.stk", "cd1.itk", "objet1.itk", 0 } }, + { &fallbackDescs[13], { "playtoon.stk", "archi.stk", 0 } }, + { &fallbackDescs[14], { "playtoon.stk", "spirou.stk", 0 } }, + { &fallbackDescs[15], { "playtoon.stk", "chato.stk", 0 } }, + { &fallbackDescs[16], { "playtoon.stk", "manda.stk", 0 } }, + { &fallbackDescs[17], { "playtoon.stk", "wakan.stk", 0 } }, + { &fallbackDescs[18], { "playtoon.stk", "dan.itk" } }, + { &fallbackDescs[19], { "intro.stk", "bambou.itk", 0 } }, + { &fallbackDescs[20], { "disk0.stk", "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[21], { "disk1.stk", "disk2.stk", "disk3.stk", 0 } }, + { &fallbackDescs[22], { "adi2.stk", 0 } }, + { &fallbackDescs[23], { "adif41.stk", "adim41.stk", 0 } }, + { &fallbackDescs[24], { "coktelplayer.scn", 0 } }, + { 0, { 0 } } +}; + +} -- cgit v1.2.3 From 560809e42c16425a80d2bddeeb8a13b49ad4f498 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:15:08 +0000 Subject: Split out detection tables for AGI engine svn-id: r49693 --- engines/agi/detection.cpp | 838 +-------------------------------------- engines/agi/detection_tables.h | 861 +++++++++++++++++++++++++++++++++++++++++ 2 files changed, 862 insertions(+), 837 deletions(-) create mode 100644 engines/agi/detection_tables.h (limited to 'engines') diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index 1c2638fc89..fa21925b78 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -125,841 +125,7 @@ static const PlainGameDescriptor agiGames[] = { {0, 0} }; - -namespace Agi { - -using Common::GUIO_NONE; - -#define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ - { \ - id, \ - name, \ - AD_ENTRY1s(fname,md5,size), \ - lang, \ - platform, \ - ADGF_NO_FLAGS, \ - GUIO_NONE \ - }, \ - gid, \ - interp, \ - features, \ - ver, \ - } - -#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ - { \ - id, \ - name, \ - AD_ENTRY1s(fname,md5,size), \ - lang, \ - platform, \ - ADGF_USEEXTRAASTITLE, \ - GUIO_NONE \ - }, \ - gid, \ - interp, \ - features, \ - ver, \ - } - -#define GAME(id,name,md5,ver,gid) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) -#define GAME3(id,name,fname,md5,ver,gid) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) - -#define GAME_P(id,name,md5,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) - -#define GAME_FP(id,name,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) - -#define GAME_PS(id,name,md5,size,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) - -#define GAME_LPS(id,name,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) - -#define GAME_LFPS(id,name,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) - -#define GAME3_P(id,name,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) - -#define GAMEpre_P(id,name,fname,md5,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) - -#define GAMEpre_PS(id,name,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) - -#define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) - -#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) - -#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) -#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) - -#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) - -#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) -#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) - -#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0) -#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features) -#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0) -#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0) - -#define FANMADE(name,md5) FANMADE_F(name,md5,0) - -static const AGIGameDescription gameDescriptions[] = { - - // AGI Demo 1 (PC) 05/87 [AGI 2.425] - GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO), - - // AGI Demo 2 (IIgs) 1.0C (Censored) - GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS), - - // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915] - GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO), - - // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915] - GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO), - - // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917] - GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO), - - // AGI Demo 3 (PC) 09/88 [AGI 3.002.102] - GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO), - - // AGI Demo for Kings Quest III and Space Quest I - GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO), - - // Black Cauldron (Amiga) 2.00 6/14/87 - GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga), - - // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE) - // Menus not tested - GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS), - - // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439] - GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC), - - // Black Cauldron (Russian) - GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC), - - // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098] - GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC), - - // Black Cauldron (PC) 2.10 [AGI 3.002.097] - GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC), - - // Black Cauldron (CoCo3 360k) [AGI 2.023] - GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), - - // Black Cauldron (CoCo3 360k) [AGI 2.072] - GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), - -// TODO -// These aren't supposed to work now as they require unsupported agi engine 2.01 -#if 0 - // Donald Duck's Playground (Amiga) 1.0C - // Menus not tested - GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga), - - // Donald Duck's Playground (ST) 1.0A 8/8/86 - // Menus not tested - GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Menus not tested - GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC), -#endif - - // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316 - GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga), - - // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88 - // Menus not tested - GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformApple2GS), - - // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88 - GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST), - - // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] - GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH), - - // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149] - GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH), - - // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149] - GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH), - - { - // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] - { - "goldrush", - "2.01 1988-12-22", - { - { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399}, - { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_GOLDRUSH, - GType_V3, - GF_MACGOLDRUSH, - 0x3149, - }, - - - // Gold Rush! (CoCo3 720k) [AGI 2.023] - GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), - - // Gold Rush! (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), - - // King's Quest 1 (Amiga) 1.0U # 2.082 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga), - - // King's Quest 1 (ST) 1.0V - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST), - - // King's Quest 1 (IIgs) 1.0S-88223 - // Menus not tested - GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS), - - // King's Quest 1 (Mac) 2.0C - GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh), - - // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917] - GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1), - - // King's Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), - - // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE) - GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS), - - // King's Quest 2 (Amiga) 2.0J (Broken) - GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga), - - // King's Quest 2 (Mac) 2.0R - GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh), - - // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien? - // XXX: any major differences from 2.411 to 2.440? - GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2), - - // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426] - GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2), - - // King's Quest 2 (Russian) - GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC), - - // King's Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 2 (CoCo3 360k) [AGI 2.072] - GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3), - - // King's Quest 3 (Amiga) 1.01 11/8/86 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga), - - // King's Quest 3 (ST) 1.02 11/18/86 - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST), - - // King's Quest 3 (Mac) 2.14 3/15/88 - GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh), - - // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE) - GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS), - - // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333 - // Original pauses with ESC, has menus accessible with mouse. - // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly). - // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears. - GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga), - - // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272] - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), - - // King's Quest 3 (Russian) - GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), - - // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435] - GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3), - - // King's Quest 3 (Mac) 2.14 3/15/88 - // Menus not tested - GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh), - - // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936] - GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3), - - // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023] - GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3), - - // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086] - GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086] - GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086] - // Menus not tested - GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086] - GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4), - - // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086] - GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4), - - // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE) - // Menus not tested - GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS), - - // King's Quest 4 demo (PC) [AGI 3.002.102] - // Menus not tested - GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4), - - // King's Quest 4 (CoCo3 720k) [AGI 2.023] - GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), - - // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), - - // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440] - GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1), - - // Leisure Suit Larry 1 Polish - GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC), - - // Leisure Suit Larry 1 Polish - Demo - GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC), - - // Leisure Suit Larry 1 (ST) 1.04 6/18/87 - GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST), - - // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy - GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga), - - // Leisure Suit Larry 1 (IIgs) 1.0E - GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS), - - // Leisure Suit Larry 1 (Mac) 1.05 6/26/87 - GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh), - - // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072] - GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3), - - // Manhunter NY (ST) 1.03 10/20/88 - GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), - - // Manhunter NY (IIgs) 2.0E 10/05/88 (CE) - GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS), - - // Manhunter NY (Amiga) 1.06 3/18/89 - GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107] - GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC), - - // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102] - GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC), - - // Manhunter NY (CoCo3 720k) [AGI 2.023] - GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), - - // Manhunter NY (CoCo3 360k/720k) [AGI 2.072] - GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), - - // Manhunter SF (ST) 1.0 7/29/89 - GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), - - // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333 - GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga), - - // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149] - GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2), - - // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149] - GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2), - - // Manhunter SF (CoCo3 720k) [AGI 2.023] - GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), - - // Manhunter SF (CoCo3 720k) [AGI 2.072] - GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), - - // Mickey's Space Adventure - // Preagi game - GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC), - -#if 0 - // Mixed-Up Mother Goose (Amiga) 1.1 - // Problematic: crashes - // Menus not tested - GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga), -#endif - - // Mixed Up Mother Goose (IIgs) - GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS), - - // Mixed-Up Mother Goose (PC) [AGI 2.915] - GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), - - // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072] - GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3), - - // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915] - GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1), - - // Police Quest 1 (Mac) 2.0G 12/3/87 - GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh), - - // Police Quest 1 (IIgs) 2.0B-88421 - GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS), - - // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310 - GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga), - - // Police Quest 1 (IIgs) 2.0A-88318 - GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS), - - // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911] - GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1), - - // Police Quest 1 (Russian) - GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC), - - // Police Quest 1 2.0G 12/3/87 - GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1), - - // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien? - // not sure about disk format -- dsymonds - GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1), - - // Police Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3), - - // Police Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (ST) 1.1A - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST), - - // Space Quest 1 (PC 360k) 1.1A [AGI 2.272] - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (PC 720k) 1.1A [AGI 2.272] - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (Amiga) 1.2 # 2.082 - // The original game did not have menus, they are enabled under ScummVM - GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga), - - // Space Quest 1 (Mac) 1.5D - GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh), - - // Space Quest 1 (IIgs) 2.2 - GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS), - - // Space Quest 1 (PC) 1.0X [AGI 2.089] - // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game - GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (Russian) - GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), - - // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917] - GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1), - - // Space Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (CoCo3 360k) [AGI 2.023] - GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 1 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3), - - // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936] - GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2), - - // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE) - GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS), - - { - // Space Quest 2 (Amiga) 2.0F - { - "sq2", - "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]", - { - { "logdir", 0, "28add5125484302d213911df60d2aded", 426}, - { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372}, - { NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_SQ2, - GType_V2, - 0, - 0x2936, - }, - - - // Space Quest 2 (Mac) 2.0D - GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh), - - // reported by Filippos (thebluegr) in bugreport #1654500 - // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912] - GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (Russian) - GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912] - GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC), - - // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915] - // Menus not tested - GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2), - - // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936] - GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2), - - // Space Quest 2 (CoCo3 360k) [AGI 2.023] - GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), - - // Space Quest 2 (CoCo3 360k) [AGI 2.072] - GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), - - // Troll's Tale - GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC), - - // Winnie the Pooh in the Hundred Acre Wood - GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC), - - // Winnie the Pooh in the Hundred Acre Wood (Amiga) - GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga), - - // Winnie the Pooh in the Hundred Acre Wood (C64) - GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64), - - // Winnie the Pooh in the Hundred Acre Wood (Apple //gs) - GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS), - - // Xmas Card 1986 (PC) [AGI 2.272] - GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD), - - // Xmas Card 1986 (CoCo3 360k) [AGI 2.072] - GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3), - - FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE), - FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"), - FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"), - FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"), - FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"), - FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"), - FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE), - FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"), - FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"), - FANMADE_I("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a"), - FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440), - FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256), - FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2), - FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL), - FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"), - FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"), - FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"), - FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"), - FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"), - FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"), - FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"), - FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"), - FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"), - FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"), - FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE), - FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE), - FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE), - FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE), - FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"), - FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"), - FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"), - FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE), - FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE), - FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"), - FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"), - FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"), - FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"), - FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"), - FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), - FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), - FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), - FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA), - FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"), - FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL), - FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"), - FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA), - FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"), - FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256), - FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"), - FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"), - FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"), - FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"), - FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"), - FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"), - FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"), - FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"), - FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"), - FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"), - FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"), - FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"), - FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3), - FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"), - FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"), - FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"), - FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"), - FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"), - FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"), - FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"), - FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"), - FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"), - FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"), - FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"), - - { - // Groza - { - "agi-fanmade", - "Groza (russian) [AGDS sample]", - AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"), - Common::RU_RUS, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_FANMADE, - GType_V2, - GF_AGDS, - 0x2440, - }, - - { - // Get Outta SQ - { - "agi-fanmade", - "Get Outta Space Quest", - AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_GETOUTTASQ, - GType_V2, - 0, - 0x2440, - }, - - FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE), - FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"), - FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"), - FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD), - FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"), - FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"), - FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE), - FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"), - FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE), - FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"), - FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"), - FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"), - FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"), - FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"), - FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"), - FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"), - FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"), - FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), - FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"), - FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"), - FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"), - FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"), - FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"), - FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"), - FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"), - FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"), - FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"), - FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"), - FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"), - FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"), - FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"), - FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"), - FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"), - FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE), - FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"), - FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"), - FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA), - FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE), - // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information? - FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"), - FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"), - FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"), - FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"), - FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"), - FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"), - FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"), - FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"), - FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"), - FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"), - FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"), - FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"), - FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"), - FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"), - FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA), - FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"), - FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"), - FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"), - FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"), - FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"), - FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"), - FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"), - FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"), - FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"), - FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"), - FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"), - // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"), - FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"), - FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"), - FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"), - FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"), - FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"), - FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"), - FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"), - FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"), - FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"), - FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"), - FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"), - FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"), - FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"), - FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"), - FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"), - FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), - FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), - FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), - FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE), - FANMADE_IF("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", GF_AGIMOUSE|GF_AGIPAL), - FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"), - FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE), - FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), - FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), - FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), - FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"), - FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"), - FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3), - FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), - FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), - FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), - FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), - FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), - FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"), - FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"), - FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"), - FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL), - FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"), - FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"), - FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"), - FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"), - FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"), - FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"), - FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"), - FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"), - FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"), - FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"), - FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"), - FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"), - FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"), - FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"), - FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"), - FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"), - FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"), - FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"), - FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"), - FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3), - FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"), - FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"), - FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"), - FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"), - FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"), - { - // V - The Graphical Adventure - { - "agi-fanmade", - "V - The Graphical Adventure (Demo 2)", - AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_USEEXTRAASTITLE, - GUIO_NONE - }, - GID_FANMADE, - GType_V3, - GF_FANMADE, - 0x3149, - }, - FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3), - - FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"), - FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"), - FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"), - - { AD_TABLE_END_MARKER, 0, 0, 0, 0 } -}; - -/** - * The fallback game descriptor used by the AGI engine's fallbackDetector. - * Contents of this struct are to be overwritten by the fallbackDetector. - */ -static AGIGameDescription g_fallbackDesc = { - { - "", - "", - AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor - Common::UNK_LANG, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_FANMADE, - GType_V2, - GF_FANMADE, - 0x2917, -}; +#include "agi/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -984,8 +150,6 @@ static const ADParams detectionParams = { 1 }; -} // End of namespace Agi - using namespace Agi; class AgiMetaEngine : public AdvancedMetaEngine { diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h new file mode 100644 index 0000000000..96cb12cdd2 --- /dev/null +++ b/engines/agi/detection_tables.h @@ -0,0 +1,861 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +namespace Agi { + +using Common::GUIO_NONE; + +#define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ + { \ + id, \ + name, \ + AD_ENTRY1s(fname,md5,size), \ + lang, \ + platform, \ + ADGF_NO_FLAGS, \ + GUIO_NONE \ + }, \ + gid, \ + interp, \ + features, \ + ver, \ + } + +#define GAME_LVFPNF(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ + { \ + id, \ + name, \ + AD_ENTRY1s(fname,md5,size), \ + lang, \ + platform, \ + ADGF_USEEXTRAASTITLE, \ + GUIO_NONE \ + }, \ + gid, \ + interp, \ + features, \ + ver, \ + } + +#define GAME(id,name,md5,ver,gid) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) +#define GAME3(id,name,fname,md5,ver,gid) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) + +#define GAME_P(id,name,md5,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) + +#define GAME_FP(id,name,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) + +#define GAME_PS(id,name,md5,size,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) + +#define GAME_LPS(id,name,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) + +#define GAME_LFPS(id,name,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) + +#define GAME3_P(id,name,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) + +#define GAMEpre_P(id,name,fname,md5,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) + +#define GAMEpre_PS(id,name,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) + +#define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) + +#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) + +#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) + +#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) + +#define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) +#define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) + +#define FANMADE_V(name,md5,ver) FANMADE_LVF(name,md5,Common::EN_ANY,ver,0) +#define FANMADE_F(name,md5,features) FANMADE_LF(name,md5,Common::EN_ANY,features) +#define FANMADE_L(name,md5,lang) FANMADE_LF(name,md5,lang,0) +#define FANMADE_I(id,name,md5) FANMADE_IF(id,name,md5,0) + +#define FANMADE(name,md5) FANMADE_F(name,md5,0) + +static const AGIGameDescription gameDescriptions[] = { + + // AGI Demo 1 (PC) 05/87 [AGI 2.425] + GAME("agidemo", "Demo 1 1987-05-20", "9c4a5b09cc3564bc48b4766e679ea332", 0x2440, GID_AGIDEMO), + + // AGI Demo 2 (IIgs) 1.0C (Censored) + GAME_P("agidemo", "Demo 2 1987-11-24 1.0C", "580ffdc569ff158f56fb92761604f70e", 0x2917, GID_AGIDEMO, Common::kPlatformApple2GS), + + // AGI Demo 2 (PC 3.5") 11/87 [AGI 2.915] + GAME("agidemo", "Demo 2 1987-11-24 3.5\"", "e8ebeb0bbe978172fe166f91f51598c7", 0x2917, GID_AGIDEMO), + + // AGI Demo 2 (PC 5.25") 11/87 [v1] [AGI 2.915] + GAME("agidemo", "Demo 2 1987-11-24 [version 1] 5.25\"", "852ac303a374df62571642ca1e2d1f0a", 0x2917, GID_AGIDEMO), + + // AGI Demo 2 (PC 5.25") 01/88 [v2] [AGI 2.917] + GAME("agidemo", "Demo 2 1987-11-25 [version 2] 5.25\"", "1503f02086ea9f388e7e041c039eaa69", 0x2917, GID_AGIDEMO), + + // AGI Demo 3 (PC) 09/88 [AGI 3.002.102] + GAME3("agidemo", "Demo 3 1988-09-13", "dmdir", "289c7a2c881f1d973661e961ced77d74", 0x3149, GID_AGIDEMO), + + // AGI Demo for Kings Quest III and Space Quest I + GAME("agidemo", "Demo Kings Quest III and Space Quest I", "502e6bf96827b6c4d3e67c9cdccd1033", 0x2272, GID_AGIDEMO), + + // Black Cauldron (Amiga) 2.00 6/14/87 + GAME_P("bc", "2.00 1987-06-14", "7b01694af21213b4727bb94476f64eb5", 0x2440, GID_BC, Common::kPlatformAmiga), + + // Black Cauldron (Apple IIgs) 1.0O 2/24/89 (CE) + // Menus not tested + GAME3_P("bc", "1.0O 1989-02-24 (CE)", "bcdir", "dc09d30b147242692f4f85b9811962db", 0x3149, 0, GID_BC, Common::kPlatformApple2GS), + + // Black Cauldron (PC) 2.00 6/14/87 [AGI 2.439] + GAME("bc", "2.00 1987-06-14", "7f598d4712319b09d7bd5b3be10a2e4a", 0x2440, GID_BC), + + // Black Cauldron (Russian) + GAME_LPS("bc", "", "b7de782dfdf8ea7dde8064f09804bcf5", 357, Common::RU_RUS, 0x2440, GID_BC, Common::kPlatformPC), + + // Black Cauldron (PC 5.25") 2.10 11/10/88 [AGI 3.002.098] + GAME3("bc", "2.10 1988-11-10 5.25\"", "bcdir", "0c5a9acbcc7e51127c34818e75806df6", 0x3149, GID_BC), + + // Black Cauldron (PC) 2.10 [AGI 3.002.097] + GAME3("bc", "2.10", "bcdir", "0de3953c9225009dc91e5b0d1692967b", 0x3149, GID_BC), + + // Black Cauldron (CoCo3 360k) [AGI 2.023] + GAME_PS("bc", "", "51212c54808ade96176f201ae0ac7a6f", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + + // Black Cauldron (CoCo3 360k) [AGI 2.072] + GAME_PS("bc", "updated", "c4e1937f74e8100cd0152b904434d8b4", 357, 0x2440, GID_BC, Common::kPlatformCoCo3), + +// TODO +// These aren't supposed to work now as they require unsupported agi engine 2.01 +#if 0 + // Donald Duck's Playground (Amiga) 1.0C + // Menus not tested + GAME_P("ddp", "1.0C 1987-04-27", "550971d196f65190a5c760d2479406ef", 0x2272, GID_DDP, Common::kPlatformAmiga), + + // Donald Duck's Playground (ST) 1.0A 8/8/86 + // Menus not tested + GAME("ddp", "1.0A 1986-08-08", "64388812e25dbd75f7af1103bc348596", 0x2272, GID_DDP), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Menus not tested + GAME_PS("ddp", "1.0C 1986-06-09", "550971d196f65190a5c760d2479406ef", 132, 0x2272, GID_DDP, Common::kPlatformPC), +#endif + + // Gold Rush! (Amiga) 1.01 1/13/89 aka 2.05 3/9/89 # 2.316 + GAME3_PS("goldrush", "1.01 1989-01-13 aka 2.05 1989-03-09", "dirs", "a1d4de3e75c2688c1e2ca2634ffc3bd8", 2399, 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAmiga), + + // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88 + // Menus not tested + GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformApple2GS), + + // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88 + GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST), + + // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] + GAME3("goldrush", "2.01 1988-12-22 5.25\"", "grdir", "db733d199238d4009a9e95f11ece34e9", 0x3149, GID_GOLDRUSH), + + // Gold Rush! (PC 3.5") 2.01 12/22/88 [AGI 3.002.149] + GAME3("goldrush", "2.01 1988-12-22 3.5\"", "grdir", "6a285235745f69b4b421403659497216", 0x3149, GID_GOLDRUSH), + + // Gold Rush! (PC 3.5", bought from The Software Farm) 3.0 1998-12-22 [AGI 3.002.149] + GAME3("goldrush", "3.0 1998-12-22 3.5\"", "grdir", "6882b6090473209da4cd78bb59f78dbe", 0x3149, GID_GOLDRUSH), + + { + // Gold Rush! (PC 5.25") 2.01 12/22/88 [AGI 3.002.149] + { + "goldrush", + "2.01 1988-12-22", + { + { "grdir", 0, "db733d199238d4009a9e95f11ece34e9", 2399}, + { "vol.0", 0, "4b6423d143674d3757ab1b875d25951d", 25070}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_GOLDRUSH, + GType_V3, + GF_MACGOLDRUSH, + 0x3149, + }, + + + // Gold Rush! (CoCo3 720k) [AGI 2.023] + GAME_PS("goldrush", "", "0a41b65efc0cd6c4271e957e6ffbbd8e", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + + // Gold Rush! (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("goldrush", "updated", "c49bf56bf91e31a4601a604e51ef8bfb", 744, 0x2440, GID_GOLDRUSH, Common::kPlatformCoCo3), + + // King's Quest 1 (Amiga) 1.0U # 2.082 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq1", "1.0U 1986", "246c695324f1c514aee2b904fa352fad", 0x2440, GF_MENUS, GID_KQ1, Common::kPlatformAmiga), + + // King's Quest 1 (ST) 1.0V + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq1", "1.0V 1986", "c3a017e556c4b0eece366a4cd9abb657", 0x2272, GF_MENUS, GID_KQ1, Common::kPlatformAtariST), + + // King's Quest 1 (IIgs) 1.0S-88223 + // Menus not tested + GAME_P("kq1", "1.0S 1988-02-23", "f4277aa34b43d37382bc424c81627617", 0x2272, GID_KQ1, Common::kPlatformApple2GS), + + // King's Quest 1 (Mac) 2.0C + GAME_P("kq1", "2.0C 1987-03-26", "d4c4739d4ac63f7dbd29255425077d48", 0x2440, GID_KQ1, Common::kPlatformMacintosh), + + // King's Quest 1 (PC 5.25"/3.5") 2.0F [AGI 2.917] + GAME("kq1", "2.0F 1987-05-05 5.25\"/3.5\"", "10ad66e2ecbd66951534a50aedcd0128", 0x2917, GID_KQ1), + + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "", "10ad66e2ecbd66951534a50aedcd0128", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq1", "fixed", "4c8ef8b5d2f1b6c1a93e456d1f1ffc74", 768, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq1", "updated", "94087178c78933a4af3cd24d1c8dd7b2", 315, 0x2440, GID_KQ1, Common::kPlatformCoCo3), + + // King's Quest 2 (IIgs) 2.0A 6/16/88 (CE) + GAME_P("kq2", "2.0A 1988-06-16 (CE)", "5203c8b95250a2ecfee93ddb99414753", 0x2917, GID_KQ2, Common::kPlatformApple2GS), + + // King's Quest 2 (Amiga) 2.0J (Broken) + GAME_P("kq2", "2.0J 1987-01-29 [OBJECT decrypted]", "b866f0fab2fad91433a637a828cfa410", 0x2440, GID_KQ2, Common::kPlatformAmiga), + + // King's Quest 2 (Mac) 2.0R + GAME_P("kq2", "2.0R 1988-03-23", "cbdb0083317c8e7cfb7ac35da4bc7fdc", 0x2440, GID_KQ2, Common::kPlatformMacintosh), + + // King's Quest 2 (PC) 2.1 [AGI 2.411]; entry from DAGII, but missing from Sarien? + // XXX: any major differences from 2.411 to 2.440? + GAME("kq2", "2.1 1987-04-10", "759e39f891a0e1d86dd29d7de485c6ac", 0x2440, GID_KQ2), + + // King's Quest 2 (PC 5.25"/3.5") 2.2 [AGI 2.426] + GAME("kq2", "2.2 1987-05-07 5.25\"/3.5\"", "b944c4ff18fb8867362dc21cc688a283", 0x2917, GID_KQ2), + + // King's Quest 2 (Russian) + GAME_LPS("kq2", "", "35211c574ececebdc723b23e35f99275", 543, Common::RU_RUS, 0x2917, GID_KQ2, Common::kPlatformPC), + + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "", "b944c4ff18fb8867362dc21cc688a283", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("kq2", "updated", "f64a606de740a5348f3d125c03e989fe", 543, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("kq2", "fixed", "fb33ac2768a94a89117a270771db465c", 768, 0x2440, GID_KQ2, Common::kPlatformCoCo3), + + // King's Quest 3 (Amiga) 1.01 11/8/86 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("kq3", "1.01 1986-11-08", "8ab343306df0e2d98f136be4e8cfd0ef", 0x2440, GF_MENUS, GID_KQ3, Common::kPlatformAmiga), + + // King's Quest 3 (ST) 1.02 11/18/86 + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("kq3", "1.02 1986-11-18", "8846df2654302b623217ba8bd6d657a9", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformAtariST), + + // King's Quest 3 (Mac) 2.14 3/15/88 + GAME_P("kq3", "2.14 1988-03-15", "7639c0da5ce94848227d409351fabda2", 0x2440, GID_KQ3, Common::kPlatformMacintosh), + + // King's Quest 3 (IIgs) 2.0A 8/28/88 (CE) + GAME_P("kq3", "2.0A 1988-08-28 (CE)", "ac30b7ca5a089b5e642fbcdcbe872c12", 0x2917, GID_KQ3, Common::kPlatformApple2GS), + + // King's Quest 3 (Amiga) 2.15 11/15/89 # 2.333 + // Original pauses with ESC, has menus accessible with mouse. + // ver = 0x3086 -> menus accessible with ESC or mouse, bug #2835581 (KQ3: Game Crash When Leaving Tavern as Fly). + // ver = 0x3149 -> menus accessible with mouse, ESC pauses game, bug #2835581 disappears. + GAME3_PS("kq3", "2.15 1989-11-15", "dirs", "8e35bded2bc5cf20f5eec2b15523b155", 1805, 0x3149, 0, GID_KQ3, Common::kPlatformAmiga), + + // King's Quest 3 (PC) 1.01 11/08/86 [AGI 2.272] + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("kq3", "1.01 1986-11-08", "9c2b34e7ffaa89c8e2ecfeb3695d444b", 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), + + // King's Quest 3 (Russian) + GAME_LFPS("kq3", "", "5856dec6ccb9c4b70aee21044a19270a", 390, Common::RU_RUS, 0x2272, GF_ESCPAUSE, GID_KQ3, Common::kPlatformPC), + + // King's Quest 3 (PC 5.25") 2.00 5/25/87 [AGI 2.435] + GAME("kq3", "2.00 1987-05-25 5.25\"", "18aad8f7acaaff760720c5c6885b6bab", 0x2440, GID_KQ3), + + // King's Quest 3 (Mac) 2.14 3/15/88 + // Menus not tested + GAME_P("kq3", "2.14 1988-03-15 5.25\"", "7650e659c7bc0f1e9f8a410b7a2e9de6", 0x2440, GID_KQ3, Common::kPlatformMacintosh), + + // King's Quest 3 (PC 3.5") 2.14 3/15/88 [AGI 2.936] + GAME("kq3", "2.14 1988-03-15 3.5\"", "d3d17b77b3b3cd13246749231d9473cd", 0x2936, GID_KQ3), + + // King's Quest 3 (CoCo3 158k/360k) [AGI 2.023] + GAME_PS("kq3", "", "5a6be7d16b1c742c369ef5cc64fefdd2", 429, 0x2440, GID_KQ3, Common::kPlatformCoCo3), + + // King's Quest 4 (PC 5.25") 2.0 7/27/88 [AGI 3.002.086] + GAME3("kq4", "2.0 1988-07-27", "kq4dir", "f50f7f997208ca0e35b2650baec43a2d", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.0 7/27/88 [AGI 3.002.086] + GAME3("kq4", "2.0 1988-07-27 3.5\"", "kq4dir", "fe44655c42f16c6f81046fdf169b6337", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.2 9/27/88 [AGI 3.002.086] + // Menus not tested + GAME3("kq4", "2.2 1988-09-27 3.5\"", "kq4dir", "7470b3aeb49d867541fc66cc8454fb7d", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 5.25") 2.3 9/27/88 [AGI 3.002.086] + GAME3("kq4", "2.3 1988-09-27", "kq4dir", "6d7714b8b61466a5f5981242b993498f", 0x3086, GID_KQ4), + + // King's Quest 4 (PC 3.5") 2.3 9/27/88 [AGI 3.002.086] + GAME3("kq4", "2.3 1988-09-27 3.5\"", "kq4dir", "82a0d39af891042e99ac1bd6e0b29046", 0x3086, GID_KQ4), + + // King's Quest 4 (IIgs) 1.0K 11/22/88 (CE) + // Menus not tested + GAME3_P("kq4", "1.0K 1988-11-22", "kq4dir", "8536859331159f15012e35dc82cb154e", 0x3086, 0, GID_KQ4, Common::kPlatformApple2GS), + + // King's Quest 4 demo (PC) [AGI 3.002.102] + // Menus not tested + GAME3("kq4", "Demo 1988-12-20", "dmdir", "a3332d70170a878469d870b14863d0bf", 0x3149, GID_KQ4), + + // King's Quest 4 (CoCo3 720k) [AGI 2.023] + GAME_PS("kq4", "", "9e7729a28e749ca241d2bf71b9b2dbde", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + + // King's Quest 4 (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("kq4", "updated", "1959ca10739edb34069bb504dbd74805", 741, 0x2440, GID_KQ4, Common::kPlatformCoCo3), + + // Leisure Suit Larry 1 (PC 5.25"/3.5") 1.00 6/1/87 [AGI 2.440] + GAME("lsl1", "1.00 1987-06-01 5.25\"/3.5\"", "1fe764e66857e7f305a5f03ca3f4971d", 0x2440, GID_LSL1), + + // Leisure Suit Larry 1 Polish + GAME_LPS("lsl1", "2.00 2001-12-11", "7ba1fccc46d27c141e704706c1d0a85f", 303, Common::PL_POL, 0x2440, GID_LSL1, Common::kPlatformPC), + + // Leisure Suit Larry 1 Polish - Demo + GAME_LPS("lsl1", "Demo", "3b2f564306c401dff6334441df967ddd", 666, Common::PL_POL, 0x2917, GID_LSL1, Common::kPlatformPC), + + // Leisure Suit Larry 1 (ST) 1.04 6/18/87 + GAME_P("lsl1", "1.04 1987-06-18", "8b579f8673fe9448c2538f5ed9887cf0", 0x2440, GID_LSL1, Common::kPlatformAtariST), + + // Leisure Suit Larry 1 (Amiga) 1.05 6/26/87 # x.yyy + GAME_P("lsl1", "1.05 1987-06-26", "3f5d26d8834ca49c147fb60936869d56", 0x2440, GID_LSL1, Common::kPlatformAmiga), + + // Leisure Suit Larry 1 (IIgs) 1.0E + GAME_P("lsl1", "1.0E 1987", "5f9e1dd68d626c6d303131c119582ad4", 0x2440, GID_LSL1, Common::kPlatformApple2GS), + + // Leisure Suit Larry 1 (Mac) 1.05 6/26/87 + GAME_P("lsl1", "1.05 1987-06-26", "8a0076429890531832f0dc113285e31e", 0x2440, GID_LSL1, Common::kPlatformMacintosh), + + // Leisure Suit Larry 1 (CoCo3 158k/360k) [AGI 2.072] + GAME_PS("lsl1", "", "a2de1fe76565c3e8b40c9d036b5e5612", 198, 0x2440, GID_LSL1, Common::kPlatformCoCo3), + + // Manhunter NY (ST) 1.03 10/20/88 + GAME3_P("mh1", "1.03 1988-10-20", "mhdir", "f2d58056ad802452d60776ee920a52a6", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), + + // Manhunter NY (IIgs) 2.0E 10/05/88 (CE) + GAME3_P("mh1", "2.0E 1988-10-05 (CE)", "mhdir", "2f1509f76f24e6e7d213f2dadebbf156", 0x3149, 0, GID_MH1, Common::kPlatformApple2GS), + + // Manhunter NY (Amiga) 1.06 3/18/89 + GAME3_P("mh1", "1.06 1989-03-18", "dirs", "92c6183042d1c2bb76236236a7d7a847", 0x3149, GF_OLDAMIGAV20, GID_MH1, Common::kPlatformAmiga), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Manhunter NY (PC 5.25") 1.22 8/31/88 [AGI 3.002.107] + GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "0c7b86f05fe02c2e26cff1b07450b82a", 2123, 0x3149, 0, GID_MH1, Common::kPlatformPC), + + // Manhunter NY (PC 3.5") 1.22 8/31/88 [AGI 3.002.102] + GAME3_PS("mh1", "1.22 1988-08-31", "mhdir", "5b625329021ad49fd0c1d6f2d6f54bba", 2141, 0x3149, 0, GID_MH1, Common::kPlatformPC), + + // Manhunter NY (CoCo3 720k) [AGI 2.023] + GAME_PS("mh1", "", "b968285caf2f591c78dd9c9e26ab8974", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + + // Manhunter NY (CoCo3 360k/720k) [AGI 2.072] + GAME_PS("mh1", "updated", "d47da950c62289f8d4ccf36af73365f2", 495, 0x2440, GID_MH1, Common::kPlatformCoCo3), + + // Manhunter SF (ST) 1.0 7/29/89 + GAME3_P("mh2", "1.0 1989-07-29", "mh2dir", "5e3581495708b952fea24438a6c7e040", 0x3149, 0, GID_MH1, Common::kPlatformAtariST), + + // Manhunter SF (Amiga) 3.06 8/17/89 # 2.333 + GAME3_PS("mh2", "3.06 1989-08-17", "dirs", "b412e8a126368b76696696f7632d4c16", 2573, 0x3086, GF_OLDAMIGAV20, GID_MH2, Common::kPlatformAmiga), + + // Manhunter SF (PC 5.25") 3.03 8/17/89 [AGI 3.002.149] + GAME3("mh2", "3.03 1989-08-17 5.25\"", "mh2dir", "b90e4795413c43de469a715fb3c1fa93", 0x3149, GID_MH2), + + // Manhunter SF (PC 3.5") 3.02 7/26/89 [AGI 3.002.149] + GAME3("mh2", "3.02 1989-07-26 3.5\"", "mh2dir", "6fb6f0ee2437704c409cf17e081ba152", 0x3149, GID_MH2), + + // Manhunter SF (CoCo3 720k) [AGI 2.023] + GAME_PS("mh2", "", "acaaa577e10d1753c5a74f6ae1d858d4", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + + // Manhunter SF (CoCo3 720k) [AGI 2.072] + GAME_PS("mh2", "updated", "c64875766700196e72a92359f70f45a9", 591, 0x2440, GID_MH2, Common::kPlatformCoCo3), + + // Mickey's Space Adventure + // Preagi game + GAMEpre_P("mickey", "", "1.pic", "b6ec04c91a05df374792872c4d4ce66d", 0x0000, GID_MICKEY, Common::kPlatformPC), + +#if 0 + // Mixed-Up Mother Goose (Amiga) 1.1 + // Problematic: crashes + // Menus not tested + GAME3_PS("mixedup", "1.1 1986-12-10", "dirs", "5c1295fe6daaf95831195ba12894dbd9", 2021, 0x3086, 0, GID_MIXEDUP, Common::kPlatformAmiga), +#endif + + // Mixed Up Mother Goose (IIgs) + GAME_P("mixedup", "1987", "3541954a7303467c6df87665312ffb6a", 0x2917, GID_MIXEDUP, Common::kPlatformApple2GS), + + // Mixed-Up Mother Goose (PC) [AGI 2.915] + GAME("mixedup", "1987-11-10", "e524655abf9b96a3b179ffcd1d0f79af", 0x2917, GID_MIXEDUP), + + // Mixed-Up Mother Goose (CoCo3 360k) [AGI 2.072] + GAME_PS("mixedup", "", "44e63e9b4d4822a31edea0e8a7e7eac4", 606, 0x2440, GID_MIXEDUP, Common::kPlatformCoCo3), + + // Police Quest 1 (PC) 2.0E 11/17/87 [AGI 2.915] + GAME("pq1", "2.0E 1987-11-17", "2fd992a92df6ab0461d5a2cd83c72139", 0x2917, GID_PQ1), + + // Police Quest 1 (Mac) 2.0G 12/3/87 + GAME_P("pq1", "2.0G 1987-12-03", "805750b66c1c5b88a214e67bfdca17a1", 0x2440, GID_PQ1, Common::kPlatformMacintosh), + + // Police Quest 1 (IIgs) 2.0B-88421 + GAME_P("pq1", "2.0B 1988-04-21", "e7c175918372336461e3811d594f482f", 0x2917, GID_PQ1, Common::kPlatformApple2GS), + + // Police Quest 1 (Amiga) 2.0B 2/22/89 # 2.310 + GAME3_PS("pq1", "2.0B 1989-02-22", "dirs", "cfa93e5f2aa7378bddd10ad6746a2ffb", 1613, 0x3149, 0, GID_PQ1, Common::kPlatformAmiga), + + // Police Quest 1 (IIgs) 2.0A-88318 + GAME_P("pq1", "2.0A 1988-03-18", "8994e39d0901de3d07cecfb954075bb5", 0x2917, GID_PQ1, Common::kPlatformApple2GS), + + // Police Quest 1 (PC) 2.0A 10/23/87 [AGI 2.903/2.911] + GAME("pq1", "2.0A 1987-10-23", "b9dbb305092851da5e34d6a9f00240b1", 0x2917, GID_PQ1), + + // Police Quest 1 (Russian) + GAME_LPS("pq1", "", "604cc8041d24c4c7e5fa8baf386ef76e", 360, Common::RU_RUS, 0x2917, GID_PQ1, Common::kPlatformPC), + + // Police Quest 1 2.0G 12/3/87 + GAME("pq1", "2.0G 1987-12-03 5.25\"/ST", "231f3e28170d6e982fc0ced4c98c5c1c", 0x2440, GID_PQ1), + + // Police Quest 1 (PC) 2.0G 12/3/87; entry from DAGII, but missing from Sarien? + // not sure about disk format -- dsymonds + GAME("pq1", "2.0G 1987-12-03", "d194e5d88363095f55d5096b8e32fbbb", 0x2917, GID_PQ1), + + // Police Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("pq1", "", "28a077041f75aab78f66804800940085", 375, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + + // Police Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("pq1", "updated", "63b9a9c6eec154751dd446cd3693e0e2", 768, 0x2440, GID_PQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (ST) 1.1A + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 1986-02-06", "6421fb64b0e6604c9dd065975d9279e9", 0x2440, GF_MENUS, GID_SQ1, Common::kPlatformAtariST), + + // Space Quest 1 (PC 360k) 1.1A [AGI 2.272] + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 1986-11-13", "8d8c20ab9f4b6e4817698637174a1cb6", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (PC 720k) 1.1A [AGI 2.272] + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.1A 720kb", "0a92b1be7daf3bb98caad3f849868aeb", 0x2272, GF_MENUS, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (Amiga) 1.2 # 2.082 + // The original game did not have menus, they are enabled under ScummVM + GAME_FP("sq1", "1.2 1986", "0b216d931e95750f1f4837d6a4b821e5", 0x2440, GF_MENUS | GF_OLDAMIGAV20, GID_SQ1, Common::kPlatformAmiga), + + // Space Quest 1 (Mac) 1.5D + GAME_P("sq1", "1.5D 1987-04-02", "ce88419aadd073d1c6682d859b3d8aa2", 0x2440, GID_SQ1, Common::kPlatformMacintosh), + + // Space Quest 1 (IIgs) 2.2 + GAME_P("sq1", "2.2 1987", "64b9b3d04c1066d36e6a6e56187a83f7", 0x2917, GID_SQ1, Common::kPlatformApple2GS), + + // Space Quest 1 (PC) 1.0X [AGI 2.089] + // Does not have menus, crashes if menus are enforced. Therefore, ESC pauses the game + GAME_FP("sq1", "1.0X 1986-09-24", "af93941b6c51460790a9efa0e8cb7122", 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (Russian) + GAME_LFPS("sq1", "", "a279eb8ddbdefdb1ea6adc827a1d632a", 372, Common::RU_RUS, 0x2089, GF_ESCPAUSE, GID_SQ1, Common::kPlatformPC), + + // Space Quest 1 (PC 5.25"/3.5") 2.2 [AGI 2.426/2.917] + GAME("sq1", "2.2 1987-05-07 5.25\"/3.5\"", "5d67630aba008ec5f7f9a6d0a00582f4", 0x2440, GID_SQ1), + + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "", "5d67630aba008ec5f7f9a6d0a00582f4", 372, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq1", "fixed", "ca822b768b6462e410423ea7f498daee", 768, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 1 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq1", "updated", "7fa54e6bb7ffeb4cf20eca39d86f5fb2", 387, 0x2440, GID_SQ1, Common::kPlatformCoCo3), + + // Space Quest 2 (PC 3.5") 2.0D [AGI 2.936] + GAME("sq2", "2.0D 1988-03-14 3.5\"", "85390bde8958c39830e1adbe9fff87f3", 0x2936, GID_SQ2), + + // Space Quest 2 (IIgs) 2.0A 7/25/88 (CE) + GAME_P("sq2", "2.0A 1988-07-25 (CE)", "5dfdac98dd3c01fcfb166529f917e911", 0x2936, GID_SQ2, Common::kPlatformApple2GS), + + { + // Space Quest 2 (Amiga) 2.0F + { + "sq2", + "2.0F 1986-12-09 [VOL.2->PICTURE.16 broken]", + { + { "logdir", 0, "28add5125484302d213911df60d2aded", 426}, + { "object", 0, "5dc52be721257719f4b311a84ce22b16", 372}, + { NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_SQ2, + GType_V2, + 0, + 0x2936, + }, + + + // Space Quest 2 (Mac) 2.0D + GAME_P("sq2", "2.0D 1988-04-04", "bfbebe0b59d83f931f2e1c62ce9484a7", 0x2936, GID_SQ2, Common::kPlatformMacintosh), + + // reported by Filippos (thebluegr) in bugreport #1654500 + // Space Quest 2 (PC 5.25") 2.0A [AGI 2.912] + GAME_PS("sq2", "2.0A 1987-11-06 5.25\"", "ad7ce8f800581ecc536f3e8021d7a74d", 423, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (Russian) + GAME_LPS("sq2", "", "ba21c8934caf28e3ba45ce7d1cd6b041", 423, Common::RU_RUS, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (PC 3.5") 2.0A [AGI 2.912] + GAME_PS("sq2", "2.0A 1987-11-06 3.5\"", "6c25e33d23b8bed42a5c7fa63d588e5c", 423, 0x2917, GID_SQ2, Common::kPlatformPC), + + // Space Quest 2 (PC 5.25"/ST) 2.0C/A [AGI 2.915] + // Menus not tested + GAME("sq2", "2.0C/A 5.25\"/ST", "bd71fe54869e86945041700f1804a651", 0x2917, GID_SQ2), + + // Space Quest 2 (PC 3.5") 2.0F [AGI 2.936] + GAME("sq2", "2.0F 1989-01-05 3.5\"", "28add5125484302d213911df60d2aded", 0x2936, GID_SQ2), + + // Space Quest 2 (CoCo3 360k) [AGI 2.023] + GAME_PS("sq2", "", "12973d39b892dc9d280257fd271e9597", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + + // Space Quest 2 (CoCo3 360k) [AGI 2.072] + GAME_PS("sq2", "updated", "d24f19b047e65e1763eff4b46f3d50df", 768, 0x2440, GID_SQ2, Common::kPlatformCoCo3), + + // Troll's Tale + GAMEpre_PS("troll", "", "troll.img", "62903f264b3d849be4214b3a5c42a2fa", 184320, 0x0000, GID_TROLL, Common::kPlatformPC), + + // Winnie the Pooh in the Hundred Acre Wood + GAMEpre_P("winnie", "", "title.pic", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformPC), + + // Winnie the Pooh in the Hundred Acre Wood (Amiga) + GAMEpre_P("winnie", "", "title", "2e7900c1ccaa7671d65405f6d1efed30", 0x0000, GID_WINNIE, Common::kPlatformAmiga), + + // Winnie the Pooh in the Hundred Acre Wood (C64) + GAMEpre_P("winnie", "", "title.pic", "d4eb97cffc866110f71e1ec9f84fe643", 0x0000, GID_WINNIE, Common::kPlatformC64), + + // Winnie the Pooh in the Hundred Acre Wood (Apple //gs) + GAMEpre_P("winnie", "", "title.pic", "45e06010a3c61d78f4661103c901ae11", 0x0000, GID_WINNIE, Common::kPlatformApple2GS), + + // Xmas Card 1986 (PC) [AGI 2.272] + GAME("xmascard", "1986-11-13 [version 1]", "3067b8d5957e2861e069c3c0011bd43d", 0x2272, GID_XMASCARD), + + // Xmas Card 1986 (CoCo3 360k) [AGI 2.072] + GAME_PS("xmascard", "", "25ad35e9628fc77e5e0dd35852a272b6", 768, 0x2440, GID_XMASCARD, Common::kPlatformCoCo3), + + FANMADE_F("2 Player Demo", "4279f46b3cebd855132496476b1d2cca", GF_AGIMOUSE), + FANMADE("AGI Contest 1 Template", "d879aed25da6fc655564b29567358ae2"), + FANMADE("AGI Contest 2 Template", "5a2fb2894207eff36c72f5c1b08bcc07"), + FANMADE("AGI Mouse Demo 0.60 demo 1", "c07e2519de674c67386cb2cc6f2e3904"), + FANMADE("AGI Mouse Demo 0.60 demo 2", "cc49d8b88ed6faf4f53ce92c84e0fe1b"), + FANMADE("AGI Mouse Demo 0.70", "3497c291e4afb6f758e61740678a2aec"), + FANMADE_F("AGI Mouse Demo 1.00", "20397f0bf0ef936f416bb321fb768fc7", GF_AGIMOUSE), + FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"), + FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"), + FANMADE_I("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a"), + FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440), + FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256), + FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2), + FANMADE_LF("Abrah: L'orphelin de l'espace (v1.2)", "b7b6d1539e14d5a26fa3088288e1badc", Common::FR_FRA, GF_AGIPAL), + FANMADE("Acidopolis", "7017db1a4b726d0d59e65e9020f7d9f7"), + FANMADE("Agent 0055 (v1.0)", "c2b34a0c77acb05482781dda32895f24"), + FANMADE("Agent 06 vs. The Super Nazi", "136f89ca9f117c617e88a85119777529"), + FANMADE("Agent Quest", "59e49e8f72058a33c00d60ee1097e631"), + FANMADE("Al Pond - On Holiday (v1.0)", "a84975496b42d485920e886e92eed68b"), + FANMADE("Al Pond - On Holiday (v1.1)", "7c95ac4689d0c3bfec61e935f3093634"), + FANMADE("Al Pond - On Holiday (v1.3)", "8f30c260de9e1dd3d8b8f89cc19d2633"), + FANMADE("Al Pond 1 - Al Lives Forever (v1.0)", "e8921c3043b749b056ff51f56d1b451b"), + FANMADE("Al Pond 1 - Al Lives Forever (v1.3)", "fb4699474054962e0dbfb4cf12ca52f6"), + FANMADE("Apocalyptic Quest (v0.03 Teaser)", "42ced528b67965d3bc3b52c635f94a57"), + FANMADE_F("Apocalyptic Quest (v4.00 Alpha 1)", "e15581628d84949b8d352d224ec3184b", GF_AGIMOUSE), + FANMADE_F("Apocalyptic Quest (v4.00 Alpha 2)", "0eee850005860e46345b38fea093d194", GF_AGIMOUSE), + FANMADE_F("Band Quest (Demo)", "7326abefd793571cc17ed0db647bdf34", GF_AGIMOUSE), + FANMADE_F("Band Quest (Early Demo)", "de4758dd34676b248c8301b32d93bc6f", GF_AGIMOUSE), + FANMADE("Beyond the Titanic 2", "9b8de38dc64ffb3f52b7877ea3ebcef9"), + FANMADE("Biri Quest 1", "1b08f34f2c43e626c775c9d6649e2f17"), + FANMADE("Bob The Farmboy", "e4b7df9d0830addee5af946d380e66d7"), + FANMADE_F("Boring Man 1: The Toad to Robinland", "d74481cbd227f67ace37ce6a5493039f", GF_AGIMOUSE), + FANMADE_F("Boring Man 2: Ho Man! This Game Sucks!", "250032ba105bdf7c1bc4fed767c2d37e", GF_AGIMOUSE), + FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"), + FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"), + FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"), + FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"), + FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"), + FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), + FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), + FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), + FANMADE_L("Coco Coq (French) - Coco Coq Dans la Base de Grostesteing (v1.0.2)", "ef579ebccfe5e356f9a557eb3b2d8649", Common::FR_FRA), + FANMADE("Corby's Murder Mystery (v1.0)", "4ebe62ac24c5a8c7b7898c8eb070efe5"), + FANMADE_F("DG: The AGIMouse Adventure (English v1.1)", "efe453b92bc1487ea69fbebede4d5f26", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_LF("DG: The AGIMouse Adventure (French v1.1)", "eb3d17ca466d672cbb95947e8d6e846a", Common::FR_FRA, GF_AGIMOUSE|GF_AGIPAL), + FANMADE("DG: The Adventure Game (English v1.1)", "0d6376d493fa7a21ec4da1a063e12b25"), + FANMADE_L("DG: The Adventure Game (French v1.1)", "258bdb3bb8e61c92b71f2f456cc69e23", Common::FR_FRA), + FANMADE("Dashiki (16 Colors)", "9b2c7b9b0283ab9f12bedc0cb6770a07"), + FANMADE_F("Dashiki (256 Colors)", "c68052bb209e23b39b55ff3d759958e6", GF_AGIMOUSE|GF_AGI256), + FANMADE("Date Quest 1 (v1.0)", "ba3dcb2600645be53a13170aa1a12e69"), + FANMADE("Date Quest 2 (v1.0 Demo)", "1602d6a2874856e928d9a8c8d2d166e9"), + FANMADE("Date Quest 2 (v1.0)", "f13f6fc85aa3e6e02b0c20408fb63b47"), + FANMADE("Dave's Quest (v0.07)", "f29c3660de37bacc1d23547a167f27c9"), + FANMADE("Dave's Quest (v0.17)", "da3772624cc4a86f7137db812f6d7c39"), + FANMADE("Disco Nights (Demo)", "dc5a2b21182ba38bdcd992a3a978e690"), + FANMADE("Dogs Quest - The Quest for the Golden Bone (v1.0)", "f197357edaaea0ff70880602d2f09b3e"), + FANMADE("Dr. Jummybummy's Space Adventure", "988bd81785f8a452440a2a8ac67f96aa"), + FANMADE("Ed Ward", "98be839b9f30cbedea4c9cee5442d827"), + FANMADE("Elfintard", "c3b847e9e9e978af9708df76a0751dc2"), + FANMADE("Enclosure (v1.01)", "f08e66fee9ecdde77db7ee9a10c96ba2"), + FANMADE("Enclosure (v1.03)", "e4a0613ed02401502e506ba3565a8c40"), + FANMADE_SVP("Enclosure", "fe98e6126db74c6cc6fd8fe395cc6e8c", 345, 0x2440, Common::kPlatformCoCo3), + FANMADE("Epic Fighting (v0.1)", "aff24a1b3bdd676187685c4d95ba4294"), + FANMADE("Escape Quest (v0.0.3)", "2346b65619b1da0298b715b06d1a45a1"), + FANMADE("Escape from the Desert (beta 1)", "dfdc634d340854bd6ece28024010758d"), + FANMADE("Escape from the Salesman", "e723ca4fe0f6f56affe039fbb4dbeb6c"), + FANMADE("Fu$k Quest 1 (final)", "1cd0587422313f6ca77d6a95988e88ed"), + FANMADE("Fu$k Quest 1", "1cd0587422313f6ca77d6a95988e88ed"), + FANMADE("Fu$k Quest 2 - Romancing the Bone (Teaser)", "d288355d71d9bb1639260ccaa3b2fbfe"), + FANMADE("Fu$k Quest 2 - Romancing the Bone", "294beeb7765c7ea6b05ed7b9bf7bff4f"), + FANMADE("Gennadi Tahab Autot - Mission Pack 1 - Kuressaare", "bfa5fe71978e6ccf3d4eedd430124015"), + FANMADE("Go West, Young Hippie", "ff31484ea465441cb5f3a0f8e956b716"), + FANMADE("Good Man (demo v3.41)", "3facd8a8f856b7b6e0f6c3200274d88c"), + + { + // Groza + { + "agi-fanmade", + "Groza (russian) [AGDS sample]", + AD_ENTRY1("logdir", "421da3a18004122a966d64ab6bd86d2e"), + Common::RU_RUS, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_FANMADE, + GType_V2, + GF_AGDS, + 0x2440, + }, + + { + // Get Outta SQ + { + "agi-fanmade", + "Get Outta Space Quest", + AD_ENTRY1("logdir", "aaea5b4a348acb669d13b0e6f22d4dc9"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_GETOUTTASQ, + GType_V2, + 0, + 0x2440, + }, + + FANMADE_F("Half-Death - Terror At White-Mesa", "b62c05d0ace878261392073f57ae788c", GF_AGIMOUSE), + FANMADE("Hank's Quest (v1.0 English) - Victim of Society", "64c15b3d0483d17888129100dc5af213"), + FANMADE("Hank's Quest (v1.1 English) - Victim of Society", "86d1f1dd9b0c4858d096e2a60cca8a14"), + FANMADE_L("Hank's Quest (v1.81 Dutch) - Slachtoffer Van Het Gebeuren", "41e53972d55ff3dff9e90d15fe1b659f", Common::NL_NLD), + FANMADE("Hank's Quest (v1.81 English) - Victim of Society", "7a776383282f62a57c3a960dafca62d1"), + FANMADE("Herbao (v0.2)", "6a5186fc8383a9060517403e85214fc2"), + FANMADE_F("Hitler's Legacy (v.0004q)", "a412881269ba34584bd0a3268e5a9863", GF_AGIMOUSE), + FANMADE("Hobbits", "4a1c1ef3a7901baf0ab45fde0cfadd89"), + FANMADE_F("Isabella Coq - A Present For My Dad", "55c6819f2330c4d5d6459874c9f123d9", GF_AGIMOUSE), + FANMADE("Jack & Julia - VAMPYR", "8aa0b9a26f8d5a4421067ab8cc3706f6"), + FANMADE("Jeff's Quest (v.5 alpha Jun 1)", "10f1720eed40c12b02a0f32df3e72ded"), + FANMADE("Jeff's Quest (v.5 alpha May 31)", "51ff71c0ed90db4e987a488ed3bf0551"), + FANMADE("Jen's Quest (Demo 1)", "361afb5bdb6160213a1857245e711939"), + FANMADE("Jen's Quest (Demo 2)", "3c321eee33013b289ab8775449df7df2"), + FANMADE("Jiggy Jiggy Uh! Uh!", "bc331588a71e7a1c8840f6cc9b9487e4"), + FANMADE("Jimmy In: The Alien Attack (v0.1)", "a4e9db0564a494728de7873684a4307c"), + FANMADE("Joe McMuffin In \"What's Cooking, Doc\" (v1.0)", "8a3de7e61a99cb605fa6d233dd91c8e1"), + FANMADE_LVF("Jolimie, le Village Maudit (v0.5)", "21818501636b3cb8ad5de5c1a66de5c2", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), + FANMADE_LVF("Jolimie, le Village Maudit (v1.1)", "68d7aef1161bb5972fe03efdf29ccb7f", Common::FR_FRA, 0x2936, GF_AGIMOUSE|GF_AGIPAL), + FANMADE("Journey Of Chef", "aa0a0b5a6364801ae65fdb96d6741df5"), + FANMADE("Jukebox (v1.0)", "c4b9c5528cc67f6ba777033830de7751"), + FANMADE("Justin Quest (v1.0 in development)", "103050989da7e0ffdc1c5e1793a4e1ec"), + FANMADE("J\xf5ulumaa (v0.05) (Estonian)", "53982ecbfb907e41392b3961ad1c3475"), + FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Mar 26)", "a25d7379d281b1b296d4785df90a8e78"), + FANMADE("Kings Quest 2 - Breast Intentions (v2.0 Aug 16)", "6b4f796d0421d2e12e501b511962e03a"), + FANMADE("Lasse Holm: The Quest for Revenge (v1.0)", "f9fbcc8a4ef510bfbb92423296ff4abb"), + FANMADE("Lawman for Hire", "c78b28bfd3767dd455b992cd8b7854fa"), + FANMADE("Lefty Goes on Vacation (Not in The Right Place)", "ccdc49a33870310b01f2c48b8a1f3c34"), + FANMADE("Les Ins\xe3parables (v1.0)", "4b780887cab0ecabc5eca319acb3acf2"), + FANMADE("Little Pirate (Demo 2 v0.6)", "437068efe4ec32d436da09d6f2ea56e1"), + FANMADE("Lost Eternity (v1.0)", "95f15c5632feb8a39e9ca3d9af35fcc9"), + FANMADE("MD Quest - The Search for Michiel (v0.10)", "2a6fcb21d2b5e4144c38ed817fabe8ee"), + FANMADE("Maale Adummin Quest", "ddfbeb33feb7cf78504fe4dba14ec63b"), + FANMADE("Monkey Man", "2322d03f997e8cc235d4578efff69cfa"), + FANMADE_F("Napalm Quest (v0.5)", "b659afb491d967bb34810d1c6ce22093", GF_AGIMOUSE), + FANMADE("Naturette 1 (English v1.2)", "0a75884e7f010974a230bdf269651117"), + FANMADE("Naturette 1 (English v1.3)", "f15bbf999ac55ebd404aa1eb84f7c1d9"), + FANMADE_L("Naturette 1 (French v1.2)", "d3665622cc41aeb9c7ecf4fa43f20e53", Common::FR_FRA), + FANMADE_F("Naturette 2: Daughter of the Moon (v1.0)", "bdf76a45621c7f56d1c9d40292c6137a", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Naturette 3: Adventure in Treeworld (v1.0a)", "6dbb0e7fc75fec442e6d9e5a06f1530e", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Naturette 4: From a Planet to Another Planet (Not Finished)", "13be8cd9cf35aeff0a39b8757057fbc8", GF_AGIMOUSE), + // FIXME: Actually Naturette 4 has both English and French language support built into it. How to add that information? + FANMADE_F("Naturette 4: From a Planet to Another Planet (2007-10-05)", "8253706b6ef5423a79413b216760297c", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("New AGI Hangman Test", "d69c0e9050ccc29fd662b74d9fc73a15"), + FANMADE("Nick's Quest - In Pursuit of QuakeMovie (v2.1 Gold)", "e29cbf9222551aee40397fabc83eeca0"), + FANMADE_F("Open Mic Night (v0.1)", "70000a2f67aac27d1133d019df70246d", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("Operation: Recon", "0679ce8405411866ccffc8a6743370d0"), + FANMADE("Patrick's Quest (Demo v1.0)", "f254f5b894b98fec5f92acc07fb62841"), + FANMADE("Phantasmagoria", "87d20c1c11aee99a4baad3797b63146b"), + FANMADE("Pharaoh Quest (v0.0)", "51c630899d076cf799e573dadaa2276d"), + FANMADE("Phil's Quest - the Search for Tolbaga", "5e7ca45c360e03164b8358e49900c588"), + FANMADE("Pinkun Maze Quest (v0.1)", "148ff0843af389928b3939f463bfd20d"), + FANMADE("Pirate Quest", "bb612a919ed2b9ea23bbf03ce69fed42"), + FANMADE("Pothead (v0.1)", "d181101385d3a45082f418cd4b3c5b01"), + FANMADE("President's Quest", "4937d0e8ecadb7888faeb347799b0388"), + FANMADE("Prince Quest", "266248d75c3130c8ccc9c9bf2ad30a0d"), + FANMADE("Professor (English) - The Professor is Missing (Mar 17)", "6232de31cc204affdf2e92dfe3dc0e4d"), + FANMADE("Professor (English) - The Professor is Missing (Mar 22)", "b5fcf0ca2f0d1c073be82f01e2170961"), + FANMADE_L("Professor (French) - Le Professeur a Disparu", "7d9f8a4d4610bb9b0b97caa17590c2d3", Common::FR_FRA), + FANMADE("Quest for Glory VI - Hero's Adventure", "d26765c3075064c80d284c5e06e33a7e"), + FANMADE("Quest for Home", "d2895dc1cd3930f2489af0f843b144b3"), + FANMADE("Quest for Ladies (demo v1.1 Apr 1)", "3f6e02f16e1154a0daf296c8895edd97"), + FANMADE("Quest for Ladies (demo v1.1 Apr 6)", "f75e7b6a0769a3fa926eea0854711591"), + FANMADE("Quest for Piracy 1 - Enter the Silver Pirate (v0.15)", "d23f5c2a26f6dc60c686f8a2436ea4a6"), + FANMADE("Quest for a Record Deal", "f4fbd7abf056d2d3204f790da5ac89ab"), + FANMADE("Ralph's Quest (v0.1)", "5cf56378aa01a26ec30f25295f0750ca"), + FANMADE("Residence 44 Quest (Dutch v0.99)", "7c5cc64200660c70240053b33d379d7d"), + FANMADE("Residence 44 Quest (English v0.99)", "fe507851fddc863d540f2bec67cc67fd"), + FANMADE("Residence 44 Quest (English v1.0a)", "f99e3f69dc8c77a45399da9472ef5801"), + FANMADE("SQ2Eye (v0.3)", "2be2519401d38ad9ce8f43b948d093a3"), + // FANMADE("SQ2Eye (v0.4)", "2be2519401d38ad9ce8f43b948d093a3"), + FANMADE("SQ2Eye (v0.41)", "f0e82c55f10eb3542d7cd96c107ae113"), + FANMADE("SQ2Eye (v0.42)", "d7beae55f6328ef8b2da47b1aafea40c"), + FANMADE("SQ2Eye (v0.43)", "2a895f06e45de153bb4b77c982009e06"), + FANMADE("SQ2Eye (v0.44)", "5174fc4b6d8a477ba0ff0575cd64e0aa"), + FANMADE("SQ2Eye (v0.45)", "6e06f8bb7b90ce6f6aabf1a0e620159c"), + FANMADE("SQ2Eye (v0.46)", "bf0ad7a035ff9113951d09d1efe380c4"), + FANMADE("SQ2Eye (v0.47)", "85dc3be1d33ff932c292b74f9037abaa"), + FANMADE("SQ2Eye (v0.48)", "587574252972a5b5c070a647973a9b4a"), + FANMADE("SQ2Eye (v0.481)", "fc9234beb49804ae869696ce5af8ef30"), + FANMADE("SQ2Eye (v0.482)", "3ed84b7b87fa6840f25c15f250a11ffb"), + FANMADE("SQ2Eye (v0.483)", "647c31298d3f9cda641231b893e347c0"), + FANMADE("SQ2Eye (v0.484)", "f2c86fae7b9046d408c62c8c49a4b882"), + FANMADE("SQ2Eye (v0.485)", "af59e36bc28f44545458b68a93e91e67"), + FANMADE("SQ2Eye (v0.486)", "3fd86436e93456770dbdd4593eded70a"), + FANMADE("Save Santa (v1.0)", "4644f6beb5802081772f14be56ae196c"), + FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), + FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), + FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), + FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE), + FANMADE_IF("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", GF_AGIMOUSE|GF_AGIPAL), + FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"), + FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE), + FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), + FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), + FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), + FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"), + FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"), + FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3), + FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), + FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), + FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), + FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), + FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), + FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), + FANMADE("Speeder Bike Challenge (v1.0)", "2deb25bab379285ca955df398d96c1e7"), + FANMADE("Star Commander 1 - The Escape (v1.0)", "a7806f01e6fa14ebc029faa58f263750"), + FANMADE("Star Pilot: Bigger Fish", "8cb26f8e1c045b75c6576c839d4a0172"), + FANMADE_F("Street Quest (Demo)", "cf2aa94a7eb78dce6892c37f03e310d6", GF_AGIPAL), + FANMADE("Tales of the Tiki", "8103c9c87e3964690a14a3d0d83f7ddc"), + FANMADE("Tex McPhilip 1 - Quest For The Papacy", "3c74b9a24b51aa8020ac82bee3132266"), + FANMADE("Tex McPhilip 2 - Road To Divinity (v1.5)", "7387e8df854440bc26620ca0ea43af9a"), + FANMADE("Tex McPhilip 3 - A Destiny of Sin (Demo v0.25)", "992d12031a486ad84e592ff5d7c9d782"), + FANMADE("The 13th Disciple (v1.00)", "887719ad59afce9a41ec057dbb73ad73"), + FANMADE("The Adventures of a Crazed Hermit", "6e3086cbb794d3299a9c5a9792295511"), + FANMADE("The Grateful Dead", "c2146631afacf8cb455ce24f3d2d46e7"), + FANMADE("The Legend of Shay-Larah 1 - The Lost Prince", "04e720c8e30c9cf12db22ea14a24a3dd"), + FANMADE("The Legend of Zelda: The Fungus of Time (Demo v1.00)", "dcaf8166ceb62a3d9b9aea7f3b197c09"), + FANMADE("The Legendary Harry Soupsmith (Demo 1998 Apr 2)", "64c46b0d6fc135c9835afa80980d2831"), + FANMADE("The Legendary Harry Soupsmith (Demo 1998 Aug 19)", "8d06d82970f2c591d880a95476efbcf0"), + FANMADE("The Long Haired Dude: Encounter of the 18-th Kind", "86ea17b9fc2f3e537a7e40863d352c29"), + FANMADE("The Lost Planet (v0.9)", "590dffcbd932a9fbe554be13b769cac0"), + FANMADE("The Lost Planet (v1.0)", "58564df8b6394612dd4b6f5c0fd68d44"), + FANMADE("The New Adventure of Roger Wilco (v1.00)", "e5f0a7cb8d49f66b89114951888ca688"), + FANMADE("The Ruby Cast (v0.02)", "ed138e461bb1516e097007e017ab62df"), + FANMADE("The Shadow Plan", "c02cd10267e721f4e836b1431f504a0a"), + FANMADE("Time Quest (Demo v0.1)", "12e1a6f03ea4b8c5531acd0400b4ed8d"), + FANMADE("Time Quest (Demo v0.2)", "7b710608abc99e0861ac59b967bf3f6d"), + FANMADE_SVP("Time Quest", "90314f473d8317be5cd1f0306f139aea", 300, 0x2440, Common::kPlatformCoCo3), + FANMADE("Tonight The Shrieking Corpses Bleed (Demo v0.11)", "bcc57a7c8d563fa0c333107ae1c0a6e6"), + FANMADE("Tonight The Shrieking Corpses Bleed (v1.01)", "36b38f621b38e8d104aa0807302dc8c9"), + FANMADE("Turks' Quest - Heir to the Planet", "3d19254b737c8b218e5bc4580542b79a"), + FANMADE("URI Quest (v0.173 Feb 27)", "3986eefcf546dafc45f920ae91a697c3"), + FANMADE("URI Quest (v0.173 Jan 29)", "494150940d34130605a4f2e67ee40b12"), + { + // V - The Graphical Adventure + { + "agi-fanmade", + "V - The Graphical Adventure (Demo 2)", + AD_ENTRY1s("vdir", "c71f5c1e008d352ae9040b77fcf79327", 3080), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_USEEXTRAASTITLE, + GUIO_NONE + }, + GID_FANMADE, + GType_V3, + GF_FANMADE, + 0x3149, + }, + FANMADE_SVP("V - The Graphical Adventure", "1646eaade74f137a9041eb427a389969", 768, 0x2440, Common::kPlatformCoCo3), + + FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Jan 1)", "ae95f0c77d9a97b61420fd192348b937"), + FANMADE("Voodoo Girl - Queen of the Darned (v1.2 2002 Mar 29)", "11d0417b7b886f963d0b36789dac4c8f"), + FANMADE("Wizaro (v0.1)", "abeec1eda6eaf8dbc52443ea97ff140c"), + + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } +}; + +/** + * The fallback game descriptor used by the AGI engine's fallbackDetector. + * Contents of this struct are to be overwritten by the fallbackDetector. + */ +static AGIGameDescription g_fallbackDesc = { + { + "", + "", + AD_ENTRY1(0, 0), // This should always be AD_ENTRY1(0, 0) in the fallback descriptor + Common::UNK_LANG, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_FANMADE, + GType_V2, + GF_FANMADE, + 0x2917, +}; + +} // End of namespace Agi -- cgit v1.2.3 From d5c3cda8c5cc06a75b27d7fd7f735fb27e5877e3 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:15:29 +0000 Subject: Moved tinsel detection tables to separate file. svn-id: r49694 --- engines/tinsel/detection.cpp | 544 +----------------------------------- engines/tinsel/detection_tables.h | 567 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 568 insertions(+), 543 deletions(-) create mode 100644 engines/tinsel/detection_tables.h (limited to 'engines') diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index a70b75f136..c46a93fb38 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -75,549 +75,7 @@ static const PlainGameDescriptor tinselGames[] = { {0, 0} }; - -namespace Tinsel { - -using Common::GUIO_NONE; -using Common::GUIO_NOSPEECH; -using Common::GUIO_NOSFX; -using Common::GUIO_NOMUSIC; - -static const TinselGameDescription gameDescriptions[] = { - - // Note: The following is the (hopefully) definitive list of version details: - // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version - // of the Tinsel engine and graphics compression - // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA - // files, and the second used .SCN files. The second also provided some fixes to - // various script bugs and coding errors, but is still considered TINSEL_V1, - // as both game versions work equally well with the newer code. - // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine, - // and as far as we know there aren't any variations of this engine. - - { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php - { - "dw", - "Floppy Demo", - AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192), - //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC - }, - GID_DW1, - 0, - GF_DEMO, - TINSEL_V0, - }, - - { // CD Demo V1 version, with *.gra files - { - "dw", - "CD Demo", - { - {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676}, - {"english.smp", 0, NULL, -1}, - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD, - TINSEL_V1, - }, - - { // Multilingual Floppy V1 with *.gra files. - // Note: It contains no english subtitles. - { - "dw", - "Floppy", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NOSPEECH - }, - GID_DW1, - 0, - GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Floppy V1 version, with *.gra files - { - "dw", - "Floppy", - AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NOSPEECH - }, - GID_DW1, - 0, - GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // CD V1 version, with *.gra files (same as the floppy one, with english.smp) - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Italian CD with english speech and *.gra files. - // Note: It contains only italian subtitles, but inside english.txt - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Multilingual CD with english speech and *.gra files. - // Note: It contains no english subtitles. - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - { - { - "dw", - "CD", - { - {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, - {"english.smp", 0, NULL, -1}, - {"french.txt", 0, NULL, -1}, - {"german.txt", 0, NULL, -1}, - {"italian.txt", 0, NULL, -1}, - {"spanish.txt", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // English CD v2 - { - "dw", - "CD", - { - {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Hebrew CD v2 - { - "dw", - "CD", - { - {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::HE_ISR, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Discworld PSX CD - { - "dw", - "CD", - { - {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPSX, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // multilanguage PSX demo - { - "dw", - "CD demo", - { - {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914}, - {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942}, - {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834}, - {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702}, - {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPSX, - ADGF_DEMO, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V1, - }, - -#if 0 - { // English Saturn CD - { - "dw", - "CD", - { - {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, -#endif - -#if 0 - { // Mac multilanguage CD - { - "dw", - "CD", - { - {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - -#endif - - { // German CD re-release "Neon Edition" - // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT - { - "dw", - "CD", - AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // Russian Discworld 1 - { - "dw", - "CD", - { - {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524}, - {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821}, - {"english.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::RU_RUS, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW1, - 0, - GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, - TINSEL_V1, - }, - - { // European/Australian Discworld 2 release - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_GRB, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // US Discworld 2 release - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"us1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::EN_USA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // French version of Discworld 2 - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"french1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // German Discworld 2 re-release "Neon Edition" - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"german1.smp", 0, NULL, -1}, - {NULL, 0, NULL, 0} - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // Italian/Spanish Discworld 2 - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495}, - {NULL, 0, NULL, 0} - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - { - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323}, - {NULL, 0, NULL, 0} - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { // Russian Discworld 2 release by Fargus - { - "dw2", - "CD", - { - {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, - {"english1.smp", 0, NULL, -1}, - {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, - {NULL, 0, NULL, 0} - }, - Common::RU_RUS, - Common::kPlatformPC, - ADGF_NO_FLAGS, - GUIO_NONE - }, - GID_DW2, - 0, - GF_CD | GF_SCNFILES, - TINSEL_V2, - }, - - { AD_TABLE_END_MARKER, 0, 0, 0, 0 } -}; - -} // End of namespace Tinsel +#include "tinsel/detection_tables.h" static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure diff --git a/engines/tinsel/detection_tables.h b/engines/tinsel/detection_tables.h new file mode 100644 index 0000000000..b467cc613e --- /dev/null +++ b/engines/tinsel/detection_tables.h @@ -0,0 +1,567 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +namespace Tinsel { + +using Common::GUIO_NONE; +using Common::GUIO_NOSPEECH; +using Common::GUIO_NOSFX; +using Common::GUIO_NOMUSIC; + +static const TinselGameDescription gameDescriptions[] = { + + // Note: The following is the (hopefully) definitive list of version details: + // TINSEL_V0: Used only by the Discworld 1 demo - this used a more primitive version + // of the Tinsel engine and graphics compression + // TINSEL_V1: There were two versions of the Discworld 1 game - the first used .GRA + // files, and the second used .SCN files. The second also provided some fixes to + // various script bugs and coding errors, but is still considered TINSEL_V1, + // as both game versions work equally well with the newer code. + // TINSEL_V2: The Discworld 2 game used this updated version of the Tinsel 1 engine, + // and as far as we know there aren't any variations of this engine. + + { // Floppy Demo V0 from http://www.adventure-treff.de/specials/dl_demos.php + { + "dw", + "Floppy Demo", + AD_ENTRY1s("dw.gra", "ce1b57761ba705221bcf70955b827b97", 441192), + //AD_ENTRY1s("dw.scn", "ccd72f02183d0e96b6e7d8df9492cda8", 23308), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + GUIO_NOSPEECH | GUIO_NOSFX | GUIO_NOMUSIC + }, + GID_DW1, + 0, + GF_DEMO, + TINSEL_V0, + }, + + { // CD Demo V1 version, with *.gra files + { + "dw", + "CD Demo", + { + {"dw.gra", 0, "ef5a2518c9e205f786f5a4526396e661", 781676}, + {"english.smp", 0, NULL, -1}, + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD, + TINSEL_V1, + }, + + { // Multilingual Floppy V1 with *.gra files. + // Note: It contains no english subtitles. + { + "dw", + "Floppy", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NOSPEECH + }, + GID_DW1, + 0, + GF_FLOPPY | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Floppy V1 version, with *.gra files + { + "dw", + "Floppy", + AD_ENTRY1s("dw.gra", "c8808ccd988d603dd35dff42013ae7fd", 781656), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSPEECH + }, + GID_DW1, + 0, + GF_FLOPPY | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // CD V1 version, with *.gra files (same as the floppy one, with english.smp) + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Italian CD with english speech and *.gra files. + // Note: It contains only italian subtitles, but inside english.txt + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 237774}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Multilingual CD with english speech and *.gra files. + // Note: It contains no english subtitles. + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + { + { + "dw", + "CD", + { + {"dw.gra", 0, "c8808ccd988d603dd35dff42013ae7fd", 781656}, + {"english.smp", 0, NULL, -1}, + {"french.txt", 0, NULL, -1}, + {"german.txt", 0, NULL, -1}, + {"italian.txt", 0, NULL, -1}, + {"spanish.txt", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_USE_4FLAGS | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // English CD v2 + { + "dw", + "CD", + { + {"dw.scn", 0, "70955425870c7720d6eebed903b2ef41", 776188}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Hebrew CD v2 + { + "dw", + "CD", + { + {"dw.scn", 0, "759d1374b4f02af6d52fc07c96679936", 770780}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::HE_ISR, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Discworld PSX CD + { + "dw", + "CD", + { + {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPSX, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // multilanguage PSX demo + { + "dw", + "CD demo", + { + {"french.txt", 0, "e7020d35f58d0d187052ac406d86cc87", 273914}, + {"german.txt", 0, "52f0a01e0ff0d340b02a36fd5109d705", 263942}, + {"italian.txt", 0, "15f0703f85477d7fab4280bf938b61c1", 239834}, + {"spanish.txt", 0, "c324170c3f1922c605c5cc09ba265aa5", 236702}, + {"english.txt", 0, "7526cfc3a64e00f223795de476b4e2c9", 230326}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPSX, + ADGF_DEMO, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V1, + }, + +#if 0 + { // English Saturn CD + { + "dw", + "CD", + { + {"dw.scn", 0, "6803f293c88758057cc685b9437f7637", 382248}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, +#endif + +#if 0 + { // Mac multilanguage CD + { + "dw", + "CD", + { + {"dw.scn", 0, "cfc40a8d5d476a1c9d3abf826fa46f8c", 1265532}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + +#endif + + { // German CD re-release "Neon Edition" + // Note: This release has ENGLISH.TXT (with german content) instead of GERMAN.TXT + { + "dw", + "CD", + AD_ENTRY1s("dw.scn", "6182c7986eaec893c62fb6ea13a9f225", 774556), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // Russian Discworld 1 + { + "dw", + "CD", + { + {"dw.scn", 0, "133041bde59d05c1bf084fd6f1bdce4b", 776524}, + {"english.txt", 0, "f73dcbd7b136b37c2adf7c9448ea336d", 231821}, + {"english.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::RU_RUS, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW1, + 0, + GF_CD | GF_SCNFILES | GF_ENHANCED_AUDIO_SUPPORT, + TINSEL_V1, + }, + + { // European/Australian Discworld 2 release + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_GRB, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // US Discworld 2 release + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"us1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::EN_USA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // French version of Discworld 2 + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"french1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // German Discworld 2 re-release "Neon Edition" + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"german1.smp", 0, NULL, -1}, + {NULL, 0, NULL, 0} + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // Italian/Spanish Discworld 2 + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"italian1.txt", 0, "d443249f8b55489b5888c227b9096f4e", 246495}, + {NULL, 0, NULL, 0} + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + { + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"spanish1.txt", 0, "bc6e147c5f542db228ac577357e4d897", 230323}, + {NULL, 0, NULL, 0} + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { // Russian Discworld 2 release by Fargus + { + "dw2", + "CD", + { + {"dw2.scn", 0, "c6d15ce9720a9d8fef06e6582dcf3f34", 103593}, + {"english1.smp", 0, NULL, -1}, + {"english1.txt", 0, "b522e19d7b2cd7b85e50e36fe48e36a9", 274444}, + {NULL, 0, NULL, 0} + }, + Common::RU_RUS, + Common::kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NONE + }, + GID_DW2, + 0, + GF_CD | GF_SCNFILES, + TINSEL_V2, + }, + + { AD_TABLE_END_MARKER, 0, 0, 0, 0 } +}; + +} // End of namespace Tinsel -- cgit v1.2.3 From d137b4610ab6c2d1577d6656bf8c193d2e4cf8a3 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:15:51 +0000 Subject: Split out detection code in Kyra engine. svn-id: r49695 --- engines/kyra/detection.cpp | 1169 +------------------------------------- engines/kyra/detection_tables.h | 1192 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 1193 insertions(+), 1168 deletions(-) create mode 100644 engines/kyra/detection_tables.h (limited to 'engines') diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 90a107099f..4ed314934d 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -41,1172 +41,7 @@ struct KYRAGameDescription { Kyra::GameFlags flags; }; -namespace { - -#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } -#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } - -#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1) -#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1) -#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1) - -#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2) -#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2) - -#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3) -#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3) -#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3) - -#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL) -#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL) -#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) -#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) - -const KYRAGameDescription adGameDescs[] = { - /* disable these targets until they get supported - { - { - "kyra1", - 0, - AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_CMP_FLAGS - }, - - { - { - "kyra1", - 0, - AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_CMP_FLAGS - }, - */ - - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from Arne.F - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from VooD - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // floppy 1.8 from clemmy - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), - Common::ES_ESP, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - { // from gourry - { - "kyra1", - "Extracted", - AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, - { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_AMIGA_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, - { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::DE_DEU, - Common::kPlatformAmiga, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_AMIGA_FLAGS - }, - - { - { - "kyra1", - 0, - { - { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_FLOPPY_FLAGS - }, - - { // FM-TOWNS version - { - "kyra1", - 0, - { - { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, - { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_FLAGS - }, - { - { - "kyra1", - 0, - { - { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, - { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::JA_JPN, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_SJIS_FLAGS - }, - - // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, - // thus we will mark it as non CD game. - { - { - "kyra1", - "", - { - { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, - { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA1_TOWNS_SJIS_FLAGS - }, - - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat" - { - "kyra1", - "CD", - AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::DE_DEU, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - { - { - "kyra1", - "CD", - { - { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 }, - { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, - { NULL, 0, NULL, 0 } - }, - Common::FR_FRA, - Common::kPlatformMacintosh, - ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_CD_FLAGS - }, - - { - { - "kyra1", - "Demo", - AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NOSPEECH - }, - KYRA1_DEMO_FLAGS - }, - - { // Special Kyrandia 1 CD demo - { - "kyra1", - "Demo/CD", - AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO | ADGF_CD, - Common::GUIO_NONE - }, - KYRA1_DEMO_CD_FLAGS - }, - - { // Floppy version - { - "kyra2", - 0, - AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_CMP_FLAGS - }, - - { // Floppy version - { - "kyra2", - 0, - AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_CMP_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // Floppy version extracted - { - "kyra2", - "Extracted", - AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_FLOPPY_FLAGS - }, - - { // CD version - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FLAGS - }, - - // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" - { // CD version - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { - { - "kyra2", - "CD", - AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Interactive Demo - { - "kyra2", - "CD/Demo", - AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_CD_DEMO_FLAGS - }, - - { // Non-Interactive Demos - { - "kyra2", - "Demo", - AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"), - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NONE - }, - KYRA2_DEMO_FLAGS - }, - - { // FM-TOWNS - { - "kyra2", - 0, - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::EN_ANY, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_FLAGS - }, - { - { - "kyra2", - 0, - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::JA_JPN, - Common::kPlatformFMTowns, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_SJIS_FLAGS - }, - { // PC-9821 - { - "kyra2", - "CD", - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::EN_ANY, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_FLAGS - }, - { - { - "kyra2", - "CD", - AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_CD, - Common::GUIO_NOSPEECH - }, - KYRA2_TOWNS_SJIS_FLAGS - }, - - // Kyra3 - - // non installed version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "WESTWOOD.001", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FLAGS - }, - - // installed version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - - // Mac version - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformMacintosh, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_INS_FLAGS - }, - - // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::ES_ESP, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) - }, - - // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - { - { - "kyra3", - 0, - { - { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, - { "AUD.PAK", 0, 0, -1 }, - { 0, 0, 0, 0 } - }, - Common::IT_ITA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE, - Common::GUIO_NOMIDI - }, - KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) - }, - -#ifdef ENABLE_LOL - // Lands of Lore CD - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - "CD", - { - { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, - { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, - { 0, 0, 0, 0 } - }, - Common::FR_FRA, - Common::kPlatformPC, - ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE - }, - LOL_CD_FLAGS - }, - - { - { - "lol", - 0, - { - { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_CMP_FLAGS - }, - - { - { - "lol", - 0, - { - { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_CMP_FLAGS - }, - - { - { - "lol", - "Extracted", - { - { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 }, - { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_FLAGS - }, - - { - { - "lol", - "Extracted", - { - { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 }, - { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 }, - { 0, 0, 0, 0 } - }, - Common::DE_DEU, - Common::kPlatformPC, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_FLOPPY_FLAGS - }, - - { - { - "lol", - 0, - { - { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 }, - { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 }, - { 0, 0, 0, 0 } - }, - Common::JA_JPN, - Common::kPlatformPC98, - ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH - }, - LOL_PC98_SJIS_FLAGS - }, - - { - { - "lol", - "Demo", - { - { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 }, - { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NONE - }, - LOL_DEMO_FLAGS - }, - - { - { - "lol", - "Demo", - { - { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 }, - { 0, 0, 0, 0 } - }, - Common::EN_ANY, - Common::kPlatformPC, - ADGF_DEMO, - Common::GUIO_NOSPEECH - }, - LOL_KYRA2_DEMO_FLAGS - }, -#endif // ENABLE_LOL - - { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) } -}; - -const PlainGameDescriptor gameList[] = { - { "kyra1", "The Legend of Kyrandia" }, - { "kyra2", "The Legend of Kyrandia: The Hand of Fate" }, - { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" }, -#ifdef ENABLE_LOL - { "lol", "Lands of Lore: The Throne of Chaos" }, -#endif // ENABLE_LOL - { 0, 0 } -}; +#include "kyra/detection_tables.h" const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure @@ -1231,8 +66,6 @@ const ADParams detectionParams = { 1 }; -} // End of anonymous namespace - class KyraMetaEngine : public AdvancedMetaEngine { public: KyraMetaEngine() : AdvancedMetaEngine(detectionParams) {} diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h new file mode 100644 index 0000000000..9f40cc3b1f --- /dev/null +++ b/engines/kyra/detection_tables.h @@ -0,0 +1,1192 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + */ + +namespace { + +#define FLAGS(x, y, z, a, b, c, d, id) { Common::UNK_LANG, Common::UNK_LANG, Common::UNK_LANG, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } +#define FLAGS_FAN(fanLang, repLang, x, y, z, a, b, c, d, id) { Common::UNK_LANG, fanLang, repLang, Common::kPlatformUnknown, x, y, z, a, b, c, d, id } + +#define KYRA1_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA1) +#define KYRA1_AMIGA_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_FLAGS FLAGS(false, true, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_TOWNS_SJIS_FLAGS FLAGS(false, true, false, true, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_CD_FLAGS FLAGS(false, true, true, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA1) +#define KYRA1_DEMO_CD_FLAGS FLAGS(true, true, true, false, false, false, false, Kyra::GI_KYRA1) + +#define KYRA2_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_KYRA2) +#define KYRA2_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_CD_DEMO_FLAGS FLAGS(true, false, true, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define KYRA2_TOWNS_SJIS_FLAGS FLAGS(false, false, false, true, false, false, false, Kyra::GI_KYRA2) + +#define KYRA3_CD_FLAGS FLAGS(false, false, true, false, false, true, true, Kyra::GI_KYRA3) +#define KYRA3_CD_INS_FLAGS FLAGS(false, false, true, false, false, true, false, Kyra::GI_KYRA3) +#define KYRA3_CD_FAN_FLAGS(x, y) FLAGS_FAN(x, y, false, false, true, false, false, true, false, Kyra::GI_KYRA3) + +#define LOL_CD_FLAGS FLAGS(false, false, true, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_FLOPPY_CMP_FLAGS FLAGS(false, false, false, false, false, false, true, Kyra::GI_LOL) +#define LOL_PC98_SJIS_FLAGS FLAGS(false, false, false, true, true, false, false, Kyra::GI_LOL) +#define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) +#define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) + +const KYRAGameDescription adGameDescs[] = { + /* disable these targets until they get supported + { + { + "kyra1", + 0, + AD_ENTRY1("DISK1.EXE", "c8641d0414d6c966d0a3dad79db07bf4"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + + { + { + "kyra1", + 0, + AD_ENTRY1("DISK1.EXE", "5d5cee4c3d0b68d586788b74243d254a"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_CMP_FLAGS + }, + */ + + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "3c244298395520bb62b5edfe41688879"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "796e44863dd22fa635b042df1bf16673"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "abf8eb360e79a6c2a837751fbd4d3d24"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "6018e1dfeaca7fe83f8d0b00eb0dd049"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { // from Arne.F + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "f0b276781f47c130f423ec9679fe9ed9"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { // from VooD + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "8909b41596913b3f5deaf3c9f1017b01"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { // floppy 1.8 from clemmy + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "747861d2a9c643c59fdab570df5b9093"), + Common::ES_ESP, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + { // from gourry + { + "kyra1", + "Extracted", + AD_ENTRY1("GEMCUT.EMC", "ef08c8c237ee1473fd52578303fc36df"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, + { "GEMCUT.EMC", 0, "2a3f44e179f1e9f7643e90083c747571", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_AMIGA_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.PAK", 0, "2bd1da653eaefd691e050e4a9eb68a64", -1 }, + { "GEMCUT.EMC", 0, "74f99e9ed99abf8d0429826d78485a2a", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::DE_DEU, + Common::kPlatformAmiga, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_AMIGA_FLAGS + }, + + { + { + "kyra1", + 0, + { + { "GEMCUT.EMC", 0, "796e44863dd22fa635b042df1bf16673", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_FLOPPY_FLAGS + }, + + { // FM-TOWNS version + { + "kyra1", + 0, + { + { "EMC.PAK", 0, "a046bb0b422061aab8e4c4689400343a", -1 }, + { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_TOWNS_FLAGS + }, + { + { + "kyra1", + 0, + { + { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, + { "TWMUSIC.PAK", 0, "e53bca3a3e3fb49107d59463ec387a59", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::JA_JPN, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_TOWNS_SJIS_FLAGS + }, + + // PC-9801 floppy + CD / PC-9821 floppy version are all using the same data files, + // thus we will mark it as non CD game. + { + { + "kyra1", + "", + { + { "JMC.PAK", 0, "9c5707a2a478e8167e44283246612d2c", -1 }, + { "MUSIC98.PAK", 0, "02fc212f799331b769b274e33d87b37f", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA1_TOWNS_SJIS_FLAGS + }, + + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "fac399fe62f98671e56a005c5e94e39f"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "230f54e6afc007ab4117159181a1c722"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "b037c41768b652a040360ffa3556fd2a"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + + { // italian fan translation see fr#1727941 "KYRA: add Italian CD Version to kyra.dat" + { + "kyra1", + "CD", + AD_ENTRY1("GEMCUT.PAK", "d8327fc4b7a72b23c900fa13aef4093a"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + + { // Kyra 1 Mac CD as mentioned in fr #2766454 "KYRA1: Add support for Macintosh CD" by nnooiissee + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "d3d4b281cd357230aabcec46843d04bd", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "4a0cb720e824295bcbccbd1407652110", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + { + { + "kyra1", + "CD", + { + { "GEMCUT.PAK", 0, "b71ee090aa12e80ed2ba068826d92bed", -1 }, + { "BEAD.CPS", 0, "3038466f65b7751451844707187aa401", -1 }, + { NULL, 0, NULL, 0 } + }, + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_CD_FLAGS + }, + + { + { + "kyra1", + "Demo", + AD_ENTRY1("DEMO1.WSA", "fb722947d94897512b13b50cc84fd648"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_NOSPEECH + }, + KYRA1_DEMO_FLAGS + }, + + { // Special Kyrandia 1 CD demo + { + "kyra1", + "Demo/CD", + AD_ENTRY1("INTRO.VRM", "e3045fb69b8c29db84b8fda3ccbdac54"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO | ADGF_CD, + Common::GUIO_NONE + }, + KYRA1_DEMO_CD_FLAGS + }, + + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "3f52dda68c4f7696c8309038be9f4151"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // Floppy version + { + "kyra2", + 0, + AD_ENTRY1("WESTWOOD.001", "d787b9559afddfe058b84c0b3a787224"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_CMP_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "1ba18be685ad8e5a0ab5d46a0ce4d345"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "262fb69dd8e52e596c7aefc6456f7c1b"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "f7de11506b4c8fdf64bc763206c3e4e7"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_FLAGS + }, + + { // Floppy version extracted + { + "kyra2", + "Extracted", + AD_ENTRY1("FATE.PAK", "e0a70c31b022cb4bb3061890020fc27c"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_FLOPPY_FLAGS + }, + + { // CD version + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "28cbad1c5bf06b2d3825ae57d760d032"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FLAGS + }, + + // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" + { // CD version + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "30487f3b8d7790c7857f4769ff2dd125"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { + { + "kyra2", + "CD", + AD_ENTRY1("FATE.PAK", "39772ff82e42c4c520050518deb82e64"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Interactive Demo + { + "kyra2", + "CD/Demo", + AD_ENTRY1("THANKS.CPS", "b1a78d990b120bb2234b7094f74e30a5"), + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, + Common::GUIO_NONE + }, + KYRA2_CD_DEMO_FLAGS + }, + + { // Non-Interactive Demos + { + "kyra2", + "Demo", + AD_ENTRY1("VOC.PAK", "ecb3561b63749158172bf21528cf5f45"), + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_NONE + }, + KYRA2_DEMO_FLAGS + }, + + { // FM-TOWNS + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::EN_ANY, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_TOWNS_FLAGS + }, + { + { + "kyra2", + 0, + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::JA_JPN, + Common::kPlatformFMTowns, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + KYRA2_TOWNS_SJIS_FLAGS + }, + { // PC-9821 + { + "kyra2", + "CD", + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::EN_ANY, + Common::kPlatformPC98, + ADGF_CD, + Common::GUIO_NOSPEECH + }, + KYRA2_TOWNS_FLAGS + }, + { + { + "kyra2", + "CD", + AD_ENTRY1("WSCORE.PAK", "c44de1302b67f27d4707409987b7a685"), + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_CD, + Common::GUIO_NOSPEECH + }, + KYRA2_TOWNS_SJIS_FLAGS + }, + + // Kyra3 + + // non installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "WESTWOOD.001", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FLAGS + }, + + // installed version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + + // Mac version + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "3833ff312757b8e6147f464cca0a6587", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformMacintosh, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_INS_FLAGS + }, + + // Spanish fan translation, see fr#1994040 "KYRA3: Add support for Spanish fan translation" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::ES_ESP, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "9aaca21d2a205ca02ec53132f2911794", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::ES_ESP, Common::EN_ANY) + }, + + // Italian fan translation, see fr#2003504 "KYRA: add support for Italian version of Kyrandia 2&3" + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + { + { + "kyra3", + 0, + { + { "ONETIME.PAK", 0, "ee2d4d056a5de5333a3c6bda055b3cb4", -1 }, + { "AUD.PAK", 0, 0, -1 }, + { 0, 0, 0, 0 } + }, + Common::IT_ITA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE, + Common::GUIO_NOMIDI + }, + KYRA3_CD_FAN_FLAGS(Common::IT_ITA, Common::FR_FRA) + }, + +#ifdef ENABLE_LOL + // Lands of Lore CD + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "05a4f588fb81dc9c0ef1f2ec20d89e24", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + "CD", + { + { "GENERAL.PAK", 0, "9e4bab499b7ea9337b91ac29fcba6d13", -1 }, + { "L01.PAK", 0, "759a0ac26808d77ea968bd392355ba1d", -1 }, + { 0, 0, 0, 0 } + }, + Common::FR_FRA, + Common::kPlatformPC, + ADGF_DROPLANGUAGE | ADGF_CD, + Common::GUIO_NONE + }, + LOL_CD_FLAGS + }, + + { + { + "lol", + 0, + { + { "WESTWOOD.1", 0, "c656aa9a2b4032d341e3dc8e3525b917", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + LOL_FLOPPY_CMP_FLAGS + }, + + { + { + "lol", + 0, + { + { "WESTWOOD.1", 0, "3c61cb7de5b2ec452f5851f5075207ee", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + LOL_FLOPPY_CMP_FLAGS + }, + + { + { + "lol", + "Extracted", + { + { "GENERAL.PAK", 0, "2aaa30e120c08af87196820e9dd4bf73", -1 }, + { "CHAPTER7.PAK", 0, "eb92bf7ebb4e890add1233a6b0c810ff", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + LOL_FLOPPY_FLAGS + }, + + { + { + "lol", + "Extracted", + { + { "GENERAL.PAK", 0, "996e66e81054d36249907a1d8158da3d", -1 }, + { "CHAPTER7.PAK", 0, "cabee57f00d6d84b65a732b6868a4959", -1 }, + { 0, 0, 0, 0 } + }, + Common::DE_DEU, + Common::kPlatformPC, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + LOL_FLOPPY_FLAGS + }, + + { + { + "lol", + 0, + { + { "GENERAL.PAK", 0, "3fe6539b9b09084c0984eaf7170464e9", -1 }, + { "MUS.PAK", 0, "008dc69d8cbcdb6bae30e270fab26e76", -1 }, + { 0, 0, 0, 0 } + }, + Common::JA_JPN, + Common::kPlatformPC98, + ADGF_NO_FLAGS, + Common::GUIO_NOSPEECH + }, + LOL_PC98_SJIS_FLAGS + }, + + { + { + "lol", + "Demo", + { + { "INTRO.PAK", 0, "4bc22a3b57f19a49212c5de58ab014d6", -1 }, + { "INTROVOC.PAK", 0, "7e578e4f1da31c1f294e14a8e8f3cc44", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_NONE + }, + LOL_DEMO_FLAGS + }, + + { + { + "lol", + "Demo", + { + { "GENERAL.PAK", 0, "e94863d86c4597a2d581d05481c152ba", -1 }, + { 0, 0, 0, 0 } + }, + Common::EN_ANY, + Common::kPlatformPC, + ADGF_DEMO, + Common::GUIO_NOSPEECH + }, + LOL_KYRA2_DEMO_FLAGS + }, +#endif // ENABLE_LOL + + { AD_TABLE_END_MARKER, FLAGS(0, 0, 0, 0, 0, 0, 0, 0) } +}; + +const PlainGameDescriptor gameList[] = { + { "kyra1", "The Legend of Kyrandia" }, + { "kyra2", "The Legend of Kyrandia: The Hand of Fate" }, + { "kyra3", "The Legend of Kyrandia: Malcolm's Revenge" }, +#ifdef ENABLE_LOL + { "lol", "Lands of Lore: The Throne of Chaos" }, +#endif // ENABLE_LOL + { 0, 0 } +}; + +} // End of anonymous namespace -- cgit v1.2.3 From 723cb6c0f0a638cc9d4f07c0fccf7bdf0197a6ac Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:16:13 +0000 Subject: SAGA: Moved more code under ENABLE_IHNM svn-id: r49696 --- engines/saga/interface.cpp | 8 ++++++++ engines/saga/scene.cpp | 4 ++++ engines/saga/sfuncs.cpp | 12 ------------ engines/saga/sfuncs_ihnm.cpp | 12 ++++++++++++ 4 files changed, 24 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index c0d3cee465..70e6aa0c6b 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -544,8 +544,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelCutaway: if (keystate.keycode == Common::KEYCODE_ESCAPE) { @@ -555,8 +557,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_INHM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelVideo: if (keystate.keycode == Common::KEYCODE_ESCAPE) { @@ -570,8 +574,10 @@ bool Interface::processAscii(Common::KeyState keystate) { return true; } +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart()) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; case kPanelOption: // TODO: check input dialog keys @@ -1866,8 +1872,10 @@ void Interface::update(const Point& mousePoint, int updateFlag) { break; case kPanelNull: +#ifdef ENABLE_IHNM if (_vm->_scene->isNonInteractiveIHNMDemoPart() && (updateFlag & UPDATE_MOUSECLICK)) _vm->_scene->showIHNMDemoSpecialScreen(); +#endif break; } diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 40ee1fb720..1b2a600729 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1425,6 +1425,8 @@ void Scene::clearPlacard() { q_event = _vm->_events->chain(q_event, &event); } +#ifdef ENABLE_IHNM + void Scene::showPsychicProfile(const char *text) { int textHeight; static PalEntry cur_pal[PAL_ENTRIES]; @@ -1531,4 +1533,6 @@ void Scene::showIHNMDemoSpecialScreen() { _vm->_scene->changeScene(150, 0, kTransitionFade); } +#endif // IHNM + } // End of namespace Saga diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index f98a80acd8..a924383ba3 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -1153,18 +1153,6 @@ void Script::sfPlacardOff(SCRIPTFUNC_PARAMS) { _vm->_scene->clearPlacard(); } -void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) { - thread->wait(kWaitTypePlacard); - - _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop())); -} - -void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) { - // This is called a while after the psychic profile is - // opened, to close it automatically - _vm->_scene->clearPsychicProfile(); -} - // Script function #50 (0x32) void Script::sfSetProtagState(SCRIPTFUNC_PARAMS) { _vm->_actor->setProtagState(thread->pop()); diff --git a/engines/saga/sfuncs_ihnm.cpp b/engines/saga/sfuncs_ihnm.cpp index fe586b54ae..b98c1cb852 100644 --- a/engines/saga/sfuncs_ihnm.cpp +++ b/engines/saga/sfuncs_ihnm.cpp @@ -440,6 +440,18 @@ void Script::sfDisableAbortSpeeches(SCRIPTFUNC_PARAMS) { _vm->_interface->disableAbortSpeeches(thread->pop() != 0); } +void Script::sfPsychicProfile(SCRIPTFUNC_PARAMS) { + thread->wait(kWaitTypePlacard); + + _vm->_scene->showPsychicProfile(thread->_strings->getString(thread->pop())); +} + +void Script::sfPsychicProfileOff(SCRIPTFUNC_PARAMS) { + // This is called a while after the psychic profile is + // opened, to close it automatically + _vm->_scene->clearPsychicProfile(); +} + } // End of namespace Saga #endif -- cgit v1.2.3 From 5d72a614ec75b875e950ecd62222bac3008945bc Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:16:32 +0000 Subject: SAGA: Add more thread-related output. svn-id: r49697 --- engines/saga/script.h | 3 +++ engines/saga/sthread.cpp | 8 ++++++++ 2 files changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/saga/script.h b/engines/saga/script.h index f31af7b2ea..21afeb5c44 100644 --- a/engines/saga/script.h +++ b/engines/saga/script.h @@ -246,16 +246,19 @@ public: } void waitWalk(void *threadObj) { + debug(3, "waitWalk()"); wait(kWaitTypeWalk); _threadObj = threadObj; } void waitDelay(int sleepTime) { + debug(3, "waitDelay(%d)", sleepTime); wait(kWaitTypeDelay); _sleepTime = sleepTime; } void waitFrames(int frames) { + debug(3, "waitFrames(%d)", frames); wait(kWaitTypeWaitFrames); _frameWait = frames; } diff --git a/engines/saga/sthread.cpp b/engines/saga/sthread.cpp index c133f8de88..be674e5acd 100644 --- a/engines/saga/sthread.cpp +++ b/engines/saga/sthread.cpp @@ -58,6 +58,8 @@ ScriptThread &Script::createThread(uint16 scriptModuleNumber, uint16 scriptEntry _threadList.push_front(newThread); + debug(3, "createThread(). Total threads: %d", _threadList.size()); + ScriptThread &tmp = *_threadList.begin(); tmp._stackBuf = (int16 *)malloc(ScriptThread::THREAD_STACK_SIZE * sizeof(int16)); tmp._stackTopIndex = ScriptThread::THREAD_STACK_SIZE - 2; @@ -78,6 +80,8 @@ void Script::wakeUpActorThread(int waitType, void *threadObj) { void Script::wakeUpThreads(int waitType) { ScriptThreadList::iterator threadIterator; + debug(3, "wakeUpThreads(%d)", waitType); + for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { ScriptThread &thread = *threadIterator; if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { @@ -89,6 +93,8 @@ void Script::wakeUpThreads(int waitType) { void Script::wakeUpThreadsDelayed(int waitType, int sleepTime) { ScriptThreadList::iterator threadIterator; + debug(3, "wakeUpThreads(%d, %d)", waitType, sleepTime); + for (threadIterator = _threadList.begin(); threadIterator != _threadList.end(); ++threadIterator) { ScriptThread &thread = *threadIterator; if ((thread._flags & kTFlagWaiting) && (thread._waitType == waitType)) { @@ -169,6 +175,8 @@ void Script::executeThreads(uint msec) { void Script::abortAllThreads() { ScriptThreadList::iterator threadIterator; + debug(3, "abortAllThreads()"); + threadIterator = _threadList.begin(); while (threadIterator != _threadList.end()) { -- cgit v1.2.3 From 7746321ed62d80c918a3687b595405e07e80e2aa Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:16:53 +0000 Subject: SAGA: Fix bug #1970191. Bug #1970191: "IHNM: Psychic Profile problem". Still there is a slight artefact. When the profile has 2 pages and is skipped, there are two fade-ins in a row. It could be checked by analysing event queue. svn-id: r49698 --- engines/saga/interface.cpp | 1 + engines/saga/scene.cpp | 2 ++ 2 files changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/saga/interface.cpp b/engines/saga/interface.cpp index 70e6aa0c6b..c4b4688785 100644 --- a/engines/saga/interface.cpp +++ b/engines/saga/interface.cpp @@ -1861,6 +1861,7 @@ void Interface::update(const Point& mousePoint, int updateFlag) { if (updateFlag & UPDATE_MOUSECLICK) { if (!_vm->isIHNMDemo()) { _vm->_scene->clearPsychicProfile(); + _vm->_script->wakeUpThreads(kWaitTypeDelay); } else { setMode(kPanelConverse); _vm->_scene->_textList.clear(); diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 1b2a600729..8cb632ae91 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1442,6 +1442,8 @@ void Scene::showPsychicProfile(const char *text) { _vm->_interface->setMode(kPanelPlacard); _vm->_gfx->savePalette(); + _vm->_events->clearList(); + event.type = kEvTOneshot; event.code = kCursorEvent; event.op = kEventHide; -- cgit v1.2.3 From d577d863ce4cee58b973e3a1cb461ad339e91c61 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:17:18 +0000 Subject: CINE: Fix bug #2812694. Bug #2812694: "CINE: Operation Stealth german crash". Our code assumed that there exists only 256-color version which is not the case for German version. Added code to store background format. Old savegames are broken and could not be fixed. Bumped savefile version. svn-id: r49699 --- engines/cine/gfx.cpp | 22 +++++++++++++++------- engines/cine/gfx.h | 4 ++-- engines/cine/saveload.cpp | 4 ++-- engines/cine/saveload.h | 2 +- 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index a4220e6e35..aa0330df84 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -772,7 +772,7 @@ const char *FWRenderer::getBgName(uint idx) const { * Restore active and backup palette from save * @param fHandle Savefile open for reading */ -void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle) { +void FWRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) { byte buf[kLowPalNumBytes]; // Load the active 16 color palette from file @@ -819,9 +819,8 @@ void FWRenderer::savePalette(Common::OutSaveFile &fHandle) { void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { byte buf[kHighPalNumBytes]; - // Make sure the active palette has the correct format and color count - assert(_activePal.colorFormat() == kHighPalFormat); - assert(_activePal.colorCount() == kHighPalNumColors); + // We can have 16 color palette in many cases + fHandle.writeUint16LE(_activePal.colorCount()); // Write the active 256 color palette. _activePal.save(buf, sizeof(buf), CINE_LITTLE_ENDIAN); @@ -836,12 +835,21 @@ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { * Restore active and backup palette from save * @param fHandle Savefile open for reading */ -void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle) { +void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) { byte buf[kHighPalNumBytes]; + uint colorCount; + + if (version > 0) + colorCount = fHandle.readUint16LE(); - // Load the active 256 color palette from file fHandle.read(buf, kHighPalNumBytes); - _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + + if (colorCount == kHighPalNumBytes || version == 0) { + // Load the active 256 color palette from file + _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); + } else { + _activePal.load(buf, sizeof(buf), kLowPalFormat, kLowPalNumColors, CINE_LITTLE_ENDIAN); + } // Jump over the backup 256 color palette. // FIXME: Load the backup 256 color palette and use it properly. diff --git a/engines/cine/gfx.h b/engines/cine/gfx.h index 56ba6885f4..da7e3dd572 100644 --- a/engines/cine/gfx.h +++ b/engines/cine/gfx.h @@ -197,7 +197,7 @@ public: virtual void refreshPalette(); virtual void reloadPalette(); - virtual void restorePalette(Common::SeekableReadStream &fHandle); + virtual void restorePalette(Common::SeekableReadStream &fHandle, int version); virtual void savePalette(Common::OutSaveFile &fHandle); virtual void rotatePalette(int a, int b, int c); virtual void transformPalette(int first, int last, int r, int g, int b); @@ -257,7 +257,7 @@ public: const char *getBgName(uint idx = 0) const; void reloadPalette(); - void restorePalette(Common::SeekableReadStream &fHandle); + void restorePalette(Common::SeekableReadStream &fHandle, int version); void savePalette(Common::OutSaveFile &fHandle); void transformPalette(int first, int last, int r, int g, int b); diff --git a/engines/cine/saveload.cpp b/engines/cine/saveload.cpp index c76bed3f8e..b5adebcd0b 100644 --- a/engines/cine/saveload.cpp +++ b/engines/cine/saveload.cpp @@ -566,7 +566,7 @@ bool CineEngine::loadTempSaveOS(Common::SeekableReadStream &in) { } loadObjectTable(in); - renderer->restorePalette(in); + renderer->restorePalette(in, hdr.version); globalVars.load(in, NUM_MAX_VAR); loadZoneData(in); loadCommandVariables(in); @@ -698,7 +698,7 @@ bool CineEngine::loadPlainSaveFW(Common::SeekableReadStream &in, CineSaveGameFor loadObjectTable(in); // At 0x2043 (i.e. 0x005F + 2 * 2 + 255 * 32): - renderer->restorePalette(in); + renderer->restorePalette(in, 0); // At 0x2083 (i.e. 0x2043 + 16 * 2 * 2): globalVars.load(in, NUM_MAX_VAR); diff --git a/engines/cine/saveload.h b/engines/cine/saveload.h index 65f24f838d..a6e0e3f1ab 100644 --- a/engines/cine/saveload.h +++ b/engines/cine/saveload.h @@ -74,7 +74,7 @@ enum CineSaveGameFormat { static const uint32 TEMP_OS_FORMAT_ID = MKID_BE('TEMP'); /** The current version number of Operation Stealth's savegame format. */ -static const uint32 CURRENT_OS_SAVE_VER = 0; +static const uint32 CURRENT_OS_SAVE_VER = 1; /** Chunk header used by the temporary Operation Stealth savegame format. */ struct ChunkHeader { -- cgit v1.2.3 From c933bec975e7d8e176884312a257472a6358fea1 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:17:34 +0000 Subject: Drascula: Optimized blitting code. svn-id: r49700 --- engines/drascula/graphics.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 00399816da..03c866857f 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -190,10 +190,16 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width, dest += xdes + ydes * 320; src += xorg + yorg * 320; - for (y = 0; y < height; y++) - for (x = 0; x < width; x++) - if (src[x + y * 320] != 255) - dest[x + y * 320] = src[x + y * 320]; + int ptr = 0; + for (y = 0; y < height; y++) { + for (x = 0; x < width; x++) { + if (src[ptr] != 255) + dest[ptr] = src[ptr]; + ptr++; + } + ptr += 320 - width; + } + } void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) { -- cgit v1.2.3 From b78663f6fb45728fd90da0c91f5432e1389e421e Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:17:51 +0000 Subject: Drascula: Added animation-related debug output. svn-id: r49701 --- engines/drascula/animation.cpp | 104 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 104 insertions(+) (limited to 'engines') diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index e4bd844d75..67a1e2bee3 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -43,6 +43,8 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig // This is the game's introduction sequence void DrasculaEngine::animation_1_1() { + debug(4, "animation_1_1()"); + int l, l2, p; //int pixelPos[6]; @@ -371,6 +373,8 @@ void DrasculaEngine::animation_1_1() { // John falls in love with BJ, who is then abducted by Drascula void DrasculaEngine::animation_2_1() { + debug(4, "animation_2_1()"); + int l; gotoObject(231, 91); @@ -560,6 +564,8 @@ void DrasculaEngine::animation_2_1() { // John Hacker talks with the bartender to book a room void DrasculaEngine::animation_3_1() { + debug(4, "animation_3_1()"); + loadPic("an11y13.alg", extraSurface); playTalkSequence(3); // sequence 3, chapter 1 @@ -569,6 +575,8 @@ void DrasculaEngine::animation_3_1() { // John Hacker talks with the pianist void DrasculaEngine::animation_4_1() { + debug(4, "animation_4_1()"); + loadPic("an12.alg", extraSurface); talk(205); @@ -605,6 +613,8 @@ void DrasculaEngine::animation_4_1() { } void DrasculaEngine::animation_2_2() { + debug(4, "animation_2_2()"); + trackProtagonist = 0; copyBackground(); moveCharacters(); @@ -640,6 +650,8 @@ void DrasculaEngine::animation_2_2() { } void DrasculaEngine::animation_4_2() { + debug(4, "animation_4_2()"); + stopMusic(); flags[9] = 1; @@ -704,6 +716,8 @@ void DrasculaEngine::animation_4_2() { } void DrasculaEngine::animation_14_2() { + debug(4, "animation_14_2()"); + int cY = -160; int l = 0; @@ -735,6 +749,8 @@ void DrasculaEngine::animation_14_2() { // The drunk tells us about Von Braun void DrasculaEngine::animation_16_2() { + debug(4, "animation_16_2()"); + char curPic[20]; talk_drunk(12); talk(371); @@ -812,6 +828,8 @@ asco: } void DrasculaEngine::animation_20_2() { + debug(4, "animation_20_2()"); + talk_vonBraun(7, kVonBraunDoor); talk_vonBraun(8, kVonBraunDoor); talk(383); @@ -842,6 +860,8 @@ void DrasculaEngine::animation_20_2() { } void DrasculaEngine::animation_23_2() { + debug(4, "animation_23_2()"); + loadPic("an24.alg", frontSurface); flags[21] = 1; @@ -897,6 +917,8 @@ void DrasculaEngine::animation_23_2() { } void DrasculaEngine::animation_23_joined() { + debug(4, "animation_23_joined()"); + int p_x = curX + 2, p_y = curY - 3; int x[] = {1, 38, 75, 112, 75, 112, 75, 112, 149, 112, 149, 112, 149, 186, 223, 260, 1, 38, 75, 112, 149, 112, 149, 112, 149, 112, 149, 186, 223, 260, 260, 260, 260, 223}; @@ -917,6 +939,8 @@ void DrasculaEngine::animation_23_joined() { } void DrasculaEngine::animation_23_joined2() { + debug(4, "animation_23_joined2()"); + int p_x = curX + 4, p_y = curY; int x[] = {1, 35, 69, 103, 137, 171, 205, 239, 273, 1, 35, 69, 103, 137}; int y[] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 73, 73, 73, 73, 73}; @@ -937,6 +961,8 @@ void DrasculaEngine::animation_23_joined2() { } void DrasculaEngine::animation_25_2() { + debug(4, "animation_25_2()"); + int cY = 0; loadPic("an14_2.alg", backSurface); @@ -967,6 +993,8 @@ void DrasculaEngine::animation_25_2() { } void DrasculaEngine::animation_27_2() { + debug(4, "animation_27_2()"); + flags[22] = 1; selectVerb(kVerbNone); @@ -986,6 +1014,8 @@ void DrasculaEngine::animation_27_2() { } void DrasculaEngine::animation_29_2() { + debug(4, "animation_29_2()"); + if (flags[33] == 0) { playTalkSequence(29); // sequence 29, chapter 2 } else @@ -1002,6 +1032,8 @@ void DrasculaEngine::animation_29_2() { } void DrasculaEngine::animation_31_2() { + debug(4, "animation_31_2()"); + talk_vonBraun(44, kVonBraunNormal); placeVonBraun(-50); pause(15); @@ -1020,6 +1052,8 @@ void DrasculaEngine::animation_31_2() { } void DrasculaEngine::animation_35_2() { + debug(4, "animation_35_2()"); + gotoObject(96, 165); gotoObject(79, 165); @@ -1050,6 +1084,8 @@ void DrasculaEngine::animation_35_2() { } void DrasculaEngine::animation_2_3() { + debug(4, "animation_2_3()"); + flags[0] = 1; playMusic(13); animation_3_3(); @@ -1070,6 +1106,8 @@ void DrasculaEngine::animation_2_3() { } void DrasculaEngine::animation_3_3() { + debug(4, "animation_3_3()"); + int px = curX - 20, py = curY - 1; loadPic("an2y_1.alg", frontSurface); @@ -1085,6 +1123,8 @@ void DrasculaEngine::animation_3_3() { } void DrasculaEngine::animation_4_3() { + debug(4, "animation_4_3()"); + int px = 120, py = 63; loadPic("any_1.alg", frontSurface); @@ -1100,6 +1140,8 @@ void DrasculaEngine::animation_4_3() { } void DrasculaEngine::animation_5_3() { + debug(4, "animation_5_3()"); + int px = curX - 20, py = curY - 1; loadPic("an3y_1.alg", frontSurface); @@ -1115,6 +1157,8 @@ void DrasculaEngine::animation_5_3() { } void DrasculaEngine::animation_6_3() { + debug(4, "animation_6_3()"); + int frame = 0, px = 112, py = 62; int yoda_x[] = { 3 ,82, 161, 240, 3, 82 }; int yoda_y[] = { 3, 3, 3, 3, 94, 94 }; @@ -1144,6 +1188,8 @@ void DrasculaEngine::animation_6_3() { } void DrasculaEngine::animation_ray() { + debug(4, "animation_ray()"); + loadPic("anr_1.alg", frontSurface, HALF_PAL); loadPic("anr_2.alg", extraSurface); loadPic("anr_3.alg", backSurface); @@ -1171,6 +1217,8 @@ void DrasculaEngine::animation_ray() { } void DrasculaEngine::animation_7_4() { + debug(4, "animation_7_4()"); + black(); talk(427); fadeFromBlack(1); @@ -1184,6 +1232,8 @@ void DrasculaEngine::animation_7_4() { } void DrasculaEngine::animation_1_5() { + debug(4, "animation_1_5()"); + if (flags[0] == 0) { talk(430); talk_bj(16); @@ -1224,6 +1274,8 @@ void DrasculaEngine::animation_1_5() { } void DrasculaEngine::animation_5_5(){ + debug(4, "animation_5_5("); + int h; int frame = 0; int boneX[] = {1, 99, 197, 1, 99, 197, 1, 99, 197}; @@ -1299,6 +1351,8 @@ void DrasculaEngine::animation_5_5(){ } void DrasculaEngine::animation_11_5() { + debug(4, "animation_11_5()"); + flags[9] = 1; if (flags[2] == 1 && flags[3] == 1 && flags[4] == 1) animation_12_5(); @@ -1309,6 +1363,8 @@ void DrasculaEngine::animation_11_5() { } void DrasculaEngine::animation_12_5() { + debug(4, "animation_12_5()"); + DacPalette256 bgPalette1; DacPalette256 bgPalette2; DacPalette256 bgPalette3; @@ -1415,6 +1471,8 @@ void DrasculaEngine::animation_12_5() { } void DrasculaEngine::animation_13_5() { + debug(4, "animation_13_5()"); + int frank_x = 199; int frame = 0; int frus_x[] = {1, 46, 91, 136, 181, 226, 271}; @@ -1446,6 +1504,8 @@ void DrasculaEngine::animation_13_5() { } void DrasculaEngine::animation_14_5() { + debug(4, "animation_14_5()"); + flags[11] = 1; playSound(3); updateRoom(); @@ -1469,6 +1529,8 @@ void DrasculaEngine::animation_14_5() { } void DrasculaEngine::animation_1_6() { + debug(4, "animation_1_6()"); + trackProtagonist = 0; curX = 103; curY = 108; @@ -1540,6 +1602,8 @@ void DrasculaEngine::animation_1_6() { } void DrasculaEngine::animation_5_6() { + debug(4, "animation_5_6()"); + int pY = -125; animate("man.bin", 14); @@ -1560,6 +1624,8 @@ void DrasculaEngine::animation_5_6() { } void DrasculaEngine::animation_6_6() { + debug(4, "animation_6_6()"); + animate("rct.bin", 11); clearRoom(); selectVerb(kVerbNone); @@ -1584,6 +1650,8 @@ void DrasculaEngine::animation_6_6() { } void DrasculaEngine::animation_9_6() { + debug(4, "animation_9_6()"); + int v_cd; animate("fin.bin", 14); @@ -1660,6 +1728,8 @@ void DrasculaEngine::animation_9_6() { } void DrasculaEngine::animation_19_6() { + debug(4, "animation_19_6()"); + copyBackground(); copyBackground(140, 23, 161, 69, 35, 80, drawSurface3, screenSurface); @@ -1675,6 +1745,8 @@ void DrasculaEngine::animation_19_6() { } void DrasculaEngine::animation_12_2() { + debug(4, "animation_12_2()"); + loadPic("an12.alg", extraSurface); talk(356); @@ -1705,6 +1777,8 @@ void DrasculaEngine::animation_12_2() { } void DrasculaEngine::animation_26_2() { + debug(4, "animation_26_2()"); + loadPic("an12.alg", extraSurface); talk(392); @@ -1762,6 +1836,8 @@ void DrasculaEngine::animation_26_2() { } void DrasculaEngine::animation_11_2() { + debug(4, "animation_11_2()"); + loadPic("an11y13.alg", extraSurface); playTalkSequence(11); // sequence 11, chapter 2 @@ -1770,6 +1846,8 @@ void DrasculaEngine::animation_11_2() { } void DrasculaEngine::animation_13_2() { + debug(4, "animation_13_2()"); + loadPic("an11y13.alg", frontSurface); if (flags[41] == 0) { @@ -1780,6 +1858,8 @@ void DrasculaEngine::animation_13_2() { } void DrasculaEngine::animation_24_2() { + debug(4, "animation_24_2()"); + if (curX < 178) gotoObject(208, 136); trackProtagonist = 3; @@ -1810,6 +1890,8 @@ void DrasculaEngine::animation_24_2() { } void DrasculaEngine::animation_32_2() { + debug(4, "animation_32_2()"); + loadPic("an32_1.alg", drawSurface3); loadPic("an32_2.alg", backSurface); @@ -1831,6 +1913,8 @@ void DrasculaEngine::animation_32_2() { } void DrasculaEngine::animation_34_2() { + debug(4, "animation_34_2()"); + trackProtagonist = 1; updateRoom(); updateScreen(); @@ -1858,6 +1942,8 @@ void DrasculaEngine::animation_34_2() { } void DrasculaEngine::animation_36_2() { + debug(4, "animation_36_2()"); + loadPic("an11y13.alg", extraSurface); talk(404); @@ -1872,6 +1958,8 @@ void DrasculaEngine::animation_36_2() { } void DrasculaEngine::animation_7_2() { + debug(4, "animation_7_2()"); + loadPic("an7_1.alg", backSurface); loadPic("an7_2.alg", extraSurface); loadPic("an7_3.alg", frontSurface); @@ -1928,6 +2016,8 @@ void DrasculaEngine::animation_7_2() { } void DrasculaEngine::animation_5_2() { + debug(4, "animation_5_2()"); + trackProtagonist = 0; updateRoom(); updateScreen(); @@ -1964,6 +2054,8 @@ void DrasculaEngine::animation_5_2() { } void DrasculaEngine::animation_6_2() { + debug(4, "animation_6_2()"); + stopMusic(); flags[9] = 1; @@ -2005,6 +2097,8 @@ void DrasculaEngine::animation_6_2() { } void DrasculaEngine::animation_33_2() { + debug(4, "animation_33_2()"); + stopMusic(); flags[9] = 1; @@ -2052,6 +2146,8 @@ void DrasculaEngine::animation_33_2() { } void DrasculaEngine::animation_1_4() { + debug(4, "animation_1_4()"); + if (flags[21] == 0) { strcpy(objName[2], "igor"); talk(275); @@ -2108,6 +2204,8 @@ void DrasculaEngine::animation_1_4() { } void DrasculaEngine::animation_5_4(){ + debug(4, "animation_5_4("); + trackProtagonist = 3; loadPic("anh_dr.alg", backSurface); gotoObject(99, 160); @@ -2136,6 +2234,8 @@ void DrasculaEngine::animation_5_4(){ } void DrasculaEngine::animation_6_4() { + debug(4, "animation_6_4()"); + int prevRoom = roomNumber; roomNumber = 26; @@ -2161,6 +2261,8 @@ void DrasculaEngine::animation_6_4() { } void DrasculaEngine::animation_8_4() { + debug(4, "animation_8_4()"); + int bookcaseX[] = {1, 75, 149, 223, 1, 75, 149, 223, 149, 223, 149, 223, 149, 223}; int bookcaseY[] = {1, 1, 1, 1, 74, 74, 74, 74, 74, 74, 74, 74, 74, 74}; @@ -2177,6 +2279,8 @@ void DrasculaEngine::animation_8_4() { } void DrasculaEngine::activatePendulum() { + debug(4, "activatePendulum()"); + flags[1] = 2; hare_se_ve = 0; roomNumber = 102; -- cgit v1.2.3 From f992721361d182223f1f551fe8bbfd030a27bd1f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:18:08 +0000 Subject: Drascula: hid room updater-related debug output to deeper level svn-id: r49702 --- engines/drascula/rooms.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/rooms.cpp b/engines/drascula/rooms.cpp index a71545feca..57bfad26af 100644 --- a/engines/drascula/rooms.cpp +++ b/engines/drascula/rooms.cpp @@ -1091,7 +1091,7 @@ void DrasculaEngine::updateRefresh() { sprintf(rm, "update_%d", roomNumber); for (uint i = 0; i < _roomHandlers->roomUpdaters.size(); i++) { if (!strcmp(rm, _roomHandlers->roomUpdaters[i]->desc)) { - debug(4, "Calling room updater %d", roomNumber); + debug(8, "Calling room updater %d", roomNumber); (this->*(_roomHandlers->roomUpdaters[i]->proc))(); break; } @@ -1129,7 +1129,7 @@ void DrasculaEngine::updateRefresh_pre() { sprintf(rm, "update_%d_pre", roomNumber); for (uint i = 0; i < _roomHandlers->roomPreupdaters.size(); i++) { if (!strcmp(rm, _roomHandlers->roomPreupdaters[i]->desc)) { - debug(4, "Calling room preupdater %d", roomNumber); + debug(8, "Calling room preupdater %d", roomNumber); (this->*(_roomHandlers->roomPreupdaters[i]->proc))(); break; } -- cgit v1.2.3 From 2ccb5bb0251d801ef8b2fc15accbf7d421990afa Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:18:34 +0000 Subject: Drascula: Added debug console. Implemented a (buggy) room comand. svn-id: r49703 --- engines/drascula/console.cpp | 63 +++++++++++++++++++++++++++++++++++++++++++ engines/drascula/console.h | 51 +++++++++++++++++++++++++++++++++++ engines/drascula/drascula.cpp | 6 +++++ engines/drascula/drascula.h | 4 +++ engines/drascula/module.mk | 1 + 5 files changed, 125 insertions(+) create mode 100755 engines/drascula/console.cpp create mode 100755 engines/drascula/console.h (limited to 'engines') diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp new file mode 100755 index 0000000000..d017468285 --- /dev/null +++ b/engines/drascula/console.cpp @@ -0,0 +1,63 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "drascula/console.h" +#include "gui/debugger.h" +#include "drascula/drascula.h" + +namespace Drascula { + +Console::Console(DrasculaEngine *vm) : GUI::Debugger(), _vm(vm) { + DCmd_Register("room", WRAP_METHOD(Console, Cmd_Room)); +} + +Console::~Console() { +} + +void Console::preEnter() { +} + +void Console::postEnter() { +} + +bool Console::Cmd_Room(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: changeCard \n"); + return true; + } + + int roomNum = atoi(argv[1]); + + _vm->loadedDifferentChapter = 0; + _vm->enterRoom(roomNum); + _vm->selectVerb(kVerbNone); + _vm->clearRoom(); + _vm->loadPic(roomNum, _vm->bgSurface, HALF_PAL); + _vm->selectionMade = 0; + + return false; +} + +} // End of namespace Drascula diff --git a/engines/drascula/console.h b/engines/drascula/console.h new file mode 100755 index 0000000000..33e2f626e4 --- /dev/null +++ b/engines/drascula/console.h @@ -0,0 +1,51 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef DRASCULA_CONSOLE_H +#define DRASCULA_CONSOLE_H + +#include "gui/debugger.h" + +namespace Drascula { + +class DrasculaEngine; + +class Console : public GUI::Debugger { +public: + Console(DrasculaEngine *vm); + virtual ~Console(void); + +protected: + virtual void preEnter(); + virtual void postEnter(); + +private: + DrasculaEngine *_vm; + + bool Cmd_Room(int argc, const char **argv); +}; + +} // End of namespace Drascula +#endif diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 2c3ca63600..b16182e3e2 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -38,6 +38,7 @@ #include "sound/mixer.h" #include "drascula/drascula.h" +#include "drascula/console.h" namespace Drascula { @@ -173,6 +174,8 @@ Common::Error DrasculaEngine::run() { _lang = kEnglish; } + _console = new Console(this); + if (!loadDrasculaDat()) return Common::kUnknownError; @@ -594,6 +597,9 @@ bool DrasculaEngine::runCurrentChapter() { } else if (key == Common::KEYCODE_ESCAPE) { if (!confirmExit()) return false; + } else if (key == Common::KEYCODE_TILDE || key == Common::KEYCODE_BACKQUOTE) { + _console->attach(); + _console->onFrame(); } else if (currentChapter == 6 && key == Common::KEYCODE_0 && roomNumber == 61) { loadPic("alcbar.alg", bgSurface, 255); } diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index 4876cf3390..aaa1a4f42a 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -317,6 +317,8 @@ static const int interf_y[] = { 51, 51, 51, 51, 83, 83, 83 }; struct RoomHandlers; +class Console; + class DrasculaEngine : public ::Engine { protected: // Engine APIs @@ -733,6 +735,8 @@ public: private: int _lang; + Console *_console; + CharInfo *_charMap; int _charMapSize; diff --git a/engines/drascula/module.mk b/engines/drascula/module.mk index a9fa257549..20fd900124 100644 --- a/engines/drascula/module.mk +++ b/engines/drascula/module.mk @@ -3,6 +3,7 @@ MODULE := engines/drascula MODULE_OBJS := \ actors.o \ animation.o \ + console.o \ converse.o \ detection.o \ drascula.o \ -- cgit v1.2.3 From 6d4ad23b55c328fd1674b07330f85b14bfc20482 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:18:51 +0000 Subject: Drascula: Fix bug #2854303. Bug #2854303: "DRASCULA: Glitch when using cross on vampire guard". Apparently during refactoring of animation-related code duplication the conversion was incorrect. Rewrote relevant function. svn-id: r49704 --- engines/drascula/animation.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 67a1e2bee3..33607c2f15 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -32,9 +32,12 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig for (int n = 0; n < count; n++){ x++; - copyBackground(x, y, destX, destY, width, height, src, screenSurface); - if (copyRectangle) + if (copyRectangle) { + copyBackground(destX, destY, destX, destY, width, height, bgSurface, screenSurface); copyRect(x, y, destX, destY, width, height, src, screenSurface); + } else { + copyBackground(x, y, destX, destY, width, height, src, screenSurface); + } updateScreen(destX, destY, destX, destY, width, height, screenSurface); x += width; pause(delayVal); @@ -1083,6 +1086,7 @@ void DrasculaEngine::animation_35_2() { fadeToBlack(2); } +// Use cross on Yoda void DrasculaEngine::animation_2_3() { debug(4, "animation_2_3()"); -- cgit v1.2.3 From eac1fdc7caf115f2deacecd8438cb650b403e6c2 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:19:25 +0000 Subject: Drascula: added more debug output svn-id: r49706 --- engines/drascula/converse.cpp | 4 ++++ engines/drascula/interface.cpp | 2 ++ 2 files changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index b2a7e217e6..deefcaddbe 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -131,6 +131,8 @@ void DrasculaEngine::cleanupString(char *string) { } void DrasculaEngine::converse(int index) { + debug(4, "converse(%d)", index); + char fileName[20]; sprintf(fileName, "op_%d.cal", index); Common::SeekableReadStream *stream = _archives.open(fileName); @@ -279,6 +281,8 @@ void DrasculaEngine::converse(int index) { } void DrasculaEngine::response(int function) { + debug(4, "response(%d)", function); + playTalkSequence(function); if (currentChapter == 2) { diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 21803a8932..507cc6e123 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -65,6 +65,8 @@ void DrasculaEngine::selectVerbFromBar() { } void DrasculaEngine::selectVerb(int verb) { + debug(4, "selectVerb(%d)", verb); + int c = _menuScreen ? 0 : 171; if (currentChapter == 5) { -- cgit v1.2.3 From b743cc316e3a0af47880f98f01f1437dc5b8124d Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:19:48 +0000 Subject: Drascula: Fix bug #2929931. Bug #2929931: "DRASCULA: Graphic Glitches". Cursor graphics was not loaded at needed time. svn-id: r49707 --- engines/drascula/converse.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index deefcaddbe..122e473f15 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -288,9 +288,10 @@ void DrasculaEngine::response(int function) { if (currentChapter == 2) { if (function == 16) animation_16_2(); - else if (function == 20) + else if (function == 20) { + loadPic(menuBackground, backSurface); animation_20_2(); - else if (function == 23) + } else if (function == 23) animation_23_2(); else if (function == 29) animation_29_2(); -- cgit v1.2.3 From 27c27c82b1f29030af468142a452dc33e87e56f4 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:20:10 +0000 Subject: Drascula: add more pic-related debug output. svn-id: r49708 --- engines/drascula/graphics.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 03c866857f..018b64d59f 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -90,6 +90,8 @@ void DrasculaEngine::moveCursor() { } void DrasculaEngine::loadPic(const char *NamePcc, byte *targetSurface, int colorCount) { + debug(5, "loadPic(%s)", NamePcc); + uint dataSize = 0; byte *pcxData; -- cgit v1.2.3 From e8b72467e1472c42bb99c5eba84f2e9e059c1a3b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:20:26 +0000 Subject: Drascula: ease load on backend. svn-id: r49709 --- engines/drascula/graphics.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 018b64d59f..28ade30601 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -205,9 +205,7 @@ void DrasculaEngine::copyRect(int xorg, int yorg, int xdes, int ydes, int width, } void DrasculaEngine::updateScreen(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *buffer) { - byte *screenBuffer = (byte *)_system->lockScreen()->pixels; - copyBackground(xorg, yorg, xdes, ydes, width, height, buffer, screenBuffer); - _system->unlockScreen(); + _system->copyRectToScreen(buffer + xorg + yorg * 320, 320, xdes, ydes, width, height); _system->updateScreen(); } -- cgit v1.2.3 From a9b9da5d7263c0c0cb9c1cc76a4351440d4d3a97 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:20:44 +0000 Subject: Drascula: Fix bug #2826610. Bug #2826610: "DRASCULA: Graveyard GFX error". Actually it was fixed by previous commit. Added more responsiveness for this animation. svn-id: r49710 --- engines/drascula/animation.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 33607c2f15..9f2ffe164b 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -40,6 +40,7 @@ void DrasculaEngine::updateAnim(int y, int destX, int destY, int width, int heig } updateScreen(destX, destY, destX, destY, width, height, screenSurface); x += width; + updateEvents(); pause(delayVal); } } @@ -1961,6 +1962,7 @@ void DrasculaEngine::animation_36_2() { loadPic(974, extraSurface); } +// Use sickle on plant void DrasculaEngine::animation_7_2() { debug(4, "animation_7_2()"); -- cgit v1.2.3 From 07cc483e139ac9449b2c41240aa43dbb18bab823 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:21:01 +0000 Subject: Drascula: Restore cursors before automated converse responses svn-id: r49711 --- engines/drascula/converse.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index 122e473f15..7c845fb251 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -286,12 +286,14 @@ void DrasculaEngine::response(int function) { playTalkSequence(function); if (currentChapter == 2) { + if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31) + loadPic(menuBackground, backSurface); + if (function == 16) animation_16_2(); - else if (function == 20) { - loadPic(menuBackground, backSurface); + else if (function == 20) animation_20_2(); - } else if (function == 23) + else if (function == 23) animation_23_2(); else if (function == 29) animation_29_2(); -- cgit v1.2.3 From 0796580c3e10c99af209b26537823ca4a69acd76 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:21:18 +0000 Subject: Drascula: Made actors animation more smooth. svn-id: r49712 --- engines/drascula/actors.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index ff46d8201a..c4996d543e 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -77,6 +77,7 @@ void DrasculaEngine::hiccup(int counter) { do { counter--; + updateEvents(); updateRoom(); if (currentChapter == 3) updateScreen(0, 0, 0, y, 320, 200, screenSurface); @@ -449,6 +450,7 @@ void DrasculaEngine::placeVonBraun(int pointX) { vonBraunHasMoved = 1; for (;;) { + updateEvents(); updateRoom(); updateScreen(); if (trackVonBraun == 0) { -- cgit v1.2.3 From 671ed4873f163bc64f59af6317791db4bbaa2824 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:21:42 +0000 Subject: Drascula: Fixed bug #2826608. Bug #2826608: "DRASCULA: Cursor GFX error" fixed by introducing separate buffer for cursors. This also fixes the root cause of the problem. svn-id: r49713 --- engines/drascula/drascula.cpp | 2 ++ engines/drascula/drascula.h | 1 + engines/drascula/graphics.cpp | 2 ++ engines/drascula/interface.cpp | 2 +- 4 files changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index b16182e3e2..4c38a87291 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -244,6 +244,8 @@ Common::Error DrasculaEngine::run() { if (currentChapter != 3) loadPic(96, frontSurface, COMPLETE_PAL); + loadPic(99, cursorSurface); + if (currentChapter == 1) { } else if (currentChapter == 2) { loadPic("pts.alg", drawSurface2); diff --git a/engines/drascula/drascula.h b/engines/drascula/drascula.h index aaa1a4f42a..0a8b7c8c9b 100644 --- a/engines/drascula/drascula.h +++ b/engines/drascula/drascula.h @@ -391,6 +391,7 @@ public: // Graphics buffers/pointers byte *bgSurface; byte *backSurface; + byte *cursorSurface; byte *drawSurface3; byte *drawSurface2; byte *tableSurface; diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 28ade30601..088e1e1da9 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -54,6 +54,7 @@ void DrasculaEngine::allocMemory() { assert(crosshairCursor); mouseCursor = (byte *)malloc(OBJWIDTH * OBJHEIGHT); assert(mouseCursor); + cursorSurface = (byte *)malloc(64000); } void DrasculaEngine::freeMemory() { @@ -67,6 +68,7 @@ void DrasculaEngine::freeMemory() { free(frontSurface); free(crosshairCursor); free(mouseCursor); + free(cursorSurface); } void DrasculaEngine::moveCursor() { diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 507cc6e123..38be3c6d5c 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -78,7 +78,7 @@ void DrasculaEngine::selectVerb(int verb) { } for (int i = 0; i < OBJHEIGHT; i++) - memcpy(mouseCursor + i * OBJWIDTH, backSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH); + memcpy(mouseCursor + i * OBJWIDTH, cursorSurface + OBJWIDTH * verb + (c + i) * 320, OBJWIDTH); setCursor(kCursorCurrentItem); if (verb > 0) { -- cgit v1.2.3 From 1850d53793388f81b3c058ba02c314994a6e6ec9 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:21:59 +0000 Subject: Drascula: Plug memory leak svn-id: r49714 --- engines/drascula/drascula.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 4c38a87291..bc6f57ea12 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -116,6 +116,8 @@ DrasculaEngine::~DrasculaEngine() { freeRoomsTable(); + delete _console; + free(_charMap); free(_itemLocations); free(_polX); -- cgit v1.2.3 From f53211fbadb6c88161f8830baee476a91a0cc547 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:22:19 +0000 Subject: Drascula: Move more cursor-related blits to cursorSurface. svn-id: r49715 --- engines/drascula/drascula.cpp | 21 +++++++++++++++------ engines/drascula/graphics.cpp | 3 +-- engines/drascula/interface.cpp | 4 ++-- 3 files changed, 18 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index bc6f57ea12..0b2ddc6799 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -279,6 +279,7 @@ Common::Error DrasculaEngine::run() { loadPic(974, tableSurface); if (currentChapter != 2) { + loadPic(99, cursorSurface); loadPic(99, backSurface); loadPic(97, extraSurface); } @@ -507,10 +508,13 @@ bool DrasculaEngine::runCurrentChapter() { if (rightMouseButton == 1 && _menuScreen) { #endif delay(100); - if (currentChapter == 2) + if (currentChapter == 2) { + loadPic(menuBackground, cursorSurface); loadPic(menuBackground, backSurface); - else + } else { + loadPic(99, cursorSurface); loadPic(99, backSurface); + } setPalette((byte *)&gamePalette); _menuScreen = false; #ifndef _WIN32_WCE @@ -535,14 +539,19 @@ bool DrasculaEngine::runCurrentChapter() { characterMoved = 0; if (trackProtagonist == 2) trackProtagonist = 1; - if (currentChapter == 4) + if (currentChapter == 4) { loadPic("icons2.alg", backSurface); - else if (currentChapter == 5) + loadPic("icons2.alg", cursorSurface); + } else if (currentChapter == 5) { loadPic("icons3.alg", backSurface); - else if (currentChapter == 6) + loadPic("icons3.alg", cursorSurface); + } else if (currentChapter == 6) { loadPic("iconsp.alg", backSurface); - else + loadPic("iconsp.alg", cursorSurface); + } else { loadPic("icons.alg", backSurface); + loadPic("icons.alg", cursorSurface); + } _menuScreen = true; #ifndef _WIN32_WCE updateEvents(); diff --git a/engines/drascula/graphics.cpp b/engines/drascula/graphics.cpp index 088e1e1da9..70085b99af 100644 --- a/engines/drascula/graphics.cpp +++ b/engines/drascula/graphics.cpp @@ -151,8 +151,7 @@ void DrasculaEngine::showFrame(Common::SeekableReadStream *stream, bool firstFra free(prevFrame); } -void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, - int height, byte *src, byte *dest) { +void DrasculaEngine::copyBackground(int xorg, int yorg, int xdes, int ydes, int width, int height, byte *src, byte *dest) { dest += xdes + ydes * 320; src += xorg + yorg * 320; /* Unoptimized code diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp index 38be3c6d5c..1495694a1b 100644 --- a/engines/drascula/interface.cpp +++ b/engines/drascula/interface.cpp @@ -128,7 +128,7 @@ void DrasculaEngine::showMenu() { OBJWIDTH, OBJHEIGHT, srcSurface, screenSurface); } copyRect(_x1d_menu[h], _y1d_menu[h], _itemLocations[n].x, _itemLocations[n].y, - OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface); } if (x < 7) @@ -142,7 +142,7 @@ void DrasculaEngine::clearMenu() { if (mouseX > _verbBarX[n] && mouseX < _verbBarX[n + 1]) verbActivated = 0; copyRect(OBJWIDTH * n, OBJHEIGHT * verbActivated, _verbBarX[n], 2, - OBJWIDTH, OBJHEIGHT, backSurface, screenSurface); + OBJWIDTH, OBJHEIGHT, cursorSurface, screenSurface); verbActivated = 1; } } -- cgit v1.2.3 From e4d77cf098e9e9bdefce9ab13e7808ca89226c74 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:22:39 +0000 Subject: Drascula: Add responsiveness while talking. svn-id: r49716 --- engines/drascula/talk.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 54175c5e5b..91711681e3 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -331,11 +331,9 @@ void DrasculaEngine::talk_bj(int index) { updateRefresh_pre(); - copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, - bgSurface, screenSurface); + copyBackground(bjX + 2, bjY - 1, bjX + 2, bjY - 1, 27, 40, bgSurface, screenSurface); - copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, - drawSurface3, screenSurface); + copyRect(x_talk[face], 99, bjX + 2, bjY - 1, 27, 40, drawSurface3, screenSurface); moveCharacters(); updateRefresh(); @@ -353,6 +351,7 @@ void DrasculaEngine::talk_bj(int index) { updateScreen(); } + updateEvents(); } while (!isTalkFinished()); updateRoom(); -- cgit v1.2.3 From ba25faaf421bbe28403ede0fcf15015b7eb4729e Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:22:56 +0000 Subject: Drascula: more responsiveness. svn-id: r49717 --- engines/drascula/animation.cpp | 21 +++++++++++++++++++-- 1 file changed, 19 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 9f2ffe164b..11489edd0b 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -147,9 +147,9 @@ void DrasculaEngine::animation_1_1() { copyBackground(0, 0, 320 - l, 0, l, 200, drawSurface3, screenSurface); copyBackground(l, 0, 0, 0, 320 - l, 200, bgSurface, screenSurface); - copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31, - drawSurface2, screenSurface); + copyRect(interf_x[l2], interf_y[l2], 156 - l, 45, 63, 31, drawSurface2, screenSurface); updateScreen(); + updateEvents(); p++; if (p == 6) { p = 0; @@ -936,6 +936,7 @@ void DrasculaEngine::animation_23_joined() { copyRect(x[n], y[n], p_x, p_y, 36, 74, backSurface, screenSurface); updateRefresh(); updateScreen(p_x, p_y, p_x, p_y, 36, 74, screenSurface); + updateEvents(); pause(5); } @@ -958,6 +959,7 @@ void DrasculaEngine::animation_23_joined2() { copyRect(x[n], y[n], p_x, p_y, 33, 71, backSurface, screenSurface); updateRefresh(); updateScreen(p_x,p_y, p_x,p_y, 33,71, screenSurface); + updateEvents(); pause(5); } @@ -989,6 +991,7 @@ void DrasculaEngine::animation_25_2() { updateRefresh(); updateScreen(); + updateEvents(); } finishSound(); @@ -1182,6 +1185,7 @@ void DrasculaEngine::animation_6_3() { copyBackground(); copyRect(yoda_x[frame], yoda_y[frame], px, py, 78, 90, frontSurface, screenSurface); updateScreen(px, py, px, py, 78, 90, screenSurface); + updateEvents(); } flags[2] = 1; @@ -1267,6 +1271,7 @@ void DrasculaEngine::animation_1_5() { break; updateRoom(); updateScreen(); + updateEvents(); } trackProtagonist = 1; @@ -1304,6 +1309,7 @@ void DrasculaEngine::animation_5_5(){ copyBackground(); copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, backSurface, screenSurface); updateScreen(pixelX, pixelY, pixelX,pixelY, 97,64, screenSurface); + updateEvents(); } copyBackground(52, 161, 198, 81, 26, 24, drawSurface3, screenSurface); @@ -1314,6 +1320,7 @@ void DrasculaEngine::animation_5_5(){ copyBackground(); copyRect(boneX[frame], boneY[frame], pixelX, pixelY, 97, 64, frontSurface, screenSurface); updateScreen(pixelX, pixelY, pixelX,pixelY, 97, 64, screenSurface); + updateEvents(); } flags[6] = 1; @@ -1336,11 +1343,13 @@ void DrasculaEngine::animation_5_5(){ pause(3); copyBackground(flyX[frame], 1, 174, 79, 61, 109, backSurface, screenSurface); updateScreen(174, 79, 174, 79, 61, 109, screenSurface); + updateEvents(); } for (frame = 0; frame < 5; frame++) { pause(3); copyBackground(flyX[frame], 1, 174, 79, 61, 109, extraSurface, screenSurface); updateScreen(174, 79, 174, 79, 61, 109, screenSurface); + updateEvents(); } updateScreen(0, 0, 0, 0, 320, 200, bgSurface); @@ -1428,6 +1437,7 @@ void DrasculaEngine::animation_12_5() { copyRect(rayX[frame], 1, 41, 0, 44, 44, backSurface, screenSurface); copyRect(frusky_x[frame], 113, 205, 50, 38, 86, drawSurface3, screenSurface); updateScreen(); + updateEvents(); } stopSound(); @@ -1444,6 +1454,7 @@ void DrasculaEngine::animation_12_5() { updateRoom(); copyRect(elfrusky_x[frame], 47, 192, 39, 66, 106, backSurface, screenSurface); updateScreen(); + updateEvents(); } animate("frel.bin", 16); @@ -1504,6 +1515,7 @@ void DrasculaEngine::animation_13_5() { frame = 0; trackProtagonist = 3; } + updateEvents(); pause(6); } } @@ -1622,6 +1634,7 @@ void DrasculaEngine::animation_5_6() { updateRefresh(); updateScreen(); + updateEvents(); pause(2); } @@ -1824,6 +1837,7 @@ void DrasculaEngine::animation_26_2() { x = x + 50; if (n == 2) playSound(9); + updateEvents(); pause(3); } @@ -1912,6 +1926,8 @@ void DrasculaEngine::animation_32_2() { x = x + 65; if (n < 2) pause(4); + + updateEvents(); } loadPic("aux18.alg", drawSurface3); @@ -2278,6 +2294,7 @@ void DrasculaEngine::animation_8_4() { pause(2); copyBackground(bookcaseX[frame], bookcaseY[frame], 77, 45, 73, 72, frontSurface, screenSurface); updateScreen(77, 45, 77, 45, 73, 72, screenSurface); + updateEvents(); } loadPic(96, frontSurface); -- cgit v1.2.3 From 02a76b2e91a0993d551ad799ebe2f98ed0f9e98b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:23:17 +0000 Subject: Drascula: add even more responsiveness svn-id: r49718 --- engines/drascula/actors.cpp | 1 + engines/drascula/animation.cpp | 7 +++++++ engines/drascula/objects.cpp | 3 +++ engines/drascula/talk.cpp | 28 ++++++++++++++++++++++------ 4 files changed, 33 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/drascula/actors.cpp b/engines/drascula/actors.cpp index c4996d543e..33cb7fd478 100644 --- a/engines/drascula/actors.cpp +++ b/engines/drascula/actors.cpp @@ -100,6 +100,7 @@ void DrasculaEngine::hiccup(int counter) { if (y == 0) trackCharacter = 0; } + pause(3); } while (counter > 0); updateRoom(); diff --git a/engines/drascula/animation.cpp b/engines/drascula/animation.cpp index 11489edd0b..d6a3bafd9f 100644 --- a/engines/drascula/animation.cpp +++ b/engines/drascula/animation.cpp @@ -1576,11 +1576,15 @@ void DrasculaEngine::animation_1_6() { talk_drascula(28, 1); talk(255); talk_drascula(29, 1); + updateEvents(); fadeToBlack(1); + updateEvents(); clearRoom(); loadPic("time1.alg", screenSurface); updateScreen(); + updateEvents(); delay(930); + updateEvents(); clearRoom(); black(); hare_se_ve = 0; @@ -1592,10 +1596,13 @@ void DrasculaEngine::animation_1_6() { talk_drascula(30, 1); talk(257); fadeToBlack(0); + updateEvents(); clearRoom(); loadPic("time1.alg", screenSurface); updateScreen(); + updateEvents(); delay(900); + updateEvents(); clearRoom(); black(); updateRoom(); diff --git a/engines/drascula/objects.cpp b/engines/drascula/objects.cpp index 13c8a742ca..73aea7b7f2 100644 --- a/engines/drascula/objects.cpp +++ b/engines/drascula/objects.cpp @@ -78,8 +78,11 @@ void DrasculaEngine::gotoObject(int pointX, int pointY) { for (;;) { updateRoom(); updateScreen(); + updateEvents(); if (characterMoved == 0) break; + + pause(3); } if (walkToObject == 1) { diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index 91711681e3..e7dbe5cba9 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -170,6 +170,7 @@ void DrasculaEngine::talk_drascula(int index, int talkerType) { centerText(said, drasculaX + 19, drasculaY); updateScreen(); + updateEvents(); pause(3); @@ -215,6 +216,7 @@ void DrasculaEngine::talk_drascula_big(int index) { centerText(said, 191, 69); updateScreen(); + updateEvents(); pause(3); @@ -245,7 +247,9 @@ void DrasculaEngine::talk_solo(const char *said, const char *filename) { else if (currentChapter == 5) centerText(said, 173, 92); } + updateEvents(); updateScreen(); + pause(3); } while (!isTalkFinished()); if (currentChapter == 6) { @@ -304,6 +308,7 @@ void DrasculaEngine::talk_bartender(int index, int talkerType) { centerText(said, 132, 45); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -466,6 +471,7 @@ void DrasculaEngine::talk(const char *said, const char *filename) { centerText(said, curX, curY); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -557,16 +563,15 @@ void DrasculaEngine::talk_vonBraun(int index, int talkerType) { if (!_subtitlesDisabled) centerText(said, vonBraunX, 66); - updateScreen(); - pause(3); } else { updateRoom(); if (!_subtitlesDisabled) centerText(said, 150, 80); - - updateScreen(); } + updateScreen(); + updateEvents(); + pause(3); } while (!isTalkFinished()); updateRoom(); @@ -620,6 +625,7 @@ void DrasculaEngine::talk_blind(int index) { centerText(said, 260, 71); updateScreen(); + updateEvents(); pause(2); p++; } while (!isTalkFinished()); @@ -640,7 +646,9 @@ void DrasculaEngine::talk_hacker(int index) { do { if (!_subtitlesDisabled) centerText(said, 156, 170); + updateEvents(); updateScreen(); + pause(3); } while (!isTalkFinished()); } @@ -707,6 +715,7 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker } updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -744,6 +753,7 @@ void DrasculaEngine::talk_bj_bed(int index) { centerText(said, 104, 102); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -780,6 +790,7 @@ void DrasculaEngine::talk_htel(int index) { centerText(said, 90, 50); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -861,6 +872,7 @@ void DrasculaEngine::talk_sync(const char *said, const char *filename, const cha centerText(said, curX, curY); updateScreen(); + updateEvents(); p++; pause(3); @@ -894,6 +906,7 @@ void DrasculaEngine::talk_trunk(int index) { centerText(said, 263, 69); updateScreen(); + updateEvents(); pause(4); } while (!isTalkFinished()); @@ -921,6 +934,7 @@ void DrasculaEngine::talk_generic(const char* said, const char* filename, int* f centerText(said, coords[5], coords[6]); updateScreen(); + updateEvents(); pause(3); } while (!isTalkFinished()); @@ -943,8 +957,10 @@ void DrasculaEngine::grr() { updateScreen(); - while (!isTalkFinished()) - ; + while (!isTalkFinished()) { + updateEvents(); + pause(3); + } updateRoom(); updateScreen(); -- cgit v1.2.3 From e71caf8600bfdfeccd1cf817401daf457ce17a94 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:23:36 +0000 Subject: Drascula: Fix bug #2827169. Bug #2827169: "DRASCULA: gfx glitch in pendulum room" fixed by rearranging draw sequence. svn-id: r49719 --- engines/drascula/talk.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/talk.cpp b/engines/drascula/talk.cpp index e7dbe5cba9..8cefe0385c 100644 --- a/engines/drascula/talk.cpp +++ b/engines/drascula/talk.cpp @@ -700,13 +700,13 @@ void DrasculaEngine::talk_pen(const char *said, const char *filename, int talker copyBackground(); updateRefresh_pre(); + updateRefresh(); + if (talkerType == 0) copyRect(x_talk[face], 145, 145, 105, 25, 29, drawSurface3, screenSurface); else copyBackground(x_talk2[face], 171, 173, 116, 25, 28, drawSurface3, screenSurface); - updateRefresh(); - if (!_subtitlesDisabled) { if (talkerType == 0) centerText(said, 160, 105); -- cgit v1.2.3 From 08c5d37da495538e5a4b634ec5a705ec305a97bc Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:23:58 +0000 Subject: Drascula: Fix bug #2827166. Bug #2827166: "DRASCULA: Repeating conversations". It looked like bug in original engine. svn-id: r49720 --- engines/drascula/converse.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/drascula/converse.cpp b/engines/drascula/converse.cpp index 7c845fb251..0e70348148 100644 --- a/engines/drascula/converse.cpp +++ b/engines/drascula/converse.cpp @@ -283,7 +283,8 @@ void DrasculaEngine::converse(int index) { void DrasculaEngine::response(int function) { debug(4, "response(%d)", function); - playTalkSequence(function); + if (function != 31) + playTalkSequence(function); if (currentChapter == 2) { if (function == 16 || function == 20 || function == 23 || function == 29 || function == 31) -- cgit v1.2.3 From 508256a71e3a194043f1c5e65699613ba2b441db Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:24:19 +0000 Subject: Drascula: Fix bug #2011470. Bug #2011470: "DRASCULA: slowdown when you hold mouse buttons" fixed by changing right mouse semantic. Now the items menu showed on button up instead mouse down like earlier. svn-id: r49721 --- engines/drascula/drascula.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index 0b2ddc6799..d8aeee3c97 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -507,6 +507,7 @@ bool DrasculaEngine::runCurrentChapter() { #else if (rightMouseButton == 1 && _menuScreen) { #endif + rightMouseButton = 0; delay(100); if (currentChapter == 2) { loadPic(menuBackground, cursorSurface); @@ -535,6 +536,7 @@ bool DrasculaEngine::runCurrentChapter() { if (rightMouseButton == 1 && !_menuScreen && !(currentChapter == 5 && pickedObject == 16)) { #endif + rightMouseButton = 0; delay(100); characterMoved = 0; if (trackProtagonist == 2) @@ -760,10 +762,10 @@ void DrasculaEngine::updateEvents() { leftMouseButton = 0; break; case Common::EVENT_RBUTTONDOWN: - rightMouseButton = 1; + // We changed semantic and react only on button up event break; case Common::EVENT_RBUTTONUP: - rightMouseButton = 0; + rightMouseButton = 1; break; case Common::EVENT_QUIT: // TODO -- cgit v1.2.3 From 2e20a48f907c61352a1ae69573830dd346a1bc61 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:24:38 +0000 Subject: Drascula: improve responsivity during pauses and palette updates. svn-id: r49722 --- engines/drascula/drascula.cpp | 10 ++++++++-- engines/drascula/palette.cpp | 4 ++++ 2 files changed, 12 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index d8aeee3c97..7e9f68a355 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -779,11 +779,17 @@ void DrasculaEngine::updateEvents() { } void DrasculaEngine::delay(int ms) { - _system->delayMillis(ms * 2); // originally was 1 + uint32 end = _system->getMillis() + ms * 2; // originally was 1 + + do { + _system->delayMillis(10); + updateEvents(); + _system->updateScreen(); + } while (_system->getMillis() < end); } void DrasculaEngine::pause(int duration) { - _system->delayMillis(duration * 30); // was originally 2 + delay(duration * 15); } int DrasculaEngine::getTime() { diff --git a/engines/drascula/palette.cpp b/engines/drascula/palette.cpp index 1e51deffd9..0f75bb7959 100644 --- a/engines/drascula/palette.cpp +++ b/engines/drascula/palette.cpp @@ -106,6 +106,8 @@ void DrasculaEngine::fadeToBlack(int fadeSpeed) { pause(fadeSpeed); setPalette((byte *)&palFade); + + updateEvents(); } } @@ -124,6 +126,8 @@ void DrasculaEngine::fadeFromBlack(int fadeSpeed) { pause(fadeSpeed); setPalette((byte *)&palFade); + + updateEvents(); } } -- cgit v1.2.3 From 6d2c916c34d875d540f2a06b112b2e2fba5f2473 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:24:55 +0000 Subject: SAGA: Add debug output for sfLockUser() svn-id: r49723 --- engines/saga/sfuncs.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index a924383ba3..99a9cbf4d9 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -370,12 +370,15 @@ void Script::sfStopBgdAnim(SCRIPTFUNC_PARAMS) { // reenabled. // Param1: boolean void Script::sfLockUser(SCRIPTFUNC_PARAMS) { - if (thread->pop()) { + int16 param = thread->pop(); + + if (param != 0) { _vm->_interface->deactivate(); } else { _vm->_interface->activate(); } + debug(1, "sfLockUser(%d)", param); } // Script function #12 (0x0C) -- cgit v1.2.3 From 0b8f8d7a249b5077e8866bc2f5d959d4a118d5b1 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:25:13 +0000 Subject: SAGA: Fix bug #2886151. Bug #2886151: "ITE: Mouse stops responding at Boar Castle" fixed by implementing a workaround. It is a script bug in original. svn-id: r49724 --- engines/saga/scene.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/saga/scene.cpp b/engines/saga/scene.cpp index 8cb632ae91..d7ee037c50 100644 --- a/engines/saga/scene.cpp +++ b/engines/saga/scene.cpp @@ -1201,6 +1201,12 @@ void Scene::endScene() { _vm->_script->abortAllThreads(); _vm->_script->_skipSpeeches = false; + // WORKAROUND: Bug #2886151: "ITE: Mouse stops responding at Boar Castle" + // This is bug in original engine + if (_sceneNumber == 50) { + _vm->_interface->activate(); + } + // Copy current screen to render buffer so inset rooms will get proper background if (!(_sceneDescription.flags & kSceneFlagISO) && !_vm->_scene->isInIntro()) { BGInfo bgInfo; -- cgit v1.2.3 From d1c34efad91e4b42dd88e0e45452f26d117d3c04 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:25:34 +0000 Subject: SAGA: Fix bug #2886141. Bug #2886141: "ITE: Cumulative Snoring sounds in Prince's Bedroom". Implemented safeguard against running same looped sound more than once. svn-id: r49725 --- engines/saga/sfuncs.cpp | 2 ++ engines/saga/sndres.cpp | 2 +- engines/saga/sound.cpp | 13 ++++++++++++- engines/saga/sound.h | 3 ++- 4 files changed, 17 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/saga/sfuncs.cpp b/engines/saga/sfuncs.cpp index 99a9cbf4d9..328d4040af 100644 --- a/engines/saga/sfuncs.cpp +++ b/engines/saga/sfuncs.cpp @@ -1464,6 +1464,8 @@ void Script::sfPlayLoopedSound(SCRIPTFUNC_PARAMS) { } else { _vm->_sound->stopSound(); } + + debug(1, "sfPlayLoopedSound(%d)", param); } // Script function #72 (0x48) diff --git a/engines/saga/sndres.cpp b/engines/saga/sndres.cpp index 8ea3fc4003..a27608dcf5 100644 --- a/engines/saga/sndres.cpp +++ b/engines/saga/sndres.cpp @@ -159,7 +159,7 @@ void SndRes::playSound(uint32 resourceId, int volume, bool loop) { return; } - _vm->_sound->playSound(buffer, volume, loop); + _vm->_sound->playSound(buffer, volume, loop, resourceId); } void SndRes::playVoice(uint32 resourceId) { diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index 811ee709f7..db979e8104 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -105,10 +105,20 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundBuffer &buffe _mixer->playStream(soundType, handle, Audio::makeLoopingAudioStream(stream, loop ? 0 : 1), -1, volume); } -void Sound::playSound(SoundBuffer &buffer, int volume, bool loop) { +void Sound::playSound(SoundBuffer &buffer, int volume, bool loop, int resId) { + // WORKAROUND + // Prevent playing same looped sound for several times + // Fixes bug #2886141: "ITE: Cumulative Snoring sounds in Prince's Bedroom" + for (int i = 0; i < SOUND_HANDLES; i++) + if (_handles[i].type == kEffectHandle && _handles[i].resId == resId) { + debug(1, "Skipped playing SFX #%d", resId); + return; + } + SndHandle *handle = getHandle(); handle->type = kEffectHandle; + handle->resId = resId; playSoundBuffer(&handle->handle, buffer, 2 * volume, handle->type, loop); } @@ -129,6 +139,7 @@ void Sound::stopSound() { if (_handles[i].type == kEffectHandle) { _mixer->stopHandle(_handles[i].handle); _handles[i].type = kFreeHandle; + _handles[i].resId = -1; } } diff --git a/engines/saga/sound.h b/engines/saga/sound.h index 9cf8f29767..7ee2765a0f 100644 --- a/engines/saga/sound.h +++ b/engines/saga/sound.h @@ -63,6 +63,7 @@ enum sndHandleType { struct SndHandle { Audio::SoundHandle handle; sndHandleType type; + int resId; }; class Sound { @@ -71,7 +72,7 @@ public: Sound(SagaEngine *vm, Audio::Mixer *mixer); ~Sound(); - void playSound(SoundBuffer &buffer, int volume, bool loop); + void playSound(SoundBuffer &buffer, int volume, bool loop, int resId); void pauseSound(); void resumeSound(); void stopSound(); -- cgit v1.2.3 From fead2bb719c0a86b5aab8a3ea62d3c4d0eb5cd92 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:25:50 +0000 Subject: SAGA: Fix bug #2886130. Bug #2886130: "ITE: Graphic Glitches during Cat Tribe Celebration". We redraw statusbar for this scene. Bug in original. svn-id: r49726 --- engines/saga/render.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/saga/render.cpp b/engines/saga/render.cpp index ec168d296e..dc9334b037 100644 --- a/engines/saga/render.cpp +++ b/engines/saga/render.cpp @@ -110,6 +110,12 @@ void Render::drawScene() { _vm->_actor->drawActors(); } + // WORKAROUND + // Bug #2886130: "ITE: Graphic Glitches during Cat Tribe Celebration" + if (_vm->_scene->currentSceneNumber() == 274) { + _vm->_interface->drawStatusBar(); + } + #ifdef SAGA_DEBUG if (getFlags() & RF_OBJECTMAP_TEST) { if (_vm->_scene->_objectMap) -- cgit v1.2.3 From 51c22b39c86426b7f303d4d4f4d797e19bd63dbf Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:26:10 +0000 Subject: SAGA: Fix bug #2928923. Bug #2928923: 'ITE: Graphic Glitches during racoon death "Cut Scene"'. Disable actor drawing for these scenes. A long standing bug in original. svn-id: r49727 --- engines/saga/actor.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/saga/actor.cpp b/engines/saga/actor.cpp index c3f5fec83a..8bc8025032 100644 --- a/engines/saga/actor.cpp +++ b/engines/saga/actor.cpp @@ -1173,7 +1173,9 @@ void Actor::drawActors() { return; } - if (_vm->_anim->hasCutaway()) { + // WORKAROUND + // Bug #2928923: 'ITE: Graphic Glitches during racoon death "Cut Scene"' + if (_vm->_anim->hasCutaway() || _vm->_scene->currentSceneNumber() == 287 || _vm->_scene->currentSceneNumber() == 286) { drawSpeech(); return; } -- cgit v1.2.3 From fa2b0a0dd20afa55d133ba3aece36148d98cd15c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:26:29 +0000 Subject: SAGA: Fix bug #2827504. Bug #2827504: "ITE: Music restarts on every background change in credits". We errorneously were stopping music on each scene, though it appeared only with Adlib music. svn-id: r49728 --- engines/saga/events.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/saga/events.cpp b/engines/saga/events.cpp index d15f0b2af3..1f4091d07c 100644 --- a/engines/saga/events.cpp +++ b/engines/saga/events.cpp @@ -306,7 +306,6 @@ int Events::handleOneShot(Event *event) { _vm->_sndRes->playVoice(event->param); break; case kMusicEvent: - _vm->_music->stop(); if (event->op == kEventPlay) _vm->_music->play(event->param, (MusicFlags)event->param2); break; -- cgit v1.2.3 From 4046cd84571694c66f19b9fe0215a284a7d14357 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:26:46 +0000 Subject: AGI: debugger. Improved usage output, added safeguards to runopcode command svn-id: r49729 --- engines/agi/console.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index a0621f80dd..c7396f47b2 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -64,7 +64,7 @@ void Console::postEnter() { bool Console::Cmd_SetVar(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar "); + DebugPrintf("Usage: setvar \n"); return true; } int p1 = (int)atoi(argv[1]); @@ -76,7 +76,7 @@ bool Console::Cmd_SetVar(int argc, const char **argv) { bool Console::Cmd_SetFlag(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar "); + DebugPrintf("Usage: setvar \n"); return true; } int p1 = (int)atoi(argv[1]); @@ -88,7 +88,7 @@ bool Console::Cmd_SetFlag(int argc, const char **argv) { bool Console::Cmd_SetObj(int argc, const char **argv) { if (argc != 3) { - DebugPrintf("Usage: setvar "); + DebugPrintf("Usage: setvar \n"); return true; } int p1 = (int)atoi(argv[1]); @@ -99,6 +99,11 @@ bool Console::Cmd_SetObj(int argc, const char **argv) { } bool Console::Cmd_RunOpcode(int argc, const char **argv) { + if (argc < 2) { + DebugPrintf("Usage: runopcode ....\n"); + return true; + } + for (int i = 0; logicNamesCmd[i].name; i++) { if (!strcmp(argv[1], logicNamesCmd[i].name)) { uint8 p[16]; @@ -120,6 +125,8 @@ bool Console::Cmd_RunOpcode(int argc, const char **argv) { } } + DebugPrintf("Unknown opcode\n"); + return true; } -- cgit v1.2.3 From 1c1fb7c9acb77d552e51d7f41d91fadb35c63ee1 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:27:04 +0000 Subject: AGI: add optional parameter to 'room' debug console command. svn-id: r49730 --- engines/agi/console.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/agi/console.cpp b/engines/agi/console.cpp index c7396f47b2..e881b092e3 100644 --- a/engines/agi/console.cpp +++ b/engines/agi/console.cpp @@ -250,6 +250,10 @@ bool Console::Cmd_Cont(int argc, const char **argv) { } bool Console::Cmd_Room(int argc, const char **argv) { + if (argc == 2) { + _vm->newRoom(strtoul(argv[1], NULL, 0)); + } + DebugPrintf("Current room: %d\n", _vm->getvar(0)); return true; -- cgit v1.2.3 From 14205bdbc0aaeea34824c8f2dc43ec273955c7fd Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:27:23 +0000 Subject: AGI: add more status-related debug output. svn-id: r49731 --- engines/agi/keyboard.cpp | 2 +- engines/agi/text.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 2bea49a807..e0e1bca045 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -320,7 +320,7 @@ void AgiEngine::handleKeys(int key) { // Clear to start a new line _game.hasPrompt = 0; _game.inputBuffer[_game.cursorPos = 0] = 0; - debugC(3, kDebugLevelInput, "clear lines"); + debugC(3, kDebugLevelInput | kDebugLevelText, "clear lines"); clearLines(l, l + 1, bg); flushLines(l, l + 1); #ifdef __DS__ diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index ee9aebf240..5689b691a9 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -214,6 +214,7 @@ void AgiEngine::printTextConsole(const char *msg, int x, int y, int len, int fg, x *= CHAR_COLS; y *= 10; + debugC(4, kDebugLevelText, "printTextConsole(): %s, %d, %d, %d, %d, %d", msg, x, y, len, fg, bg); printText2(1, msg, 0, x, y, len, fg, bg); } @@ -699,6 +700,8 @@ void AgiEngine::clearLines(int l1, int l2, int c) { // inc for endline so it matches the correct num // ie, from 22 to 24 is 3 lines, not 2 lines. + debugC(4, kDebugLevelText, "clearLines(%d, %d, %d)", l1, l2, c); + l1 *= CHAR_LINES; l2 *= CHAR_LINES; l2 += CHAR_LINES - 1; -- cgit v1.2.3 From 316e171e67ddf01f9ae36b06c075b7d2ea46ad3c Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:27:42 +0000 Subject: AGI: Fix bug #2959630. Bug #2959630: "LSL1: Security in blackjack" fixed by partially reverting r41241. Do not clear prompt without on disabling input. svn-id: r49732 --- engines/agi/text.cpp | 5 +---- 1 file changed, 1 insertion(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 5689b691a9..f656abfa0c 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -656,11 +656,8 @@ void AgiEngine::writePrompt() { int l, fg, bg, pos; int promptLength = strlen(agiSprintf(_game.strings[0])); - if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) { - clearPrompt(); - + if (!_game.inputEnabled || _game.inputMode != INPUT_NORMAL) return; - } l = _game.lineUserInput; fg = _game.colorFg; -- cgit v1.2.3 From 4c617e8282dedf2f3c5d8c344851310665cc0be5 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:28:01 +0000 Subject: AGI: Fixed named fanmade games detection. svn-id: r49733 --- engines/agi/detection_tables.h | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index 96cb12cdd2..8ec3bb031b 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -80,12 +80,12 @@ using Common::GUIO_NONE; #define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) -#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) +#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPN(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) -#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) -#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) +#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_SVP(name,md5,size,ver,platform) GAME_LVFPNF("agi-fanmade",name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) -#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) +#define FANMADE_LVF(name,md5,lang,ver,features) GAME_LVFPNF("agi-fanmade",name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) #define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) #define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) -- cgit v1.2.3 From 968f959158ced8c1820b847e4c2b3a85d82d6e61 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:28:21 +0000 Subject: AGI: Fix bug #2960567. Bug #2960567: "AGI: Ego partly erased in Load/Save thumbnails". Force screen redraw after confirmation window is closed. svn-id: r49734 --- engines/agi/saveload.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index b7e830dc53..88e279ecf8 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -864,6 +864,10 @@ int AgiEngine::saveGameDialog() { sprintf(fileName, "%s", getSavegameFilename(_firstSlot + slot)); debugC(8, kDebugLevelMain | kDebugLevelResources, "file is [%s]", fileName); + // Make sure all graphics was blitted to screen. This fixes bug + // #2960567: "AGI: Ego partly erased in Load/Save thumbnails" + _gfx->doUpdate(); + int result = saveGame(fileName, desc); if (result == errOK) -- cgit v1.2.3 From 4dddfd44ceb8de712e51e83738f897ea9f9d3444 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:28:40 +0000 Subject: AGI: Fix bug #2960584. Bug #2960584: "AGI: (Fan) SQ0: Music lost on saving (and loading)". Actually music did not loop at all. Our looping code was broken. svn-id: r49735 --- engines/agi/sound.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index ca5d42d981..1b76b1ee40 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -411,6 +411,8 @@ void SoundMgr::stopSound() { debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); + _vm->setflag(_endflag, true); + _endflag = -1; if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { for (i = 0; i < NUM_CHANNELS; i++) -- cgit v1.2.3 From a993e2fb45dd836efad3bc225f7186a4f48384fe Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:28:58 +0000 Subject: AGI: Fix bug #2960563. Bug #2960563: "AGI: (Fan) SQ0: Text input field overdraws Text window". Now our text wrapping code matches original. svn-id: r49736 --- engines/agi/text.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index f656abfa0c..36a289c47b 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -135,8 +135,8 @@ void AgiEngine::blitTextbox(const char *p, int y, int x, int len) { if (x == 0 && y == 0 && len == 0) x = y = -1; - if (len <= 0 || len >= 40) - len = 32; + if (len <= 0) + len = 30; xoff = x * CHAR_COLS; yoff = y * CHAR_LINES; -- cgit v1.2.3 From 25948606c46fdb841b961439023bb64ca542e461 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:29:20 +0000 Subject: AGI: Fix bug #2960557. Bug #2960557: "AGI: (Fan) SQ0 - Sprite (Ego) not erased". Added a workaround. Actually root cause is not yet clear. svn-id: r49737 --- engines/agi/agi.h | 5 +++-- engines/agi/detection_tables.h | 14 +++++++------- engines/agi/view.cpp | 5 ++++- 3 files changed, 14 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.h b/engines/agi/agi.h index fb9e204101..b00b0b3d7e 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -110,10 +110,11 @@ enum AgiGameID { GID_SQ2, GID_XMASCARD, GID_FANMADE, - GID_GETOUTTASQ, + GID_GETOUTTASQ, // Fanmade + GID_SQ0, // Fanmade GID_MICKEY, // PreAGI GID_WINNIE, // PreAGI - GID_TROLL // PreAGI + GID_TROLL // PreAGI }; } // End of namespace Agi diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index 8ec3bb031b..9c915b12f5 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -80,12 +80,12 @@ using Common::GUIO_NONE; #define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) -#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPN(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) +#define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) -#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) -#define FANMADE_SVP(name,md5,size,ver,platform) GAME_LVFPNF("agi-fanmade",name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_ISVP(id,name,md5,size,ver,platform) GAME_LVFPNF(id,name,"logdir",md5,size,Common::EN_ANY,ver,GF_FANMADE,GID_FANMADE,platform,GType_V2) +#define FANMADE_SVP(name,md5,size,ver,platform) FANMADE_ISVP("agi-fanmade",name,md5,size,ver,platform) -#define FANMADE_LVF(name,md5,lang,ver,features) GAME_LVFPNF("agi-fanmade",name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) +#define FANMADE_LVF(name,md5,lang,ver,features) FANMADE_ILVF("agi-fanmade",name,md5,lang,ver,features) #define FANMADE_LF(name,md5,lang,features) FANMADE_LVF(name,md5,lang,0x2917,features) #define FANMADE_IF(id,name,md5,features) FANMADE_ILVF(id,name,md5,Common::EN_ANY,0x2917,features) @@ -775,9 +775,9 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), - FANMADE_I("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590"), - FANMADE_I("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6"), - FANMADE_ISVP("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, Common::kPlatformCoCo3), + GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_SQ0), + GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_SQ0), + GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_SQ0, Common::kPlatformCoCo3), FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index fb417e86a9..b506c1ecab 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -297,14 +297,17 @@ void AgiEngine::setView(VtEntry *v, int n) { uint16 viewFlags = 0; + // WORKAROUND // When setting a view to the view table, if there's already another view set in that // view table entry and it's still drawn, erase the existing view before setting the new one // Fixes bug #1658643: AGI: SQ1 (2.2 DOS ENG) Graphic error, ego leaves behind copy // Update: Apparently, this makes ego dissapear at times, e.g. when textboxes are shown // Therefore, it's limited to view 118 in SQ1 (Roger climbing the ladder) // Fixes bug #1715284: Roger sometimes disappears + // Update: Added case fot bug #2960557: AGI: (Fan) SQ0 - Sprite (Ego) not erased if (v->viewData != NULL) { - if (v->currentView == 118 && v->flags & DRAWN && getGameID() == GID_SQ1) { + if (((v->currentView == 118 && getGameID() == GID_SQ1) || + (v->currentView == 2 & (n == 254 || n == 255) && getGameID() == GID_SQ0)) && v->flags & DRAWN) { viewFlags = v->flags; // Store the flags for the view _sprites->eraseUpdSprites(); -- cgit v1.2.3 From 341fba383e8493e214c9e74c67cf3de0467c3e6a Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:29:43 +0000 Subject: AGI: Fix bug #2862508. Bug #2862508: "AGI: Black cauldron save through GMM". BC does not have input line, and that was used for determining that user can save. Added special case for BC, so it is always allowed to save. In fact, original does not allow saving in some rare occasions, but that will require analysing of variables, which is a gross hack. svn-id: r49738 --- engines/agi/detection.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index fa21925b78..a809d24467 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -488,6 +488,9 @@ bool AgiBase::canLoadGameStateCurrently() { } bool AgiBase::canSaveGameStateCurrently() { + if (getGameID() == GID_BC) // Technically in Black Cauldron we may save anytime + return true; + return (!(getGameType() == GType_PreAGI) && getflag(fMenusWork) && !_noSaveLoadAllowed && _game.inputEnabled); } -- cgit v1.2.3 From 409fe0bd561e75b7312e4143b5e9c3803322430e Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:30:01 +0000 Subject: AGI: made sprite-related debug output more informative svn-id: r49739 --- engines/agi/sprite.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 63ac880267..26aa100d2a 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -452,7 +452,7 @@ void SpritesMgr::blitSprites(SpriteList& l) { Sprite *s = *iter; objsSaveArea(s); - debugC(8, kDebugLevelSprites, "s->v->entry = %d (prio %d)", s->v->entry, s->v->priority); + debugC(8, kDebugLevelSprites, "blitSprites(): s->v->entry = %d (prio %d)", s->v->entry, s->v->priority); hidden = blitCel(s->xPos, s->yPos, s->v->priority, s->v->celData, s->v->viewData->agi256_2); if (s->v->entry == 0) { // if ego, update f1 @@ -528,7 +528,7 @@ void SpritesMgr::eraseBoth() { * @see blit_both() */ void SpritesMgr::blitUpdSprites() { - debugC(7, kDebugLevelSprites, "blit updating"); + debugC(7, kDebugLevelSprites, "blitUpdSprites()"); buildUpdBlitlist(); blitSprites(_sprUpd); } @@ -542,7 +542,7 @@ void SpritesMgr::blitUpdSprites() { * @see blit_both() */ void SpritesMgr::blitNonupdSprites() { - debugC(7, kDebugLevelSprites, "blit non-updating"); + debugC(7, kDebugLevelSprites, "blitNonupdSprites()"); buildNonupdBlitlist(); blitSprites(_sprNonupd); } @@ -578,7 +578,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in int x1, y1, x2, y2, y3; uint8 *p1, *p2; - debugC(3, kDebugLevelSprites, "v=%d, l=%d, c=%d, x=%d, y=%d, p=%d, m=%d", view, loop, cel, x, y, pri, mar); + debugC(3, kDebugLevelSprites, "addToPic(view=%d, loop=%d, cel=%d, x=%d, y=%d, pri=%d, mar=%d)", view, loop, cel, x, y, pri, mar); _vm->recordImageStackCall(ADD_VIEW, view, loop, cel, x, y, pri, mar); @@ -609,7 +609,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in eraseBoth(); - debugC(4, kDebugLevelSprites, "blit_cel (%d, %d, %d, c)", x, y, pri); + debugC(4, kDebugLevelSprites, "blitCel(%d, %d, %d, c)", x, y, pri); blitCel(x1, y1, pri, c, _vm->_game.views[view].agi256_2); // If margin is 0, 1, 2, or 3, the base of the cel is @@ -659,7 +659,6 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in blitBoth(); - debugC(4, kDebugLevelSprites, "commit_block (%d, %d, %d, %d)", x1, y1, x2, y2); commitBlock(x1, y1, x2, y2); } @@ -711,7 +710,7 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { y1 = CLIP(y1, 0, _HEIGHT - 1); y2 = CLIP(y2, 0, _HEIGHT - 1); - debugC(7, kDebugLevelSprites, "%d, %d, %d, %d", x1, y1, x2, y2); + debugC(7, kDebugLevelSprites, "commitBlock(%d, %d, %d, %d)", x1, y1, x2, y2); w = x2 - x1 + 1; q = &_vm->_game.sbuf16c[x1 + _WIDTH * y1]; -- cgit v1.2.3 From 295edafdc4b266a7283ba494e685dfb22f132c6a Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:30:26 +0000 Subject: AGI: improve script-related debug output. svn-id: r49740 --- engines/agi/op_cmd.cpp | 27 +++++++++++++-------------- engines/agi/sprite.cpp | 2 ++ 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index d7e3ba416c..f31e1d156d 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -209,47 +209,38 @@ cmd(object_on_anything) { } cmd(object_on_land) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags |= ON_LAND; } cmd(object_on_water) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags |= ON_WATER; } cmd(observe_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags &= ~IGNORE_HORIZON; } cmd(ignore_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags |= IGNORE_HORIZON; } cmd(observe_objs) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags &= ~IGNORE_OBJECTS; } cmd(ignore_objs) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags |= IGNORE_OBJECTS; } cmd(observe_blocks) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags &= ~IGNORE_BLOCKS; } cmd(ignore_blocks) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); vt.flags |= IGNORE_BLOCKS; } cmd(set_horizon) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); game.horizon = p0; } @@ -328,7 +319,6 @@ cmd(set_cel_f) { } cmd(set_view) { - debugC(4, kDebugLevelScripts, "o%d, %d", p0, p1); g_agi->setView(&vt, p1); } @@ -423,12 +413,10 @@ cmd(word_to_string) { } cmd(open_dialogue) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); game.hasWindow = true; } cmd(close_dialogue) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); game.hasWindow = false; } @@ -1438,7 +1426,6 @@ cmd(display) { } cmd(display_f) { - debugC(4, kDebugLevelScripts, "p0 = %d", p0); g_agi->printText(curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, game.colorFg, game.colorBg); } @@ -1781,6 +1768,9 @@ int AgiEngine::runLogic(int n) { int num = 0; ScriptPos sp; + debugC(2, kDebugLevelScripts, "================="); + debugC(2, kDebugLevelScripts, "runLogic(%d)", n); + sp.script = n; sp.curIP = 0; _game.execStack.push_back(sp); @@ -1816,6 +1806,11 @@ int AgiEngine::runLogic(int n) { _game.execStack.back().curIP = ip; + char st[101]; + int sz = MIN(_game.execStack.size(), 100u); + memset(st, '.', sz); + st[sz] = 0; + switch (op = *(code + ip++)) { case 0xff: // if (open/close) testIfCode(n); @@ -1833,6 +1828,9 @@ int AgiEngine::runLogic(int n) { } break; case 0x00: // return + debugC(2, kDebugLevelScripts, "%sreturn() // Logic %d", st, n); + debugC(2, kDebugLevelScripts, "================="); + _game.execStack.pop_back(); return 1; default: @@ -1840,7 +1838,8 @@ int AgiEngine::runLogic(int n) { memmove(p, code + ip, num); memset(p + num, 0, CMD_BSIZE - num); - debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]); + debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]); + agiCommand[op](this, p); ip += num; } diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 26aa100d2a..70cc279420 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -332,6 +332,8 @@ void SpritesMgr::buildList(SpriteList &l, bool (*test)(VtEntry *, AgiEngine *)) } } + debugC(5, kDebugLevelSprites, "buildList() --> entries %d", i); + // now look for the smallest y value in the array and put that // sprite in the list for (j = 0; j < i; j++) { -- cgit v1.2.3 From 7034d071b6f44fb77f3379535f146a095357c5be Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:30:54 +0000 Subject: AGI: proper fix for sprite leftover-related bugs. Removed workarounds. svn-id: r49741 --- engines/agi/op_cmd.cpp | 23 ++++++++++++++++++++++- engines/agi/sprite.cpp | 8 ++------ engines/agi/view.cpp | 31 ------------------------------- 3 files changed, 24 insertions(+), 38 deletions(-) (limited to 'engines') diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index f31e1d156d..fb95c1cee1 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -889,7 +889,28 @@ cmd(erase) { } g_sprites->blitUpdSprites(); - g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos); + int x1, y1, x2, y2, w, h; + + w = MAX(vt.celData->width, vt.celData2->width); + h = MAX(vt.celData->height, vt.celData2->height); + + if (vt.xPos < vt.xPos2) { + x1 = vt.xPos; + x2 = vt.xPos2 + w - 1; + } else { + x1 = vt.xPos2; + x2 = vt.xPos + w - 1; + } + + if (vt.yPos < vt.yPos2) { + y1 = vt.yPos - h + 1; + y2 = vt.yPos2; + } else { + y1 = vt.yPos2 - h + 1; + y2 = vt.yPos; + } + + g_sprites->commitBlock(x1, y1, x2, y2); } cmd(position) { diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 70cc279420..10184fcaa4 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -389,12 +389,8 @@ void SpritesMgr::commitSprites(SpriteList &l) { Sprite *s = *iter; int x1, y1, x2, y2, w, h; - w = (s->v->celData->width > s->v->celData2->width) ? - s->v->celData->width : s->v->celData2->width; - - h = (s->v->celData->height > - s->v->celData2->height) ? s->v->celData-> - height : s->v->celData2->height; + w = MAX(s->v->celData->width, s->v->celData2->width); + h = MAX(s->v->celData->height, s->v->celData2->height); s->v->celData2 = s->v->celData; diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index b506c1ecab..a775b5f78b 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -294,37 +294,6 @@ void AgiEngine::setLoop(VtEntry *v, int n) { * @param n number of AGI view resource */ void AgiEngine::setView(VtEntry *v, int n) { - - uint16 viewFlags = 0; - - // WORKAROUND - // When setting a view to the view table, if there's already another view set in that - // view table entry and it's still drawn, erase the existing view before setting the new one - // Fixes bug #1658643: AGI: SQ1 (2.2 DOS ENG) Graphic error, ego leaves behind copy - // Update: Apparently, this makes ego dissapear at times, e.g. when textboxes are shown - // Therefore, it's limited to view 118 in SQ1 (Roger climbing the ladder) - // Fixes bug #1715284: Roger sometimes disappears - // Update: Added case fot bug #2960557: AGI: (Fan) SQ0 - Sprite (Ego) not erased - if (v->viewData != NULL) { - if (((v->currentView == 118 && getGameID() == GID_SQ1) || - (v->currentView == 2 & (n == 254 || n == 255) && getGameID() == GID_SQ0)) && v->flags & DRAWN) { - viewFlags = v->flags; // Store the flags for the view - _sprites->eraseUpdSprites(); - - if (v->flags & UPDATE) { - v->flags &= ~DRAWN; - } else { - _sprites->eraseNonupdSprites(); - v->flags &= ~DRAWN; - _sprites->blitNonupdSprites(); - } - _sprites->blitUpdSprites(); - - _sprites->commitBlock(v->xPos, v->yPos - v->ySize + 1, v->xPos + v->xSize - 1, v->yPos); - v->flags = viewFlags; // Restore the view's flags - } - } - v->viewData = &_game.views[n]; v->currentView = n; v->numLoops = v->viewData->numLoops; -- cgit v1.2.3 From ffc390e64c1adc8bd863ecd0bfe72ff7ecba6832 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:31:18 +0000 Subject: AGI: Fix bug #1945716. Bug #1945716: "AGI: Fan(Kings Quest 2 1/4) - Sprite not erased". Added a workaround, since it is design flaw of our rendering system. svn-id: r49742 --- engines/agi/op_cmd.cpp | 24 +++++------------------- engines/agi/sprite.cpp | 32 +++++++++++++------------------- engines/agi/view.cpp | 1 + engines/agi/view.h | 1 + 4 files changed, 20 insertions(+), 38 deletions(-) (limited to 'engines') diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index fb95c1cee1..bb0799d92c 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -889,26 +889,12 @@ cmd(erase) { } g_sprites->blitUpdSprites(); - int x1, y1, x2, y2, w, h; + int x1, y1, x2, y2; - w = MAX(vt.celData->width, vt.celData2->width); - h = MAX(vt.celData->height, vt.celData2->height); - - if (vt.xPos < vt.xPos2) { - x1 = vt.xPos; - x2 = vt.xPos2 + w - 1; - } else { - x1 = vt.xPos2; - x2 = vt.xPos + w - 1; - } - - if (vt.yPos < vt.yPos2) { - y1 = vt.yPos - h + 1; - y2 = vt.yPos2; - } else { - y1 = vt.yPos2 - h + 1; - y2 = vt.yPos; - } + x1 = MIN((int)MIN(vt.xPos, vt.xPos2), MIN(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width)); + x2 = MAX((int)MAX(vt.xPos, vt.xPos2), MAX(vt.xPos + vt.celData->width, vt.xPos2 + vt.celData2->width)); + y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); + y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); g_sprites->commitBlock(x1, y1, x2, y2); } diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 10184fcaa4..611dd16478 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -241,6 +241,14 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { q += xSize; pos0 += _WIDTH; } + + // WORKAROUND + // When set.view command is called, current code cannot detect this situation while updating + // Thus we force removal of the old sprite + if (s->v->viewReplaced) { + commitBlock(xPos, yPos, xPos + xSize, yPos + ySize); + s->v->viewReplaced = false; + } } @@ -387,29 +395,15 @@ void SpritesMgr::commitSprites(SpriteList &l) { SpriteList::iterator iter; for (iter = l.begin(); iter != l.end(); ++iter) { Sprite *s = *iter; - int x1, y1, x2, y2, w, h; + int x1, y1, x2, y2; - w = MAX(s->v->celData->width, s->v->celData2->width); - h = MAX(s->v->celData->height, s->v->celData2->height); + x1 = MIN((int)MIN(s->v->xPos, s->v->xPos2), MIN(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width)); + x2 = MAX((int)MAX(s->v->xPos, s->v->xPos2), MAX(s->v->xPos + s->v->celData->width, s->v->xPos2 + s->v->celData2->width)); + y1 = MIN((int)MIN(s->v->yPos, s->v->yPos2), MIN(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height)); + y2 = MAX((int)MAX(s->v->yPos, s->v->yPos2), MAX(s->v->yPos - s->v->celData->height, s->v->yPos2 - s->v->celData2->height)); s->v->celData2 = s->v->celData; - if (s->v->xPos < s->v->xPos2) { - x1 = s->v->xPos; - x2 = s->v->xPos2 + w - 1; - } else { - x1 = s->v->xPos2; - x2 = s->v->xPos + w - 1; - } - - if (s->v->yPos < s->v->yPos2) { - y1 = s->v->yPos - h + 1; - y2 = s->v->yPos2; - } else { - y1 = s->v->yPos2 - h + 1; - y2 = s->v->yPos; - } - commitBlock(x1, y1, x2, y2); if (s->v->stepTimeCount != s->v->stepTime) diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index a775b5f78b..b89ab3915c 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -297,6 +297,7 @@ void AgiEngine::setView(VtEntry *v, int n) { v->viewData = &_game.views[n]; v->currentView = n; v->numLoops = v->viewData->numLoops; + v->viewReplaced = true; setLoop(v, v->currentLoop >= v->numLoops ? 0 : v->currentLoop); } diff --git a/engines/agi/view.h b/engines/agi/view.h index f9017ec4ae..85f2d6eaf9 100644 --- a/engines/agi/view.h +++ b/engines/agi/view.h @@ -63,6 +63,7 @@ struct VtEntry { int16 xPos; int16 yPos; uint8 currentView; + bool viewReplaced; struct AgiView *viewData; uint8 currentLoop; uint8 numLoops; -- cgit v1.2.3 From 83053ecc27905bc60cdeea2cbfc9f9550764579b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:31:39 +0000 Subject: AGI: Fix bug #2825278. Bug #2825278: "AGI: KQ4: Swimming on land". Our drawing code was not picture perfect, and thus priority screen was trashed by one of Fills, i.e. the color leaked and took whole screen. svn-id: r49743 --- engines/agi/loader_v3.cpp | 16 ++++------------ engines/agi/picture.cpp | 14 ++++++++------ 2 files changed, 12 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index cd97c44521..4227745c5f 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -227,19 +227,12 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { compBuffer = (uint8 *)calloc(1, agid->clen + 32); fp.read(compBuffer, agid->clen); - if (x[2] & 0x80 || agid->len == agid->clen) { + if (x[2] & 0x80) { // compressed pic + data = _vm->_picture->convertV3Pic(compBuffer, agid->clen); + free(compBuffer); + } else if (agid->len == agid->clen) { // do not decompress data = compBuffer; - -#if 0 - // CM: added to avoid problems in - // convert_v2_v3_pic() when clen > len - // e.g. Sierra demo 4, first picture - // (Tue Mar 16 13:13:43 EST 1999) - agid->len = agid->clen; - - // Now removed to fix Gold Rush! in demo4 -#endif } else { // it is compressed data = (uint8 *)calloc(1, agid->len + 32); @@ -309,7 +302,6 @@ int AgiLoader_v3::loadResource(int t, int n) { unloadResource(rPICTURE, n); data = loadVolRes(&_vm->_game.dirPic[n]); if (data != NULL) { - data = _vm->_picture->convertV3Pic(data, _vm->_game.dirPic[n].len); _vm->_game.pictures[n].rdata = data; _vm->_game.dirPic[n].flags |= RES_LOADED; } else { diff --git a/engines/agi/picture.cpp b/engines/agi/picture.cpp index 60877de430..dc77433cb2 100644 --- a/engines/agi/picture.cpp +++ b/engines/agi/picture.cpp @@ -476,7 +476,7 @@ void PictureMgr::plotPattern(int x, int y) { // new purpose for temp16 - temp16 =( pen_size<<1) +1; // pen size + temp16 = (pen_size << 1) + 1; // pen size pen_final_y += temp16; // the last row of this shape temp16 = temp16 << 1; pen_width = temp16; // width of shape? @@ -495,7 +495,7 @@ void PictureMgr::plotPattern(int x, int y) { } else { circleCond = ((_patCode & 0x10) != 0); counterStep = 4; - ditherCond = 0x02; + ditherCond = 0x01; } for (; pen_y < pen_final_y; pen_y++) { @@ -503,10 +503,12 @@ void PictureMgr::plotPattern(int x, int y) { for (counter = 0; counter <= pen_width; counter += counterStep) { if (circleCond || ((binary_list[counter>>1] & circle_word) != 0)) { - temp8 = t % 2; - t = t >> 1; - if (temp8 != 0) - t = t ^ 0xB8; + if ((_patCode & 0x20) != 0) { + temp8 = t % 2; + t = t >> 1; + if (temp8 != 0) + t = t ^ 0xB8; + } // == box plot, != circle plot if ((_patCode & 0x20) == 0 || (t & 0x03) == ditherCond) -- cgit v1.2.3 From 462d1afed8ffbc9a018d07d0c0b280af448e7b52 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:32:01 +0000 Subject: AGI: Fix bug #1875842. Bug #1875842: "AGI: Character loses final walking position". Do not reset ADJ_EGO_XY if non-directional keys were pressed. svn-id: r49744 --- engines/agi/keyboard.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index e0e1bca045..056df8f026 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -191,9 +191,8 @@ int AgiEngine::handleController(int key) { } } - v->flags &= ~ADJ_EGO_XY; - if (d || key == KEY_STATIONARY) { + v->flags &= ~ADJ_EGO_XY; v->direction = v->direction == d ? 0 : d; return true; } -- cgit v1.2.3 From 88421532aa2fc34fda1a940a4ba994f96e324574 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:32:25 +0000 Subject: AGI: Implemented immediate update for most of gfx to match original. This fixes many subtle effects as in many cases there were no special pausing and engine relied only on the slowliness of the machine. svn-id: r49745 --- engines/agi/op_cmd.cpp | 7 +++++-- engines/agi/sprite.cpp | 19 +++++++++++-------- engines/agi/sprite.h | 4 ++-- engines/agi/view.cpp | 2 ++ 4 files changed, 20 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index bb0799d92c..ab7e5010e7 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -741,6 +741,7 @@ cmd(draw_pic) { g_sprites->eraseBoth(); g_picture->decodePicture(_v[p0], true); g_sprites->blitBoth(); + g_sprites->commitBoth(); game.pictureShown = 0; debugC(6, kDebugLevelScripts, "--- end of draw pic %d ---", _v[p0]); @@ -778,6 +779,7 @@ cmd(load_pic) { g_sprites->eraseBoth(); g_agi->agiLoadResource(rPICTURE, _v[p0]); g_sprites->blitBoth(); + g_sprites->commitBoth(); } cmd(discard_pic) { @@ -869,7 +871,7 @@ cmd(draw) { g_sprites->blitUpdSprites(); vt.flags &= ~DONTUPDATE; - g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos); + g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true); debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags); } @@ -896,7 +898,7 @@ cmd(erase) { y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); - g_sprites->commitBlock(x1, y1, x2, y2); + g_sprites->commitBlock(x1, y1, x2, y2, true); } cmd(position) { @@ -1804,6 +1806,7 @@ int AgiEngine::runLogic(int n) { } } else { _sprites->blitBoth(); + _sprites->commitBoth(); do { mainCycle(); } while (!_debug.steps && _debug.enabled); diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index 611dd16478..d3bd1a6212 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -391,7 +391,7 @@ void SpritesMgr::freeList(SpriteList &l) { * Copy sprites from the pic buffer to the screen buffer, and check if * sprites of the given list have moved. */ -void SpritesMgr::commitSprites(SpriteList &l) { +void SpritesMgr::commitSprites(SpriteList &l, bool immediate) { SpriteList::iterator iter; for (iter = l.begin(); iter != l.end(); ++iter) { Sprite *s = *iter; @@ -404,7 +404,7 @@ void SpritesMgr::commitSprites(SpriteList &l) { s->v->celData2 = s->v->celData; - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, immediate); if (s->v->stepTimeCount != s->v->stepTime) continue; @@ -458,11 +458,11 @@ void SpritesMgr::blitSprites(SpriteList& l) { */ void SpritesMgr::commitUpdSprites() { - commitSprites(_sprUpd); + commitSprites(_sprUpd, true); } void SpritesMgr::commitNonupdSprites() { - commitSprites(_sprNonupd); + commitSprites(_sprNonupd, true); } // check moves in both lists @@ -651,7 +651,7 @@ void SpritesMgr::addToPic(int view, int loop, int cel, int x, int y, int pri, in blitBoth(); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); } /** @@ -682,15 +682,15 @@ void SpritesMgr::showObj(int n) { objsSaveArea(&s); blitCel(x1, y1, 15, c, _vm->_game.views[n].agi256_2); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); _vm->messageBox(_vm->_game.views[n].descr); objsRestoreArea(&s); - commitBlock(x1, y1, x2, y2); + commitBlock(x1, y1, x2, y2, true); free(s.buffer); } -void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { +void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2, bool immediate) { int i, w, offset; uint8 *q; @@ -714,6 +714,9 @@ void SpritesMgr::commitBlock(int x1, int y1, int x2, int y2) { } _gfx->flushBlockA(x1, y1 + offset, x2, y2 + offset); + + if (immediate) + _gfx->doUpdate(); } SpritesMgr::SpritesMgr(AgiEngine *agi, GfxMgr *gfx) { diff --git a/engines/agi/sprite.h b/engines/agi/sprite.h index 7d6d7bb97e..57fd0dacf2 100644 --- a/engines/agi/sprite.h +++ b/engines/agi/sprite.h @@ -65,7 +65,7 @@ private: void buildUpdBlitlist(); void buildNonupdBlitlist(); void freeList(SpriteList &l); - void commitSprites(SpriteList &l); + void commitSprites(SpriteList &l, bool immediate = false); void eraseSprites(SpriteList &l); void blitSprites(SpriteList &l); static bool testUpdating(VtEntry *v, AgiEngine *); @@ -88,7 +88,7 @@ public: void commitBoth(); void addToPic(int, int, int, int, int, int, int); void showObj(int); - void commitBlock(int, int, int, int); + void commitBlock(int x1, int y1, int x2, int y2, bool immediate = false); }; } // End of namespace Agi diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index b89ab3915c..cd3584dcae 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -311,6 +311,7 @@ void AgiEngine::startUpdate(VtEntry *v) { v->flags |= UPDATE; _sprites->blitBoth(); + _sprites->commitBoth(); } } @@ -324,6 +325,7 @@ void AgiEngine::stopUpdate(VtEntry *v) { v->flags &= ~UPDATE; _sprites->blitBoth(); + _sprites->commitBoth(); } } -- cgit v1.2.3 From 81870dba5804b776044f89112976d0110b5c0695 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:32:44 +0000 Subject: AGI: Fix bug #2825273. Bug #2825273: "AGI: KQ4: Dwarf sequence". Always allow ESC to work in KQ4. svn-id: r49746 --- engines/agi/keyboard.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index 056df8f026..f99d5728be 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -104,10 +104,10 @@ int AgiEngine::handleController(int key) { VtEntry *v = &_game.viewTable[0]; int i; - // AGI 3.149 games and The Black Cauldron need KEY_ESCAPE to use menus + // AGI 3.149 games, The Black Cauldron and King's Quest 4 need KEY_ESCAPE to use menus // Games with the GF_ESCPAUSE flag need KEY_ESCAPE to pause the game if (key == 0 || - (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && !(getFeatures() & GF_ESCPAUSE)) ) + (key == KEY_ESCAPE && getVersion() != 0x3149 && getGameID() != GID_BC && getGameID() != GID_KQ4 && !(getFeatures() & GF_ESCPAUSE)) ) return false; if ((getGameID() == GID_MH1 || getGameID() == GID_MH2) && (key == KEY_ENTER) && -- cgit v1.2.3 From f7c830af26b8a7cac4b8a6864e161f614e0e9e06 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:33:07 +0000 Subject: AGI: Fix walking for some versions of KQ4. svn-id: r49747 --- engines/agi/view.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index cd3584dcae..03509e81f9 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -368,7 +368,7 @@ void AgiEngine::updateViewtable() { break; default: // for KQ4 - if (getVersion() == 0x3086) + if (getVersion() == 0x3086 || getGameId() == GID_KQ4) loop = loopTable4[v->direction]; break; } -- cgit v1.2.3 From 71917dc52daf2f2cbc2931f59c893c6c933fa2aa Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:33:26 +0000 Subject: AGI: Implement FR #1881179. FR #1881179: "AGI detecting agi mouse". Always run ScummVM in AGIMOUSE compatibility mode, thus no detection for it is needed. svn-id: r49748 --- engines/agi/cycle.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 10df40556f..5614195fcf 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -314,7 +314,8 @@ int AgiEngine::playGame() { _game.clockEnabled = true; _game.lineUserInput = 22; - if (getFeatures() & GF_AGIMOUSE) + // We run AGIMOUSE always as a side effect + if (getFeatures() & GF_AGIMOUSE || 1) report("Using AGI Mouse 1.0 protocol\n"); if (getFeatures() & GF_AGIPAL) -- cgit v1.2.3 From 38ef876d5beabb3f5e5d35690b5b14d6643e6aa3 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:33:57 +0000 Subject: AGI: Split out IIgs sound emulator into separate files. svn-id: r49749 --- engines/agi/module.mk | 1 + engines/agi/sound.cpp | 718 +------------------------------------------- engines/agi/sound.h | 282 +----------------- engines/agi/sound_2gs.cpp | 736 ++++++++++++++++++++++++++++++++++++++++++++++ engines/agi/sound_2gs.h | 311 ++++++++++++++++++++ 5 files changed, 1063 insertions(+), 985 deletions(-) create mode 100644 engines/agi/sound_2gs.cpp create mode 100644 engines/agi/sound_2gs.h (limited to 'engines') diff --git a/engines/agi/module.mk b/engines/agi/module.mk index f031834c9d..3b7741443d 100644 --- a/engines/agi/module.mk +++ b/engines/agi/module.mk @@ -30,6 +30,7 @@ MODULE_OBJS := \ predictive.o \ saveload.o \ sound.o \ + sound_2gs.o \ sprite.o \ text.o \ view.o \ diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index 1b76b1ee40..014a3dba1a 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -31,6 +31,8 @@ #include "agi/agi.h" +#include "agi/sound_2gs.h" + namespace Agi { #define USE_INTERPOLATION @@ -57,18 +59,6 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S return NULL; } -IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - _data = data; // Save the resource pointer - _ptr = _data + 2; // Set current position to just after the header - _len = len; // Save the resource's length - _type = READ_LE_UINT16(data); // Read sound resource's type - _midiTicks = _soundBufTicks = 0; - _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); -} - PCjrSound::PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { _data = data; // Save the resource pointer _len = len; // Save the resource's length @@ -86,208 +76,6 @@ const uint8 *PCjrSound::getVoicePointer(uint voiceNum) { return _data + voiceStartOffset; } -IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); - - // Check that the header was read ok and that it's of the correct type - if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource - uint32 sampleStartPos = stream.pos(); - uint32 tailLen = stream.size() - sampleStartPos; - - if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream - // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes - // of sample data although header says it should have 16384 bytes. - warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", - resnum, tailLen, _header.sampleSize); - - _header.sampleSize = (uint16) tailLen; // Use the part that's left - } - - if (_header.pitch > 0x7F) { // Check if the pitch is invalid - warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); - - _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too - } - - // Finalize the header info using the 8-bit unsigned sample data - _header.finalize(stream); - - // Convert sample data from 8-bit unsigned to 8-bit signed format - stream.seek(sampleStartPos); - _sample = new int8[_header.sampleSize]; - - if (_sample != NULL) - _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize); - } - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); -} - -/** Reads an Apple IIGS envelope from then given stream. */ -bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { - for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { - seg[segNum].bp = stream.readByte(); - seg[segNum].inc = stream.readUint16LE(); - } - - return !(stream.eos() || stream.err()); -} - -/** Reads an Apple IIGS wave information structure from the given stream. */ -bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - top = stream.readByte(); - addr = stream.readByte() * 256; - size = (1 << (stream.readByte() & 7)) * 256; - - // Read packed mode byte and parse it into parts - byte packedModeByte = stream.readByte(); - channel = (packedModeByte >> 4) & 1; // Bit 4 - mode = (packedModeByte >> 1) & 3; // Bits 1-2 - halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) - - relPitch = stream.readSint16LE(); - - // Zero the wave address if we want to ignore the wave address info - if (ignoreAddr) - addr = 0; - - return !(stream.eos() || stream.err()); -} - -bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { - uint32 startPos = uint8Wave.pos(); // Save stream's starting position - uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address - - // Calculate the true sample size (A zero ends the sample prematurely) - uint trueSize = size; // Set a default value for the result - for (uint i = 0; i < size; i++) { - if (uint8Wave.readByte() == 0) { - trueSize = i; - // A zero in the sample stream turns off looping - // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) - if (mode == OSC_MODE_LOOP) - mode = OSC_MODE_ONESHOT; - break; - } - } - size = trueSize; // Set the true sample size - - uint8Wave.seek(startPos); // Seek back to the stream's starting position - - return true; -} - -bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) - if (!waves[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { - // First read the A waves and then the B waves for the oscillators - for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) - for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) - if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) - return false; - - count = oscillatorCount; // Set the oscillator count - - return true; -} - -bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < count; i++) - if (!osc[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - env.read(stream); - relseg = stream.readByte(); - /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. - bendrange = stream.readByte(); - vibdepth = stream.readByte(); - vibspeed = stream.readByte(); - /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. - byte wac = stream.readByte(); // Read A wave count - byte wbc = stream.readByte(); // Read B wave count - oscList.read(stream, wac, ignoreAddr); // Read the oscillators - return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match -} - -bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return oscList.finalize(uint8Wave); -} - -bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { - type = stream.readUint16LE(); - pitch = stream.readByte(); - unknownByte_Ofs3 = stream.readByte(); - volume = stream.readByte(); - unknownByte_Ofs5 = stream.readByte(); - instrumentSize = stream.readUint16LE(); - sampleSize = stream.readUint16LE(); - // Read the instrument header *ignoring* its wave address info - - return instrument.read(stream, true); -} - -bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return instrument.finalize(uint8Wave); -} - -/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV1 = { - {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, - 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, - 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, - 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, - 25, 13, 13, 25}, - 5 -}; - -/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV2 = { - {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, - 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, - 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, - 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, - 27, 15, 15, 27}, - 6 -}; - -/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ -static const InstrumentSetInfo instSetV1 = { - 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 -}; - -/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ -static const InstrumentSetInfo instSetV2 = { - 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 -}; - -/** Information about different Apple IIGS AGI executables. */ -static const IIgsExeInfo IIgsExeInfos[] = { - {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, - {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, - {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, - {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, - {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, - {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, - {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, - {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, - {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, - {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, - {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, - {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, - {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} -}; - static const int16 waveformRamp[WAVEFORM_SIZE] = { 0, 8, 16, 24, 32, 40, 48, 56, 64, 72, 80, 88, 96, 104, 112, 120, @@ -370,7 +158,7 @@ void SoundMgr::startSound(int resnum, int flag) { switch (type) { case AGI_SOUND_SAMPLE: { IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; - _gsSound.playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); + _gsSound->playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); break; } case AGI_SOUND_MIDI: @@ -411,8 +199,6 @@ void SoundMgr::stopSound() { debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); - _vm->setflag(_endflag, true); - _endflag = -1; if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { for (i = 0; i < NUM_CHANNELS; i++) @@ -424,38 +210,13 @@ void SoundMgr::stopSound() { _vm->_game.sounds[_playingSound]->stop(); if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - _gsSound.stopSounds(); + _gsSound->stopSounds(); } _playingSound = -1; } } -void IIgsSoundMgr::stopSounds() { - // Stops all sounds on all MIDI channels - for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - iter->stopSounds(); -} - -bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { - stopSounds(); - IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; - - channel.setInstrument(&sampleHeader.instrument, sample); - channel.setVolume(sampleHeader.volume); - channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64) - - return true; -} - -void IIgsMidiChannel::stopSounds() { - // Stops all sounds on this single MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->stop(); - - _gsChannels.clear(); -} - int SoundMgr::initSound() { int r = -1; @@ -540,290 +301,6 @@ void SoundMgr::playNote(int i, int freq, int vol) { } } -void SoundMgr::playMidiSound() { - if (_disabledMidi) - return; - - const uint8 *p; - uint8 parm1, parm2; - static uint8 cmd, ch; - - if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { - warning("Error playing Apple IIGS MIDI sound resource"); - _playing = false; - - return; - } - - IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; - - _playing = true; - p = midiObj->getPtr(); - - midiObj->_soundBufTicks++; - - while (true) { - uint8 readByte = *p; - - // Check for end of MIDI sequence marker (Can also be here before delta-time) - if (readByte == MIDI_BYTE_STOP_SEQUENCE) { - debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); - _playing = false; - - midiObj->rewind(); - - return; - } else if (readByte == MIDI_BYTE_TIMER_SYNC) { - debugC(3, kDebugLevelSound, "Timer sync"); - p++; // Jump over the timer sync byte as it's not needed - - continue; - } - - uint8 deltaTime = readByte; - if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) { - break; - } - midiObj->_midiTicks += deltaTime; - p++; // Jump over the delta-time byte as it was already taken care of - - // Check for end of MIDI sequence marker (This time it after reading delta-time) - if (*p == MIDI_BYTE_STOP_SEQUENCE) { - debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); - _playing = false; - - midiObj->rewind(); - - return; - } - - // Separate byte into command and channel if it's a command byte. - // Otherwise use running status (i.e. previously set command and channel). - if (*p & 0x80) { - cmd = *p++; - ch = cmd & 0x0f; - cmd >>= 4; - } - - switch (cmd) { - case MIDI_CMD_NOTE_OFF: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiNoteOff(ch, parm1, parm2); - break; - case MIDI_CMD_NOTE_ON: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiNoteOn(ch, parm1, parm2); - break; - case MIDI_CMD_CONTROLLER: - parm1 = *p++; - parm2 = *p++; - _gsSound.midiController(ch, parm1, parm2); - break; - case MIDI_CMD_PROGRAM_CHANGE: - parm1 = *p++; - _gsSound.midiProgramChange(ch, parm1); - break; - case MIDI_CMD_PITCH_WHEEL: - parm1 = *p++; - parm2 = *p++; - - uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value - _gsSound.midiPitchWheel(wheelPos); - break; - } - } - - midiObj->setPtr(p); -} - -void IIgsSoundMgr::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { - _midiChannels[channel].noteOff(note, velocity); - debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity); -} - -void IIgsSoundMgr::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { - _midiChannels[channel].noteOn(note, velocity); - debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity); -} - -// TODO: Check if controllers behave differently on different MIDI channels -// TODO: Doublecheck what other controllers than the volume controller do -void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) { - IIgsMidiChannel &midiChannel = _midiChannels[channel]; - - // The tested Apple IIGS AGI MIDI resources only used - // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off). - // Controller 0's parameter was in range 94-127, - // controller 7's parameter was in range 0-127 and - // controller 64's parameter was always 0 (i.e. sustain off). - bool unimplemented = false; - switch (controller) { - case 7: // Volume - midiChannel.setVolume(value); - break; - default: - unimplemented = true; - break; - } - debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : ""); -} - -void IIgsSoundMgr::midiProgramChange(uint8 channel, uint8 program) { - _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin()); - debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel); -} - -void IIgsSoundMgr::midiPitchWheel(uint8 wheelPos) { - // In all the tested Apple IIGS AGI MIDI resources - // pitch wheel commands always used 0x2000 (Center position). - // Therefore it should be quite safe to ignore this command. - debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos); -} - -IIgsSoundMgr::IIgsSoundMgr() { - _midiChannels.resize(16); // Set the amount of available MIDI channels -} - -const IIgsInstrumentHeader* IIgsSoundMgr::getInstrument(uint8 program) const { - return &_instruments[_midiProgToInst->map(program)]; -} - -void IIgsSoundMgr::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { - _midiProgToInst = mapping; -} - -void IIgsSoundMgr::removeStoppedSounds() { - for (Common::Array::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - iter->removeStoppedSounds(); -} - -void IIgsMidiChannel::removeStoppedSounds() { - for (int i = _gsChannels.size() - 1; i >= 0; i--) - if (!_gsChannels[i].playing()) - _gsChannels.remove_at(i); -} - -uint IIgsSoundMgr::activeSounds() const { - uint result = 0; - - for (Common::Array::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - result += iter->activeSounds(); - - return result; -} - -uint IIgsMidiChannel::activeSounds() const { - uint result = 0; - - for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - if (!iter->end) - result++; - - return result; -} - -void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { - _instrument = instrument; - _sample = sample; - - // Set program on each Apple IIGS channel playing on this MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->setInstrument(instrument, sample); -} - -void IIgsMidiChannel::setVolume(uint8 volume) { - _volume = volume; - - // Set volume on each Apple IIGS channel playing on this MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->setChannelVolume(volume); -} - -void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) { - // Go through all the notes playing on this MIDI channel - // and turn off the ones that are playing the given note - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - if (iter->origNote == note) - iter->noteOff(velocity); -} - -void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) { - IIgsChannelInfo channel; - - // Use the default channel volume and instrument - channel.setChannelVolume(_volume); - channel.setInstrument(_instrument, _sample); - - // Set the note on and save the channel - channel.noteOn(note, velocity); - _gsChannels.push_back(channel); -} - -void IIgsChannelInfo::rewind() { - this->envVol = this->startEnvVol; - this->envSeg = 0; - this->pos = intToFrac(0); -} - -void IIgsChannelInfo::setChannelVolume(uint8 volume) { - this->chanVol = intToFrac(volume); -} - -void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { - assert(instrument != NULL && sample != NULL); - this->ins = instrument; - this->unrelocatedSample = sample; -} - -// TODO/FIXME: Implement correctly and fully (Take velocity into account etc) -void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) { - this->origNote = noteParam; - this->startEnvVol = intToFrac(0); - rewind(); - - const IIgsWaveInfo *waveInfo = NULL; - - for (uint i = 0; i < ins->oscList.count; i++) - if (ins->oscList(i).waves[0].top >= noteParam) - waveInfo = &ins->oscList(i).waves[0]; - - assert(waveInfo != NULL); - - this->relocatedSample = this->unrelocatedSample + waveInfo->addr; - this->posAdd = intToFrac(0); - this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0); - this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0); - this->loop = (waveInfo->mode == OSC_MODE_LOOP); - this->size = waveInfo->size - waveInfo->addr; - this->end = waveInfo->halt; -} - -// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc) -void IIgsChannelInfo::noteOff(uint8 velocity) { - this->loop = false; - this->envSeg = ins->relseg; -} - -void IIgsChannelInfo::stop() { - this->end = true; -} - -bool IIgsChannelInfo::playing() { - return !this->end; -} - -void SoundMgr::playSampleSound() { - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { - warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); - return; - } - - if (_playingSound != -1) - _playing = _gsSound.activeSounds() > 0; -} - static int cocoFrequencies[] = { 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, @@ -946,9 +423,9 @@ uint32 SoundMgr::mixSound() { // TODO: Implement playing both waves in an oscillator // TODO: Implement swap-mode in an oscillator if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - for (uint midiChan = 0; midiChan < _gsSound._midiChannels.size(); midiChan++) { - for (uint gsChan = 0; gsChan < _gsSound._midiChannels[midiChan]._gsChannels.size(); gsChan++) { - IIgsChannelInfo &channel = _gsSound._midiChannels[midiChan]._gsChannels[gsChan]; + for (uint midiChan = 0; midiChan < _gsSound->_midiChannels.size(); midiChan++) { + for (uint gsChan = 0; gsChan < _gsSound->_midiChannels[midiChan]._gsChannels.size(); gsChan++) { + IIgsChannelInfo &channel = _gsSound->_midiChannels[midiChan]._gsChannels[gsChan]; if (channel.playing()) { // Only mix in actively playing channels // Frequency multiplier was 1076.0 based on tests made with MESS 0.117. // Tests made with KEGS32 averaged the multiplier to around 1045. @@ -1002,7 +479,7 @@ uint32 SoundMgr::mixSound() { } } } - _gsSound.removeStoppedSounds(); + _gsSound->removeStoppedSounds(); return IIGS_BUFFER_SIZE; } // else ... @@ -1077,77 +554,6 @@ uint32 SoundMgr::mixSound() { return BUFFER_SIZE; } -/** - * Finds information about an Apple IIGS AGI executable based on the game ID. - * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. - */ -const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const { - for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++) - if (IIgsExeInfos[i].gameid == gameid) - return &IIgsExeInfos[i]; - return NULL; -} - -bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { - bool loadedOk = false; // Was loading successful? - Common::File file; - - // Open the executable file and check that it has correct size - file.open(exePath); - if (file.size() != (int32)exeInfo.exeSize) { - debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)", - exePath.getPath().c_str(), file.size(), exeInfo.exeSize); - } - - // Read the whole executable file into memory - Common::SharedPtr data(file.readStream(file.size())); - file.close(); - - // Check that we got enough data to be able to parse the instruments - if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) { - // Check instrument set's length (The info's saved in the executable) - data->seek(exeInfo.instSetStart - 4); - uint16 instSetByteCount = data->readUint16LE(); - if (instSetByteCount != exeInfo.instSet.byteCount) { - debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)", - instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str()); - } - - // Check instrument set's md5sum - data->seek(exeInfo.instSetStart); - - char md5str[32+1]; - Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount); - if (scumm_stricmp(md5str, exeInfo.instSet.md5)) { - warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless", - md5str, exePath.getPath().c_str()); - } - - // Read in the instrument set one instrument at a time - data->seek(exeInfo.instSetStart); - - // Load the instruments - _instruments.clear(); - _instruments.reserve(exeInfo.instSet.instCount); - - IIgsInstrumentHeader instrument; - for (uint i = 0; i < exeInfo.instSet.instCount; i++) { - if (!instrument.read(*data)) { - warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments", - i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str()); - break; - } - _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array - } - - // Loading was successful only if all instruments were loaded successfully - loadedOk = (_instruments.size() == exeInfo.instSet.instCount); - } else // Couldn't read enough data from the executable file - warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str()); - - return loadedOk; -} - /** * Convert sample from 8-bit unsigned to 8-bit signed format. * @param source Source stream containing the 8-bit unsigned sample data. @@ -1161,111 +567,6 @@ bool SoundMgr::convertWave(Common::SeekableReadStream &source, int8 *dest, uint return !(source.eos() || source.err()); } -bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { - Common::File file; - - // Open the wave file and read it into memory - file.open(wavePath); - Common::SharedPtr uint8Wave(file.readStream(file.size())); - file.close(); - - // Check that we got the whole wave file - if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) { - // Check wave file's md5sum - char md5str[32+1]; - Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE); - if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) { - warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \ - "Please report the information on the previous line to the ScummVM team.\n" \ - "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix); - } - - uint8Wave->seek(0); // Seek wave to its start - // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result - _wave.resize(uint8Wave->size()); - return SoundMgr::convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); - } else { // Couldn't read the wave file or it had incorrect size - warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str()); - return false; - } -} - -/** - * A function object (i.e. a functor) for testing if a Common::FSNode - * object's name is equal (Ignoring case) to a string or to at least - * one of the strings in a list of strings. Can be used e.g. with find_if(). - */ -struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction { -// FIXME: This should be replaced; use SearchMan instead - fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} - fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } - bool operator()(const Common::FSNode ¶m) const { - for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) - if (param.getName().equalsIgnoreCase(*iter)) - return true; - return false; - } -private: - Common::StringArray _str; -}; - -bool SoundMgr::loadInstruments() { - // Check that the platform is Apple IIGS, as only it uses custom instruments - if (_vm->getPlatform() != Common::kPlatformApple2GS) { - debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); - return true; - } - - // Get info on the particular Apple IIGS AGI game's executable - const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); - if (exeInfo == NULL) { - warning("Unsupported Apple IIGS game, not loading instruments"); - return false; - } - - // List files in the game path - Common::FSList fslist; - Common::FSNode dir(ConfMan.get("path")); - if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { - warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); - return false; - } - - // Populate executable filenames list (Long filename and short filename) for searching - Common::StringArray exeNames; - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); - - // Populate wave filenames list (Long filename and short filename) for searching - Common::StringArray waveNames; - waveNames.push_back("SIERRASTANDARD"); - waveNames.push_back("SIERRAST"); - - // Search for the executable file and the wave file (i.e. check if any of the filenames match) - Common::FSList::const_iterator exeFsnode, waveFsnode; - exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); - waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); - - // Make sure that we found the executable file - if (exeFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); - return false; - } - - // Make sure that we found the wave file - if (waveFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); - return false; - } - - // Set the MIDI program change to instrument number mapping and - // load the instrument headers and their sample data. - // None of the tested SIERRASTANDARD-files have zeroes in them so - // there's no need to check for prematurely ending samples here. - _gsSound.setProgramChangeMapping(&exeInfo->instSet.progToInst); - return _gsSound.loadWaveFile(*waveFsnode, *exeInfo) && _gsSound.loadInstrumentHeaders(*exeFsnode, *exeInfo); -} - void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) { SoundMgr *soundMgr = (SoundMgr *)udata; uint32 p = 0; @@ -1306,6 +607,8 @@ SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() { _waveform = 0; _disabledMidi = false; _useChorus = true; // FIXME: Currently always true? + + _gsSound = new IIgsSoundMgr; } void SoundMgr::premixerCall(int16 *data, uint len) { @@ -1318,6 +621,7 @@ void SoundMgr::setVolume(uint8 volume) { SoundMgr::~SoundMgr() { free(_sndBuffer); + delete _gsSound; } } // End of namespace Agi diff --git a/engines/agi/sound.h b/engines/agi/sound.h index 881e3efd56..ab0c9e20e5 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -28,20 +28,11 @@ #include "sound/audiostream.h" #include "sound/mixer.h" -#include "common/frac.h" namespace Agi { #define BUFFER_SIZE 410 -// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS -// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a -// 1/60th of a second in length. That should be getSampleRate() / 60 samples -// in length but as getSampleRate() is always 22050 at the moment we just use -// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368). -// FIXME: Use getSampleRate() / 60 rather than a hardcoded value -#define IIGS_BUFFER_SIZE 368 - #define SOUND_EMU_NONE 0 #define SOUND_EMU_PC 1 #define SOUND_EMU_TANDY 2 @@ -57,130 +48,6 @@ namespace Agi { #define ENV_RELEASE 7500 /**< envelope release rate */ #define NUM_CHANNELS 7 /**< number of sound channels */ -// MIDI command values (Shifted right by 4 so they're in the lower nibble) -#define MIDI_CMD_NOTE_OFF 0x08 -#define MIDI_CMD_NOTE_ON 0x09 -#define MIDI_CMD_CONTROLLER 0x0B -#define MIDI_CMD_PROGRAM_CHANGE 0x0C -#define MIDI_CMD_PITCH_WHEEL 0x0E -// Whole MIDI byte values (Command and channel info together) -#define MIDI_BYTE_STOP_SEQUENCE 0xFC -#define MIDI_BYTE_TIMER_SYNC 0xF8 - -struct IIgsEnvelopeSegment { - uint8 bp; - uint16 inc; ///< 8b.8b fixed point, very probably little endian -}; - -#define ENVELOPE_SEGMENT_COUNT 8 -struct IIgsEnvelope { - IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT]; - - /** Reads an Apple IIGS envelope from then given stream. */ - bool read(Common::SeekableReadStream &stream); -}; - -// 2**(1/12) i.e. the 12th root of 2 -#define SEMITONE 1.059463094359295 - -// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher -// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0) -#define C6_FREQ 1046.502261202395 - -// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments). -#define SIERRASTANDARD_SIZE 65536 - -// Maximum number of instruments in an Apple IIGS instrument set. -// Chosen empirically based on Apple IIGS AGI game data, increase if needed. -#define MAX_INSTRUMENTS 28 - -struct IIgsWaveInfo { - uint8 top; - uint addr; - uint size; -// Oscillator channel -#define OSC_CHANNEL_RIGHT 0 -#define OSC_CHANNEL_LEFT 1 - uint channel; -// Oscillator mode -#define OSC_MODE_LOOP 0 -#define OSC_MODE_ONESHOT 1 -#define OSC_MODE_SYNC_AM 2 -#define OSC_MODE_SWAP 3 - uint mode; - bool halt; - int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point) - - /** Reads an Apple IIGS wave information structure from the given stream. */ - bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -// Number of waves per Apple IIGS sound oscillator -#define WAVES_PER_OSCILLATOR 2 - -/** An Apple IIGS sound oscillator. Consists always of two waves. */ -struct IIgsOscillator { - IIgsWaveInfo waves[WAVES_PER_OSCILLATOR]; - - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -// Maximum number of oscillators in an Apple IIGS instrument. -// Chosen empirically based on Apple IIGS AGI game data, increase if needed. -#define MAX_OSCILLATORS 4 - -/** An Apple IIGS sound oscillator list. */ -struct IIgsOscillatorList { - uint count; ///< Oscillator count - IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators - - /** Indexing operators for easier access to the oscillators. */ - const IIgsOscillator &operator()(uint index) const { return osc[index]; } - IIgsOscillator &operator()(uint index) { return osc[index]; } - - /** Reads an Apple IIGS oscillator list from the given stream. */ - bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -struct IIgsInstrumentHeader { - IIgsEnvelope env; - uint8 relseg; - uint8 bendrange; - uint8 vibdepth; - uint8 vibspeed; - IIgsOscillatorList oscList; - - /** - * Read an Apple IIGS instrument header from the given stream. - * @param stream The source stream from which to read the data. - * @param ignoreAddr Should we ignore wave infos' wave address variable's value? - * @return True if successful, false otherwise. - */ - bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - -struct IIgsSampleHeader { - uint16 type; - uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080) - uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others. - uint8 volume; ///< Current guess: Logarithmic in 6 dB steps - uint8 unknownByte_Ofs5; ///< 0 in all tested samples. - uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess. - uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16. - IIgsInstrumentHeader instrument; - - /** - * Read an Apple IIGS AGI sample header from the given stream. - * @param stream The source stream from which to read the data. - * @return True if successful, false otherwise. - */ - bool read(Common::SeekableReadStream &stream); - bool finalize(Common::SeekableReadStream &uint8Wave); -}; - /** * AGI sound note structure. */ @@ -200,32 +67,6 @@ struct AgiNote { } }; -struct IIgsChannelInfo { - const IIgsInstrumentHeader *ins; ///< Instrument info - const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation - const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation - frac_t pos; ///< Current sample position - frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc) - uint8 origNote; ///< The original note without the added relative pitch - frac_t note; ///< Note (With the added relative pitch) - frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account) - frac_t chanVol; ///< Channel volume - frac_t startEnvVol; ///< Starting envelope volume - frac_t envVol; ///< Current envelope volume - uint envSeg; ///< Current envelope segment - uint size; ///< Sample size - bool loop; ///< Should we loop the sample? - bool end; ///< Has the playing ended? - - void rewind(); ///< Rewinds the sound playing on this channel to its start - void setChannelVolume(uint8 volume); ///< Sets the channel volume - void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel - void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel - void noteOff(uint8 velocity); ///< Releases the note on this channel - void stop(); ///< Stops the note playing on this channel instantly - bool playing(); ///< Is there a note playing on this channel? -}; - struct CoCoNote { uint8 freq; uint8 volume; @@ -322,126 +163,11 @@ protected: uint16 _type; ///< Sound resource type }; -class IIgsMidi : public AgiSound { -public: - IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~IIgsMidi() { if (_data != NULL) free(_data); } - virtual uint16 type() { return _type; } - virtual const uint8 *getPtr() { return _ptr; } - virtual void setPtr(const uint8 *ptr) { _ptr = ptr; } - virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; } -protected: - uint8 *_data; ///< Raw sound resource data - const uint8 *_ptr; ///< Pointer to the current position in the MIDI data - uint32 _len; ///< Length of the raw sound resource - uint16 _type; ///< Sound resource type -public: - uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second) - uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second) -}; - -class IIgsSample : public AgiSound { -public: - IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~IIgsSample() { delete[] _sample; } - virtual uint16 type() { return _header.type; } - const IIgsSampleHeader &getHeader() const { return _header; } - const int8 *getSample() const { return _sample; } -protected: - IIgsSampleHeader _header; ///< Apple IIGS AGI sample header - int8 *_sample; ///< Sample data (8-bit signed format) -}; - -/** Apple IIGS MIDI program change to instrument number mapping. */ -struct MidiProgramChangeMapping { - byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping - byte undefinedInst; ///< The undefined instrument number - - // Maps the MIDI program number to an instrument number - byte map(uint midiProg) const { - return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst; - } -}; - -/** Apple IIGS AGI instrument set information. */ -struct InstrumentSetInfo { - uint byteCount; ///< Length of the whole instrument set in bytes - uint instCount; ///< Amount of instrument in the set - const char *md5; ///< MD5 hex digest of the whole instrument set - const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments) - const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping -}; - -/** Apple IIGS AGI executable file information. */ -struct IIgsExeInfo { - enum AgiGameID gameid; ///< Game ID - const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc) - uint agiVer; ///< Apple IIGS AGI version number, not strictly needed - uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes - uint instSetStart; ///< Starting offset of the instrument set inside the executable file - const InstrumentSetInfo &instSet; ///< Information about the used instrument set -}; - -class IIgsMidiChannel { -public: - IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {} - uint activeSounds() const; ///< How many active sounds are playing? - void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); - void setVolume(uint8 volume); - void noteOff(uint8 note, uint8 velocity); - void noteOn(uint8 note, uint8 velocity); - void stopSounds(); ///< Clears the channel of any sounds - void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel -public: - typedef Common::Array::const_iterator const_iterator; - typedef Common::Array::iterator iterator; - Common::Array _gsChannels; ///< Apple IIGS channels playing on this MIDI channel -protected: - const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel - const int8 *_sample; ///< Sample data used on this MIDI channel - uint8 _volume; ///< MIDI controller number 7 (Volume) -}; - -/** - * Class for managing Apple IIGS sound channels. - * TODO: Check what instruments are used by default on the MIDI channels - * FIXME: Some instrument choices sound wrong - */ -class IIgsSoundMgr { -public: - typedef Common::Array::const_iterator const_iterator; - typedef Common::Array::iterator iterator; - static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects -public: - // For initializing - IIgsSoundMgr(); - void setProgramChangeMapping(const MidiProgramChangeMapping *mapping); - bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo); - bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo); - // Miscellaneous methods - uint activeSounds() const; ///< How many active sounds are playing? - void stopSounds(); ///< Stops all sounds - void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels - // For playing Apple IIGS AGI samples (Sound effects etc) - bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample); - // MIDI commands - void midiNoteOff(uint8 channel, uint8 note, uint8 velocity); - void midiNoteOn(uint8 channel, uint8 note, uint8 velocity); - void midiController(uint8 channel, uint8 controller, uint8 value); - void midiProgramChange(uint8 channel, uint8 program); - void midiPitchWheel(uint8 wheelPos); -protected: - const IIgsInstrumentHeader* getInstrument(uint8 program) const; -public: - Common::Array _midiChannels; ///< Information about each MIDI channel -protected: - Common::Array _wave; ///< Sample data used by the Apple IIGS MIDI instruments - const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping - Common::Array _instruments; ///< Instruments used by the Apple IIGS AGI -}; - class AgiEngine; class AgiBase; +class IIgsSoundMgr; + +struct IIgsExeInfo; class SoundMgr : public Audio::AudioStream { AgiBase *_vm; @@ -477,7 +203,7 @@ private: bool _playing; ChannelInfo _chn[NUM_CHANNELS]; - IIgsSoundMgr _gsSound; + IIgsSoundMgr *_gsSound; int _endflag; int _playingSound; uint8 _env; diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp new file mode 100644 index 0000000000..ce4aa160a0 --- /dev/null +++ b/engines/agi/sound_2gs.cpp @@ -0,0 +1,736 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/md5.h" +#include "common/config-manager.h" +#include "common/fs.h" +#include "common/random.h" +#include "common/str-array.h" + +#include "agi/agi.h" +#include "agi/sound_2gs.h" + +namespace Agi { + +IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + _data = data; // Save the resource pointer + _ptr = _data + 2; // Set current position to just after the header + _len = len; // Save the resource's length + _type = READ_LE_UINT16(data); // Read sound resource's type + _midiTicks = _soundBufTicks = 0; + _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); + + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); +} + +IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); + + // Check that the header was read ok and that it's of the correct type + if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource + uint32 sampleStartPos = stream.pos(); + uint32 tailLen = stream.size() - sampleStartPos; + + if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream + // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes + // of sample data although header says it should have 16384 bytes. + warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", + resnum, tailLen, _header.sampleSize); + + _header.sampleSize = (uint16) tailLen; // Use the part that's left + } + + if (_header.pitch > 0x7F) { // Check if the pitch is invalid + warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); + + _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too + } + + // Finalize the header info using the 8-bit unsigned sample data + _header.finalize(stream); + + // Convert sample data from 8-bit unsigned to 8-bit signed format + stream.seek(sampleStartPos); + _sample = new int8[_header.sampleSize]; + + if (_sample != NULL) + _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize); + } + + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); +} + +/** Reads an Apple IIGS envelope from then given stream. */ +bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { + for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { + seg[segNum].bp = stream.readByte(); + seg[segNum].inc = stream.readUint16LE(); + } + + return !(stream.eos() || stream.err()); +} + +/** Reads an Apple IIGS wave information structure from the given stream. */ +bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + top = stream.readByte(); + addr = stream.readByte() * 256; + size = (1 << (stream.readByte() & 7)) * 256; + + // Read packed mode byte and parse it into parts + byte packedModeByte = stream.readByte(); + channel = (packedModeByte >> 4) & 1; // Bit 4 + mode = (packedModeByte >> 1) & 3; // Bits 1-2 + halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) + + relPitch = stream.readSint16LE(); + + // Zero the wave address if we want to ignore the wave address info + if (ignoreAddr) + addr = 0; + + return !(stream.eos() || stream.err()); +} + +bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { + uint32 startPos = uint8Wave.pos(); // Save stream's starting position + uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address + + // Calculate the true sample size (A zero ends the sample prematurely) + uint trueSize = size; // Set a default value for the result + for (uint i = 0; i < size; i++) { + if (uint8Wave.readByte() == 0) { + trueSize = i; + // A zero in the sample stream turns off looping + // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) + if (mode == OSC_MODE_LOOP) + mode = OSC_MODE_ONESHOT; + break; + } + } + size = trueSize; // Set the true sample size + + uint8Wave.seek(startPos); // Seek back to the stream's starting position + + return true; +} + +bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) + if (!waves[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { + // First read the A waves and then the B waves for the oscillators + for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) + for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) + if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) + return false; + + count = oscillatorCount; // Set the oscillator count + + return true; +} + +bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < count; i++) + if (!osc[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + env.read(stream); + relseg = stream.readByte(); + /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. + bendrange = stream.readByte(); + vibdepth = stream.readByte(); + vibspeed = stream.readByte(); + /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. + byte wac = stream.readByte(); // Read A wave count + byte wbc = stream.readByte(); // Read B wave count + oscList.read(stream, wac, ignoreAddr); // Read the oscillators + return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match +} + +bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return oscList.finalize(uint8Wave); +} + +bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { + type = stream.readUint16LE(); + pitch = stream.readByte(); + unknownByte_Ofs3 = stream.readByte(); + volume = stream.readByte(); + unknownByte_Ofs5 = stream.readByte(); + instrumentSize = stream.readUint16LE(); + sampleSize = stream.readUint16LE(); + // Read the instrument header *ignoring* its wave address info + + return instrument.read(stream, true); +} + +bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return instrument.finalize(uint8Wave); +} + +/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV1 = { + {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, + 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, + 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, + 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, + 25, 13, 13, 25}, + 5 +}; + +/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV2 = { + {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, + 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, + 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, + 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, + 27, 15, 15, 27}, + 6 +}; + +/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ +static const InstrumentSetInfo instSetV1 = { + 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 +}; + +/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ +static const InstrumentSetInfo instSetV2 = { + 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 +}; + +/** Information about different Apple IIGS AGI executables. */ +static const IIgsExeInfo IIgsExeInfos[] = { + {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, + {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, + {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, + {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, + {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, + {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, + {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, + {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, + {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, + {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, + {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, + {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, + {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} +}; + +void IIgsSoundMgr::stopSounds() { + // Stops all sounds on all MIDI channels + for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->stopSounds(); +} + +void SoundMgr::playSampleSound() { + if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { + warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); + return; + } + + if (_playingSound != -1) + _playing = _gsSound->activeSounds() > 0; +} + +bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { + stopSounds(); + IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; + + channel.setInstrument(&sampleHeader.instrument, sample); + channel.setVolume(sampleHeader.volume); + channel.noteOn(sampleHeader.pitch, 64); // Use default velocity (i.e. 64) + + return true; +} + +void IIgsMidiChannel::stopSounds() { + // Stops all sounds on this single MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->stop(); + + _gsChannels.clear(); +} + +void SoundMgr::playMidiSound() { + if (_disabledMidi) + return; + + const uint8 *p; + uint8 parm1, parm2; + static uint8 cmd, ch; + + if (_playingSound == -1 || _vm->_game.sounds[_playingSound] == NULL) { + warning("Error playing Apple IIGS MIDI sound resource"); + _playing = false; + + return; + } + + IIgsMidi *midiObj = (IIgsMidi *) _vm->_game.sounds[_playingSound]; + + _playing = true; + p = midiObj->getPtr(); + + midiObj->_soundBufTicks++; + + while (true) { + uint8 readByte = *p; + + // Check for end of MIDI sequence marker (Can also be here before delta-time) + if (readByte == MIDI_BYTE_STOP_SEQUENCE) { + debugC(3, kDebugLevelSound, "End of MIDI sequence (Before reading delta-time)"); + _playing = false; + + midiObj->rewind(); + + return; + } else if (readByte == MIDI_BYTE_TIMER_SYNC) { + debugC(3, kDebugLevelSound, "Timer sync"); + p++; // Jump over the timer sync byte as it's not needed + + continue; + } + + uint8 deltaTime = readByte; + if (midiObj->_midiTicks + deltaTime > midiObj->_soundBufTicks) { + break; + } + midiObj->_midiTicks += deltaTime; + p++; // Jump over the delta-time byte as it was already taken care of + + // Check for end of MIDI sequence marker (This time it after reading delta-time) + if (*p == MIDI_BYTE_STOP_SEQUENCE) { + debugC(3, kDebugLevelSound, "End of MIDI sequence (After reading delta-time)"); + _playing = false; + + midiObj->rewind(); + + return; + } + + // Separate byte into command and channel if it's a command byte. + // Otherwise use running status (i.e. previously set command and channel). + if (*p & 0x80) { + cmd = *p++; + ch = cmd & 0x0f; + cmd >>= 4; + } + + switch (cmd) { + case MIDI_CMD_NOTE_OFF: + parm1 = *p++; + parm2 = *p++; + _gsSound->midiNoteOff(ch, parm1, parm2); + break; + case MIDI_CMD_NOTE_ON: + parm1 = *p++; + parm2 = *p++; + _gsSound->midiNoteOn(ch, parm1, parm2); + break; + case MIDI_CMD_CONTROLLER: + parm1 = *p++; + parm2 = *p++; + _gsSound->midiController(ch, parm1, parm2); + break; + case MIDI_CMD_PROGRAM_CHANGE: + parm1 = *p++; + _gsSound->midiProgramChange(ch, parm1); + break; + case MIDI_CMD_PITCH_WHEEL: + parm1 = *p++; + parm2 = *p++; + + uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value + _gsSound->midiPitchWheel(wheelPos); + break; + } + } + + midiObj->setPtr(p); +} + +void IIgsSoundMgr::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { + _midiChannels[channel].noteOff(note, velocity); + debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity); +} + +void IIgsSoundMgr::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { + _midiChannels[channel].noteOn(note, velocity); + debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity); +} + +// TODO: Check if controllers behave differently on different MIDI channels +// TODO: Doublecheck what other controllers than the volume controller do +void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) { + IIgsMidiChannel &midiChannel = _midiChannels[channel]; + + // The tested Apple IIGS AGI MIDI resources only used + // controllers 0 (Bank select?), 7 (Volume) and 64 (Sustain On/Off). + // Controller 0's parameter was in range 94-127, + // controller 7's parameter was in range 0-127 and + // controller 64's parameter was always 0 (i.e. sustain off). + bool unimplemented = false; + switch (controller) { + case 7: // Volume + midiChannel.setVolume(value); + break; + default: + unimplemented = true; + break; + } + debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : ""); +} + +void IIgsSoundMgr::midiProgramChange(uint8 channel, uint8 program) { + _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin()); + debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel); +} + +void IIgsSoundMgr::midiPitchWheel(uint8 wheelPos) { + // In all the tested Apple IIGS AGI MIDI resources + // pitch wheel commands always used 0x2000 (Center position). + // Therefore it should be quite safe to ignore this command. + debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos); +} + +IIgsSoundMgr::IIgsSoundMgr() { + _midiChannels.resize(16); // Set the amount of available MIDI channels +} + +const IIgsInstrumentHeader* IIgsSoundMgr::getInstrument(uint8 program) const { + return &_instruments[_midiProgToInst->map(program)]; +} + +void IIgsSoundMgr::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { + _midiProgToInst = mapping; +} + +void IIgsSoundMgr::removeStoppedSounds() { + for (Common::Array::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->removeStoppedSounds(); +} + +void IIgsMidiChannel::removeStoppedSounds() { + for (int i = _gsChannels.size() - 1; i >= 0; i--) + if (!_gsChannels[i].playing()) + _gsChannels.remove_at(i); +} + +uint IIgsSoundMgr::activeSounds() const { + uint result = 0; + + for (Common::Array::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + result += iter->activeSounds(); + + return result; +} + +uint IIgsMidiChannel::activeSounds() const { + uint result = 0; + + for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + if (!iter->end) + result++; + + return result; +} + +void IIgsMidiChannel::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { + _instrument = instrument; + _sample = sample; + + // Set program on each Apple IIGS channel playing on this MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->setInstrument(instrument, sample); +} + +void IIgsMidiChannel::setVolume(uint8 volume) { + _volume = volume; + + // Set volume on each Apple IIGS channel playing on this MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->setChannelVolume(volume); +} + +void IIgsMidiChannel::noteOff(uint8 note, uint8 velocity) { + // Go through all the notes playing on this MIDI channel + // and turn off the ones that are playing the given note + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + if (iter->origNote == note) + iter->noteOff(velocity); +} + +void IIgsMidiChannel::noteOn(uint8 note, uint8 velocity) { + IIgsChannelInfo channel; + + // Use the default channel volume and instrument + channel.setChannelVolume(_volume); + channel.setInstrument(_instrument, _sample); + + // Set the note on and save the channel + channel.noteOn(note, velocity); + _gsChannels.push_back(channel); +} + +void IIgsChannelInfo::rewind() { + this->envVol = this->startEnvVol; + this->envSeg = 0; + this->pos = intToFrac(0); +} + +void IIgsChannelInfo::setChannelVolume(uint8 volume) { + this->chanVol = intToFrac(volume); +} + +void IIgsChannelInfo::setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample) { + assert(instrument != NULL && sample != NULL); + this->ins = instrument; + this->unrelocatedSample = sample; +} + +// TODO/FIXME: Implement correctly and fully (Take velocity into account etc) +void IIgsChannelInfo::noteOn(uint8 noteParam, uint8 velocity) { + this->origNote = noteParam; + this->startEnvVol = intToFrac(0); + rewind(); + + const IIgsWaveInfo *waveInfo = NULL; + + for (uint i = 0; i < ins->oscList.count; i++) + if (ins->oscList(i).waves[0].top >= noteParam) + waveInfo = &ins->oscList(i).waves[0]; + + assert(waveInfo != NULL); + + this->relocatedSample = this->unrelocatedSample + waveInfo->addr; + this->posAdd = intToFrac(0); + this->note = intToFrac(noteParam) + doubleToFrac(waveInfo->relPitch/256.0); + this->vol = doubleToFrac(fracToDouble(this->envVol) * fracToDouble(this->chanVol) / 127.0); + this->loop = (waveInfo->mode == OSC_MODE_LOOP); + this->size = waveInfo->size - waveInfo->addr; + this->end = waveInfo->halt; +} + +// TODO/FIXME: Implement correctly and fully (Take release time and velocity into account etc) +void IIgsChannelInfo::noteOff(uint8 velocity) { + this->loop = false; + this->envSeg = ins->relseg; +} + +void IIgsChannelInfo::stop() { + this->end = true; +} + +bool IIgsChannelInfo::playing() { + return !this->end; +} + +/** + * Finds information about an Apple IIGS AGI executable based on the game ID. + * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. + */ +const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const { + for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++) + if (IIgsExeInfos[i].gameid == gameid) + return &IIgsExeInfos[i]; + return NULL; +} + +bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { + bool loadedOk = false; // Was loading successful? + Common::File file; + + // Open the executable file and check that it has correct size + file.open(exePath); + if (file.size() != (int32)exeInfo.exeSize) { + debugC(3, kDebugLevelSound, "Apple IIGS executable (%s) has wrong size (Is %d, should be %d)", + exePath.getPath().c_str(), file.size(), exeInfo.exeSize); + } + + // Read the whole executable file into memory + Common::SharedPtr data(file.readStream(file.size())); + file.close(); + + // Check that we got enough data to be able to parse the instruments + if (data && data->size() >= (int32)(exeInfo.instSetStart + exeInfo.instSet.byteCount)) { + // Check instrument set's length (The info's saved in the executable) + data->seek(exeInfo.instSetStart - 4); + uint16 instSetByteCount = data->readUint16LE(); + if (instSetByteCount != exeInfo.instSet.byteCount) { + debugC(3, kDebugLevelSound, "Wrong instrument set size (Is %d, should be %d) in Apple IIGS executable (%s)", + instSetByteCount, exeInfo.instSet.byteCount, exePath.getPath().c_str()); + } + + // Check instrument set's md5sum + data->seek(exeInfo.instSetStart); + + char md5str[32+1]; + Common::md5_file_string(*data, md5str, exeInfo.instSet.byteCount); + if (scumm_stricmp(md5str, exeInfo.instSet.md5)) { + warning("Unknown Apple IIGS instrument set (md5: %s) in %s, trying to use it nonetheless", + md5str, exePath.getPath().c_str()); + } + + // Read in the instrument set one instrument at a time + data->seek(exeInfo.instSetStart); + + // Load the instruments + _instruments.clear(); + _instruments.reserve(exeInfo.instSet.instCount); + + IIgsInstrumentHeader instrument; + for (uint i = 0; i < exeInfo.instSet.instCount; i++) { + if (!instrument.read(*data)) { + warning("Error loading Apple IIGS instrument (%d. of %d) from %s, not loading more instruments", + i + 1, exeInfo.instSet.instCount, exePath.getPath().c_str()); + break; + } + _instruments.push_back(instrument); // Add the successfully loaded instrument to the instruments array + } + + // Loading was successful only if all instruments were loaded successfully + loadedOk = (_instruments.size() == exeInfo.instSet.instCount); + } else // Couldn't read enough data from the executable file + warning("Error loading instruments from Apple IIGS executable (%s)", exePath.getPath().c_str()); + + return loadedOk; +} + +bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { + Common::File file; + + // Open the wave file and read it into memory + file.open(wavePath); + Common::SharedPtr uint8Wave(file.readStream(file.size())); + file.close(); + + // Check that we got the whole wave file + if (uint8Wave && uint8Wave->size() == SIERRASTANDARD_SIZE) { + // Check wave file's md5sum + char md5str[32+1]; + Common::md5_file_string(*uint8Wave, md5str, SIERRASTANDARD_SIZE); + if (scumm_stricmp(md5str, exeInfo.instSet.waveFileMd5)) { + warning("Unknown Apple IIGS wave file (md5: %s, game: %s).\n" \ + "Please report the information on the previous line to the ScummVM team.\n" \ + "Using the wave file as it is - music may sound weird", md5str, exeInfo.exePrefix); + } + + uint8Wave->seek(0); // Seek wave to its start + // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result + _wave.resize(uint8Wave->size()); + return SoundMgr::convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); + } else { // Couldn't read the wave file or it had incorrect size + warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str()); + return false; + } +} + +/** + * A function object (i.e. a functor) for testing if a Common::FSNode + * object's name is equal (Ignoring case) to a string or to at least + * one of the strings in a list of strings. Can be used e.g. with find_if(). + */ +struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction { +// FIXME: This should be replaced; use SearchMan instead + fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} + fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } + bool operator()(const Common::FSNode ¶m) const { + for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) + if (param.getName().equalsIgnoreCase(*iter)) + return true; + return false; + } +private: + Common::StringArray _str; +}; + +bool SoundMgr::loadInstruments() { + // Check that the platform is Apple IIGS, as only it uses custom instruments + if (_vm->getPlatform() != Common::kPlatformApple2GS) { + debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); + return true; + } + + // Get info on the particular Apple IIGS AGI game's executable + const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); + if (exeInfo == NULL) { + warning("Unsupported Apple IIGS game, not loading instruments"); + return false; + } + + // List files in the game path + Common::FSList fslist; + Common::FSNode dir(ConfMan.get("path")); + if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { + warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); + return false; + } + + // Populate executable filenames list (Long filename and short filename) for searching + Common::StringArray exeNames; + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); + + // Populate wave filenames list (Long filename and short filename) for searching + Common::StringArray waveNames; + waveNames.push_back("SIERRASTANDARD"); + waveNames.push_back("SIERRAST"); + + // Search for the executable file and the wave file (i.e. check if any of the filenames match) + Common::FSList::const_iterator exeFsnode, waveFsnode; + exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); + waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); + + // Make sure that we found the executable file + if (exeFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); + return false; + } + + // Make sure that we found the wave file + if (waveFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); + return false; + } + + // Set the MIDI program change to instrument number mapping and + // load the instrument headers and their sample data. + // None of the tested SIERRASTANDARD-files have zeroes in them so + // there's no need to check for prematurely ending samples here. + _gsSound->setProgramChangeMapping(&exeInfo->instSet.progToInst); + return _gsSound->loadWaveFile(*waveFsnode, *exeInfo) && _gsSound->loadInstrumentHeaders(*exeFsnode, *exeInfo); +} + +} // End of namespace Agi diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h new file mode 100644 index 0000000000..3669d29955 --- /dev/null +++ b/engines/agi/sound_2gs.h @@ -0,0 +1,311 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef AGI_SOUND_2GS_H +#define AGI_SOUND_2GS_H + +#include "common/frac.h" + +namespace Agi { + +// Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS +// KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a +// 1/60th of a second in length. That should be getSampleRate() / 60 samples +// in length but as getSampleRate() is always 22050 at the moment we just use +// the hardcoded value of 368 (22050/60 = 367.5 which rounds up to 368). +// FIXME: Use getSampleRate() / 60 rather than a hardcoded value +#define IIGS_BUFFER_SIZE 368 + +// MIDI command values (Shifted right by 4 so they're in the lower nibble) +#define MIDI_CMD_NOTE_OFF 0x08 +#define MIDI_CMD_NOTE_ON 0x09 +#define MIDI_CMD_CONTROLLER 0x0B +#define MIDI_CMD_PROGRAM_CHANGE 0x0C +#define MIDI_CMD_PITCH_WHEEL 0x0E +// Whole MIDI byte values (Command and channel info together) +#define MIDI_BYTE_STOP_SEQUENCE 0xFC +#define MIDI_BYTE_TIMER_SYNC 0xF8 + +struct IIgsEnvelopeSegment { + uint8 bp; + uint16 inc; ///< 8b.8b fixed point, very probably little endian +}; + +#define ENVELOPE_SEGMENT_COUNT 8 +struct IIgsEnvelope { + IIgsEnvelopeSegment seg[ENVELOPE_SEGMENT_COUNT]; + + /** Reads an Apple IIGS envelope from then given stream. */ + bool read(Common::SeekableReadStream &stream); +}; + +// 2**(1/12) i.e. the 12th root of 2 +#define SEMITONE 1.059463094359295 + +// C6's frequency is A4's (440 Hz) frequency but one full octave and three semitones higher +// i.e. C6_FREQ = 440 * pow(2.0, 15/12.0) +#define C6_FREQ 1046.502261202395 + +// Size of the SIERRASTANDARD file (i.e. the wave file i.e. the sample data used by the instruments). +#define SIERRASTANDARD_SIZE 65536 + +// Maximum number of instruments in an Apple IIGS instrument set. +// Chosen empirically based on Apple IIGS AGI game data, increase if needed. +#define MAX_INSTRUMENTS 28 + +struct IIgsWaveInfo { + uint8 top; + uint addr; + uint size; +// Oscillator channel +#define OSC_CHANNEL_RIGHT 0 +#define OSC_CHANNEL_LEFT 1 + uint channel; +// Oscillator mode +#define OSC_MODE_LOOP 0 +#define OSC_MODE_ONESHOT 1 +#define OSC_MODE_SYNC_AM 2 +#define OSC_MODE_SWAP 3 + uint mode; + bool halt; + int16 relPitch; ///< Relative pitch in semitones (Signed 8b.8b fixed point) + + /** Reads an Apple IIGS wave information structure from the given stream. */ + bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +// Number of waves per Apple IIGS sound oscillator +#define WAVES_PER_OSCILLATOR 2 + +/** An Apple IIGS sound oscillator. Consists always of two waves. */ +struct IIgsOscillator { + IIgsWaveInfo waves[WAVES_PER_OSCILLATOR]; + + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +// Maximum number of oscillators in an Apple IIGS instrument. +// Chosen empirically based on Apple IIGS AGI game data, increase if needed. +#define MAX_OSCILLATORS 4 + +/** An Apple IIGS sound oscillator list. */ +struct IIgsOscillatorList { + uint count; ///< Oscillator count + IIgsOscillator osc[MAX_OSCILLATORS]; ///< The oscillators + + /** Indexing operators for easier access to the oscillators. */ + const IIgsOscillator &operator()(uint index) const { return osc[index]; } + IIgsOscillator &operator()(uint index) { return osc[index]; } + + /** Reads an Apple IIGS oscillator list from the given stream. */ + bool read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsInstrumentHeader { + IIgsEnvelope env; + uint8 relseg; + uint8 bendrange; + uint8 vibdepth; + uint8 vibspeed; + IIgsOscillatorList oscList; + + /** + * Read an Apple IIGS instrument header from the given stream. + * @param stream The source stream from which to read the data. + * @param ignoreAddr Should we ignore wave infos' wave address variable's value? + * @return True if successful, false otherwise. + */ + bool read(Common::SeekableReadStream &stream, bool ignoreAddr = false); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsSampleHeader { + uint16 type; + uint8 pitch; ///< Logarithmic, base is 2**(1/12), unknown multiplier (Possibly in range 1040-1080) + uint8 unknownByte_Ofs3; // 0x7F in Gold Rush's sound resource 60, 0 in all others. + uint8 volume; ///< Current guess: Logarithmic in 6 dB steps + uint8 unknownByte_Ofs5; ///< 0 in all tested samples. + uint16 instrumentSize; ///< Little endian. 44 in all tested samples. A guess. + uint16 sampleSize; ///< Little endian. Accurate in all tested samples excluding Manhunter I's sound resource 16. + IIgsInstrumentHeader instrument; + + /** + * Read an Apple IIGS AGI sample header from the given stream. + * @param stream The source stream from which to read the data. + * @return True if successful, false otherwise. + */ + bool read(Common::SeekableReadStream &stream); + bool finalize(Common::SeekableReadStream &uint8Wave); +}; + +struct IIgsChannelInfo { + const IIgsInstrumentHeader *ins; ///< Instrument info + const int8 *relocatedSample; ///< Source sample data (8-bit signed format) using relocation + const int8 *unrelocatedSample; ///< Source sample data (8-bit signed format) without relocation + frac_t pos; ///< Current sample position + frac_t posAdd; ///< Current sample position adder (Calculated using note, vibrato etc) + uint8 origNote; ///< The original note without the added relative pitch + frac_t note; ///< Note (With the added relative pitch) + frac_t vol; ///< Current volume (Takes both channel volume and enveloping into account) + frac_t chanVol; ///< Channel volume + frac_t startEnvVol; ///< Starting envelope volume + frac_t envVol; ///< Current envelope volume + uint envSeg; ///< Current envelope segment + uint size; ///< Sample size + bool loop; ///< Should we loop the sample? + bool end; ///< Has the playing ended? + + void rewind(); ///< Rewinds the sound playing on this channel to its start + void setChannelVolume(uint8 volume); ///< Sets the channel volume + void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); ///< Sets the instrument to be used on this channel + void noteOn(uint8 noteParam, uint8 velocity); ///< Starts playing a note on this channel + void noteOff(uint8 velocity); ///< Releases the note on this channel + void stop(); ///< Stops the note playing on this channel instantly + bool playing(); ///< Is there a note playing on this channel? +}; + +class IIgsMidi : public AgiSound { +public: + IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~IIgsMidi() { if (_data != NULL) free(_data); } + virtual uint16 type() { return _type; } + virtual const uint8 *getPtr() { return _ptr; } + virtual void setPtr(const uint8 *ptr) { _ptr = ptr; } + virtual void rewind() { _ptr = _data + 2; _midiTicks = _soundBufTicks = 0; } +protected: + uint8 *_data; ///< Raw sound resource data + const uint8 *_ptr; ///< Pointer to the current position in the MIDI data + uint32 _len; ///< Length of the raw sound resource + uint16 _type; ///< Sound resource type +public: + uint _midiTicks; ///< MIDI song position in ticks (1/60ths of a second) + uint _soundBufTicks; ///< Sound buffer position in ticks (1/60ths of a second) +}; + +class IIgsSample : public AgiSound { +public: + IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~IIgsSample() { delete[] _sample; } + virtual uint16 type() { return _header.type; } + const IIgsSampleHeader &getHeader() const { return _header; } + const int8 *getSample() const { return _sample; } +protected: + IIgsSampleHeader _header; ///< Apple IIGS AGI sample header + int8 *_sample; ///< Sample data (8-bit signed format) +}; + +/** Apple IIGS MIDI program change to instrument number mapping. */ +struct MidiProgramChangeMapping { + byte midiProgToInst[44]; ///< Lookup table for the MIDI program number to instrument number mapping + byte undefinedInst; ///< The undefined instrument number + + // Maps the MIDI program number to an instrument number + byte map(uint midiProg) const { + return midiProg < ARRAYSIZE(midiProgToInst) ? midiProgToInst[midiProg] : undefinedInst; + } +}; + +/** Apple IIGS AGI instrument set information. */ +struct InstrumentSetInfo { + uint byteCount; ///< Length of the whole instrument set in bytes + uint instCount; ///< Amount of instrument in the set + const char *md5; ///< MD5 hex digest of the whole instrument set + const char *waveFileMd5; ///< MD5 hex digest of the wave file (i.e. the sample data used by the instruments) + const MidiProgramChangeMapping &progToInst; ///< Program change to instrument number mapping +}; + +/** Apple IIGS AGI executable file information. */ +struct IIgsExeInfo { + enum AgiGameID gameid; ///< Game ID + const char *exePrefix; ///< Prefix of the Apple IIGS AGI executable (e.g. "SQ", "PQ", "KQ4" etc) + uint agiVer; ///< Apple IIGS AGI version number, not strictly needed + uint exeSize; ///< Size of the Apple IIGS AGI executable file in bytes + uint instSetStart; ///< Starting offset of the instrument set inside the executable file + const InstrumentSetInfo &instSet; ///< Information about the used instrument set +}; + +class IIgsMidiChannel { +public: + IIgsMidiChannel() : _instrument(0), _sample(0), _volume(0) {} + uint activeSounds() const; ///< How many active sounds are playing? + void setInstrument(const IIgsInstrumentHeader *instrument, const int8 *sample); + void setVolume(uint8 volume); + void noteOff(uint8 note, uint8 velocity); + void noteOn(uint8 note, uint8 velocity); + void stopSounds(); ///< Clears the channel of any sounds + void removeStoppedSounds(); ///< Removes all stopped sounds from this MIDI channel +public: + typedef Common::Array::const_iterator const_iterator; + typedef Common::Array::iterator iterator; + Common::Array _gsChannels; ///< Apple IIGS channels playing on this MIDI channel +protected: + const IIgsInstrumentHeader *_instrument; ///< Instrument used on this MIDI channel + const int8 *_sample; ///< Sample data used on this MIDI channel + uint8 _volume; ///< MIDI controller number 7 (Volume) +}; + +/** + * Class for managing Apple IIGS sound channels. + * TODO: Check what instruments are used by default on the MIDI channels + * FIXME: Some instrument choices sound wrong + */ +class IIgsSoundMgr { +public: + typedef Common::Array::const_iterator const_iterator; + typedef Common::Array::iterator iterator; + static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects +public: + // For initializing + IIgsSoundMgr(); + void setProgramChangeMapping(const MidiProgramChangeMapping *mapping); + bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo); + bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo); + // Miscellaneous methods + uint activeSounds() const; ///< How many active sounds are playing? + void stopSounds(); ///< Stops all sounds + void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels + // For playing Apple IIGS AGI samples (Sound effects etc) + bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample); + // MIDI commands + void midiNoteOff(uint8 channel, uint8 note, uint8 velocity); + void midiNoteOn(uint8 channel, uint8 note, uint8 velocity); + void midiController(uint8 channel, uint8 controller, uint8 value); + void midiProgramChange(uint8 channel, uint8 program); + void midiPitchWheel(uint8 wheelPos); +protected: + const IIgsInstrumentHeader* getInstrument(uint8 program) const; +public: + Common::Array _midiChannels; ///< Information about each MIDI channel +protected: + Common::Array _wave; ///< Sample data used by the Apple IIGS MIDI instruments + const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping + Common::Array _instruments; ///< Instruments used by the Apple IIGS AGI +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_2GS_H */ -- cgit v1.2.3 From 0a1a9194064a96673b45d856f06dbb689838d746 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:34:45 +0000 Subject: AGI: Implement FR #1913900. FR #1913900: "AGI: MIDI support". Currently it gets selected when Adlib is chosen. Finding a better way to do it is a todo. Also default instrument mapping is plain. Based on original code by Jens. Christian Restemeier. svn-id: r49751 --- engines/agi/agi.cpp | 5 +- engines/agi/loader_v2.cpp | 2 +- engines/agi/loader_v3.cpp | 2 +- engines/agi/module.mk | 1 + engines/agi/sound.cpp | 71 +++++++--- engines/agi/sound.h | 17 ++- engines/agi/sound_midi.cpp | 340 +++++++++++++++++++++++++++++++++++++++++++++ engines/agi/sound_midi.h | 113 +++++++++++++++ 8 files changed, 524 insertions(+), 27 deletions(-) create mode 100755 engines/agi/sound_midi.cpp create mode 100755 engines/agi/sound_midi.h (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index c2c6d10bfe..d89b10bb32 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -583,10 +583,13 @@ void AgiEngine::initialize() { } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; } else { - switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) { + switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB)) { case MD_PCSPK: _soundemu = SOUND_EMU_PC; break; + case MD_ADLIB: + _soundemu = SOUND_EMU_MIDI; + break; default: _soundemu = SOUND_EMU_NONE; break; diff --git a/engines/agi/loader_v2.cpp b/engines/agi/loader_v2.cpp index 3d1c4fa2cf..de6f8d0653 100644 --- a/engines/agi/loader_v2.cpp +++ b/engines/agi/loader_v2.cpp @@ -232,7 +232,7 @@ int AgiLoader_v2::loadResource(int t, int n) { if (data != NULL) { // Freeing of the raw resource from memory is delegated to the createFromRawResource-function - _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound); + _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu); _vm->_game.dirSound[n].flags |= RES_LOADED; } else { ec = errBadResource; diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index 4227745c5f..4ee35d73eb 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -316,7 +316,7 @@ int AgiLoader_v3::loadResource(int t, int n) { data = loadVolRes(&_vm->_game.dirSound[n]); if (data != NULL) { // Freeing of the raw resource from memory is delegated to the createFromRawResource-function - _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound); + _vm->_game.sounds[n] = AgiSound::createFromRawResource(data, _vm->_game.dirSound[n].len, n, *_vm->_sound, _vm->_soundemu); _vm->_game.dirSound[n].flags |= RES_LOADED; } else { ec = errBadResource; diff --git a/engines/agi/module.mk b/engines/agi/module.mk index 3b7741443d..4f27447dbd 100644 --- a/engines/agi/module.mk +++ b/engines/agi/module.mk @@ -31,6 +31,7 @@ MODULE_OBJS := \ saveload.o \ sound.o \ sound_2gs.o \ + sound_midi.o \ sprite.o \ text.o \ view.o \ diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index 014a3dba1a..b9a118c95f 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -29,9 +29,12 @@ #include "common/random.h" #include "common/str-array.h" +#include "sound/mididrv.h" + #include "agi/agi.h" #include "agi/sound_2gs.h" +#include "agi/sound_midi.h" namespace Agi { @@ -41,7 +44,7 @@ namespace Agi { // TODO: add support for variable sampling rate in the output device // -AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager) { +AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu) { if (data == NULL || len < 2) // Check for too small resource or no resource at all return NULL; uint16 type = READ_LE_UINT16(data); @@ -50,9 +53,13 @@ AgiSound *AgiSound::createFromRawResource(uint8 *data, uint32 len, int resnum, S case AGI_SOUND_SAMPLE: return new IIgsSample(data, len, resnum, manager); case AGI_SOUND_MIDI: - return new IIgsMidi (data, len, resnum, manager); + return new IIgsMidi(data, len, resnum, manager); case AGI_SOUND_4CHN: - return new PCjrSound (data, len, resnum, manager); + if (soundemu == SOUND_EMU_MIDI) { + return new MIDISound(data, len, resnum, manager); + } else { + return new PCjrSound(data, len, resnum, manager); + } } warning("Sound resource (%d) has unknown type (0x%04x). Not using the sound", resnum, type); @@ -165,24 +172,29 @@ void SoundMgr::startSound(int resnum, int flag) { ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); break; case AGI_SOUND_4CHN: - PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; + if (_vm->_soundemu == SOUND_EMU_MIDI) { + _musicPlayer->playMIDI((MIDISound *)_vm->_game.sounds[resnum]); + } else { - // Initialize channel info - for (i = 0; i < NUM_CHANNELS; i++) { - _chn[i].type = type; - _chn[i].flags = AGI_SOUND_LOOP; + PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; - if (_env) { - _chn[i].flags |= AGI_SOUND_ENVELOPE; - _chn[i].adsr = AGI_SOUND_ENV_ATTACK; - } + // Initialize channel info + for (i = 0; i < NUM_CHANNELS; i++) { + _chn[i].type = type; + _chn[i].flags = AGI_SOUND_LOOP; + + if (_env) { + _chn[i].flags |= AGI_SOUND_ENVELOPE; + _chn[i].adsr = AGI_SOUND_ENV_ATTACK; + } - _chn[i].ins = _waveform; - _chn[i].size = WAVEFORM_SIZE; - _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); - _chn[i].timer = 0; - _chn[i].vol = 0; - _chn[i].end = 0; + _chn[i].ins = _waveform; + _chn[i].size = WAVEFORM_SIZE; + _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); + _chn[i].timer = 0; + _chn[i].vol = 0; + _chn[i].end = 0; + } } break; } @@ -213,6 +225,10 @@ void SoundMgr::stopSound() { _gsSound->stopSounds(); } + if (_vm->_soundemu == SOUND_EMU_MIDI) { + _musicPlayer->stop(); + } + _playingSound = -1; } } @@ -240,6 +256,8 @@ int SoundMgr::initSound() { break; case SOUND_EMU_COCO3: break; + case SOUND_EMU_MIDI: + break; } report("Initializing sound:\n"); @@ -251,7 +269,8 @@ int SoundMgr::initSound() { report("disabled\n"); } - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); + if (_vm->_soundemu != SOUND_EMU_MIDI) + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); return r; } @@ -607,12 +626,21 @@ SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() { _waveform = 0; _disabledMidi = false; _useChorus = true; // FIXME: Currently always true? + _midiDriver = 0; _gsSound = new IIgsSoundMgr; + + if (_vm->_soundemu == SOUND_EMU_MIDI) { + MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB); + + _midiDriver = MidiDriver::createMidi(midiDriver); + _musicPlayer = new MusicPlayer(_midiDriver, this); + } } void SoundMgr::premixerCall(int16 *data, uint len) { - fillAudio(this, data, len); + if (_vm->_soundemu != SOUND_EMU_MIDI) + fillAudio(this, data, len); } void SoundMgr::setVolume(uint8 volume) { @@ -622,6 +650,9 @@ void SoundMgr::setVolume(uint8 volume) { SoundMgr::~SoundMgr() { free(_sndBuffer); delete _gsSound; + + delete _musicPlayer; + delete _midiDriver; } } // End of namespace Agi diff --git a/engines/agi/sound.h b/engines/agi/sound.h index ab0c9e20e5..16ec81d19a 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -29,6 +29,8 @@ #include "sound/audiostream.h" #include "sound/mixer.h" +class MidiDriver; + namespace Agi { #define BUFFER_SIZE 410 @@ -40,6 +42,7 @@ namespace Agi { #define SOUND_EMU_AMIGA 4 #define SOUND_EMU_APPLE2GS 5 #define SOUND_EMU_COCO3 6 +#define SOUND_EMU_MIDI 7 #define WAVEFORM_SIZE 64 #define ENV_ATTACK 10000 /**< envelope attack rate */ @@ -143,7 +146,7 @@ public: * from memory using free() or delegate the responsibility onwards to some other * function! */ - static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + static AgiSound *createFromRawResource(uint8 *data, uint32 len, int resnum, SoundMgr &manager, int soundemu); protected: SoundMgr &_manager; ///< AGI sound manager object @@ -154,7 +157,7 @@ protected: class PCjrSound : public AgiSound { public: PCjrSound(uint8 *data, uint32 len, int resnum, SoundMgr &manager); - ~PCjrSound() { if (_data != NULL) free(_data); } + ~PCjrSound() { free(_data); } virtual uint16 type() { return _type; } const uint8 *getVoicePointer(uint voiceNum); protected: @@ -166,11 +169,11 @@ protected: class AgiEngine; class AgiBase; class IIgsSoundMgr; +class MusicPlayer; struct IIgsExeInfo; class SoundMgr : public Audio::AudioStream { - AgiBase *_vm; public: SoundMgr(AgiBase *agi, Audio::Mixer *pMixer); @@ -196,15 +199,21 @@ public: return 22050; } + int _endflag; + AgiBase *_vm; + private: Audio::Mixer *_mixer; Audio::SoundHandle _soundHandle; + + MusicPlayer *_musicPlayer; + MidiDriver *_midiDriver; + uint32 _sampleRate; bool _playing; ChannelInfo _chn[NUM_CHANNELS]; IIgsSoundMgr *_gsSound; - int _endflag; int _playingSound; uint8 _env; bool _disabledMidi; diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp new file mode 100755 index 0000000000..b31a4228fb --- /dev/null +++ b/engines/agi/sound_midi.cpp @@ -0,0 +1,340 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Code is based on: +// +// A very simple program, that converts an AGI-song into a MIDI-song. +// Feel free to use it for anything. +// +// The default instrument is "piano" for all the channels, what gives +// good results on most games. But I found, that some songs are interesting +// with other instruments. If you want to experiment, modify the "instr" +// array. +// +// Timing is not perfect, yet. It plays correct, when I use the +// Gravis-Midiplayer, but the songs are too fast when I use playmidi on +// Linux. +// +// Original program developed by Jens. Christian Restemeier +// + +// MIDI and digital music class + +#include "sound/audiostream.h" +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/config-manager.h" +#include "common/file.h" +#include "common/stream.h" + +#include "agi/agi.h" + +#include "agi/sound.h" +#include "agi/sound_midi.h" + +#define SPEED_FACTOR 6 + +namespace Agi { + +static uint32 convertSND2MIDI(byte *snddata, byte **data); + +MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + _data = data; // Save the resource pointer + _len = len; // Save the resource's length + _type = READ_LE_UINT16(data); // Read sound resource's type + _isValid = (_type == AGI_SOUND_4CHN) && (_data != NULL) && (_len >= 2); + + if (!_isValid) // Check for errors + warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len); +} + +MusicPlayer::MusicPlayer(MidiDriver *driver, SoundMgr *manager) : _parser(0), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false), _manager(manager) { + memset(_channel, 0, sizeof(_channel)); + memset(_channelVolume, 255, sizeof(_channelVolume)); + _masterVolume = 0; + this->open(); + _smfParser = MidiParser::createParser_SMF(); + _midiMusicData = NULL; +} + +MusicPlayer::~MusicPlayer() { + _driver->setTimerCallback(NULL, NULL); + stop(); + this->close(); + _smfParser->setMidiDriver(NULL); + delete _smfParser; + delete[] _midiMusicData; +} + +void MusicPlayer::setChannelVolume(int channel) { + int newVolume = _channelVolume[channel] * _masterVolume / 255; + _channel[channel]->volume(newVolume); +} + +void MusicPlayer::setVolume(int volume) { + Common::StackLock lock(_mutex); + + volume = CLIP(volume, 0, 255); + if (_masterVolume == volume) + return; + _masterVolume = volume; + + for (int i = 0; i < 16; ++i) { + if (_channel[i]) { + setChannelVolume(i); + } + } +} + +int MusicPlayer::open() { + // Don't ever call open without first setting the output driver! + if (!_driver) + return 255; + + int ret = _driver->open(); + if (ret) + return ret; + + _driver->setTimerCallback(this, &onTimer); + return 0; +} + +void MusicPlayer::close() { + stop(); + if (_driver) + _driver->close(); + _driver = 0; +} + +void MusicPlayer::send(uint32 b) { + if (_passThrough) { + _driver->send(b); + return; + } + + byte channel = (byte)(b & 0x0F); + if ((b & 0xFFF0) == 0x07B0) { + // Adjust volume changes by master volume + byte volume = (byte)((b >> 16) & 0x7F); + _channelVolume[channel] = volume; + volume = volume * _masterVolume / 255; + b = (b & 0xFF00FFFF) | (volume << 16); + } else if ((b & 0xF0) == 0xC0 && !_isGM && !_nativeMT32) { + b = (b & 0xFFFF00FF) | MidiDriver::_mt32ToGm[(b >> 8) & 0xFF] << 8; + } + else if ((b & 0xFFF0) == 0x007BB0) { + //Only respond to All Notes Off if this channel + //has currently been allocated + if (_channel[b & 0x0F]) + return; + } + + if (!_channel[channel]) { + _channel[channel] = (channel == 9) ? _driver->getPercussionChannel() : _driver->allocateChannel(); + // If a new channel is allocated during the playback, make sure + // its volume is correctly initialized. + if (_channel[channel]) + setChannelVolume(channel); + } + + if (_channel[channel]) + _channel[channel]->send(b); +} + +void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { + + switch (type) { + case 0x2F: // End of Track + stop(); + break; + default: + //warning("Unhandled meta event: %02x", type); + break; + } +} + +void MusicPlayer::onTimer(void *refCon) { + MusicPlayer *music = (MusicPlayer *)refCon; + Common::StackLock lock(music->_mutex); + + if (music->_parser) + music->_parser->onTimer(); +} + +void MusicPlayer::playMIDI(MIDISound *track) { + stop(); + + _isGM = true; + + // Convert AGI Sound data to MIDI + int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData); + + if (_smfParser->loadMusic(_midiMusicData, midiMusicSize)) { + MidiParser *parser = _smfParser; + parser->setTrack(0); + parser->setMidiDriver(this); + parser->setTimerRate(getBaseTempo()); + parser->property(MidiParser::mpCenterPitchWheelOnUnload, 1); + + _parser = parser; + + syncVolume(); + + _isPlaying = true; + } +} + +void MusicPlayer::stop() { + Common::StackLock lock(_mutex); + + if (!_isPlaying) + return; + + _isPlaying = false; + if (_parser) { + _parser->unloadMusic(); + _parser = NULL; + } + + if (_manager->_endflag != -1) + _manager->_vm->setflag(_manager->_endflag, true); +} + +void MusicPlayer::pause() { + setVolume(-1); + _isPlaying = false; +} + +void MusicPlayer::resume() { + syncVolume(); + _isPlaying = true; +} + +void MusicPlayer::syncVolume() { + int volume = ConfMan.getInt("music_volume"); + if (ConfMan.getBool("mute")) { + volume = -1; + } + setVolume(volume); +} + +/* channel / intrument setup: */ + +/* most songs are good with this: */ +unsigned char instr[] = {0, 0, 0}; + +/* cool for sq2: +unsigned char instr[] = {50, 51, 19}; +*/ + +static void writeDelta(Common::MemoryWriteStreamDynamic *st, int32 delta) { + int32 i; + + i = delta >> 21; if (i > 0) st->writeByte((i & 127) | 128); + i = delta >> 14; if (i > 0) st->writeByte((i & 127) | 128); + i = delta >> 7; if (i > 0) st->writeByte((i & 127) | 128); + st->writeByte(delta & 127); +} + +static uint32 convertSND2MIDI(byte *snddata, byte **data) { + int32 lp, ep; + int n; + double ll; + + Common::MemoryWriteStreamDynamic st; + + ll = log10(pow(2.0, 1.0 / 12.0)); + + /* Header */ + st.write("MThd", 4); + st.writeUint32BE(6); + st.writeUint16BE(1); /* mode */ + st.writeUint16BE(3); /* number of tracks */ + st.writeUint16BE(192); /* ticks / quarter */ + + for (n = 0; n < 3; n++) { + uint16 start, end, pos; + + st.write("MTrk", 4); + lp = st.pos(); + st.writeUint32BE(0); /* chunklength */ + writeDelta(&st, 0); /* set instrument */ + st.writeByte(0xc0 + n); + st.writeByte(instr[n]); + start = snddata[n * 2 + 0] | (snddata[n * 2 + 1] << 8); + end = ((snddata[n * 2 + 2] | (snddata[n * 2 + 3] << 8))) - 5; + + for (pos = start; pos < end; pos += 5) { + uint16 freq, dur; + dur = (snddata[pos + 0] | (snddata[pos + 1] << 8)) * SPEED_FACTOR; + freq = ((snddata[pos + 2] & 0x3F) << 4) + (snddata[pos + 3] & 0x0F); + if (snddata[pos + 2] > 0) { + double fr; + int note; + /* I don't know, what frequency equals midi note 0 ... */ + /* This moves the song 4 octaves down: */ + fr = (log10(111860.0 / (double)freq) / ll) - 48; + note = (int)floor(fr + 0.5); + if (note < 0) note = 0; + if (note > 127) note = 127; + /* note on */ + writeDelta(&st, 0); + st.writeByte(144 + n); + st.writeByte(note); + st.writeByte(100); + /* note off */ + writeDelta(&st, dur); + st.writeByte(128 + n); + st.writeByte(note); + st.writeByte(0); + } else { + /* note on */ + writeDelta(&st, 0); + st.writeByte(144 + n); + st.writeByte(0); + st.writeByte(0); + /* note off */ + writeDelta(&st, dur); + st.writeByte(128 + n); + st.writeByte(0); + st.writeByte(0); + } + } + writeDelta(&st, 0); + st.writeByte(0xff); + st.writeByte(0x2f); + st.writeByte(0x0); + ep = st.pos(); + st.seek(lp, SEEK_SET); + st.writeUint32BE((ep - lp) - 4); + st.seek(ep, SEEK_SET); + } + + *data = st.getData(); + + return st.pos(); +} + +} // End of namespace Agi diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h new file mode 100755 index 0000000000..48216ceb12 --- /dev/null +++ b/engines/agi/sound_midi.h @@ -0,0 +1,113 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +// Music class + +#ifndef AGI_SOUND_MIDI_H +#define AGI_SOUND_MIDI_H + +#include "sound/mididrv.h" +#include "sound/midiparser.h" +#include "common/mutex.h" + +namespace Agi { + +class MIDISound : public AgiSound { +public: + MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager); + ~MIDISound() { free(_data); } + virtual uint16 type() { return _type; } + uint8 *_data; ///< Raw sound resource data + uint32 _len; ///< Length of the raw sound resource + +protected: + uint16 _type; ///< Sound resource type +}; + +class MusicPlayer : public MidiDriver { +public: + MusicPlayer(MidiDriver *driver, SoundMgr *manager); + ~MusicPlayer(); + + bool isPlaying() { return _isPlaying; } + void setPlaying(bool playing) { _isPlaying = playing; } + + void setVolume(int volume); + int getVolume() { return _masterVolume; } + void syncVolume(); + + void setNativeMT32(bool b) { _nativeMT32 = b; } + bool hasNativeMT32() { return _nativeMT32; } + void playMIDI(MIDISound *track); + void stop(); + void pause(); + void resume(); + void setLoop(bool loop) { _looping = loop; } + void setPassThrough(bool b) { _passThrough = b; } + + void setGM(bool isGM) { _isGM = isGM; } + + // MidiDriver interface implementation + int open(); + void close(); + void send(uint32 b); + + void metaEvent(byte type, byte *data, uint16 length); + + void setTimerCallback(void *timerParam, void (*timerProc)(void *)) { } + uint32 getBaseTempo() { return _driver ? _driver->getBaseTempo() : 0; } + + // Channel allocation functions + MidiChannel *allocateChannel() { return 0; } + MidiChannel *getPercussionChannel() { return 0; } + + MidiParser *_parser; + Common::Mutex _mutex; + +protected: + + static void onTimer(void *data); + void setChannelVolume(int channel); + + MidiChannel *_channel[16]; + MidiDriver *_driver; + MidiParser *_smfParser; + byte _channelVolume[16]; + bool _nativeMT32; + bool _isGM; + bool _passThrough; + + bool _isPlaying; + bool _looping; + byte _masterVolume; + + byte *_midiMusicData; + + SoundMgr *_manager; +}; + +} // End of namespace Agi + +#endif -- cgit v1.2.3 From c7e9b620eef9973beee5f2055fb37308682d86ff Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:35:10 +0000 Subject: AGI: properly setup Sound var. svn-id: r49752 --- engines/agi/agi.h | 9 ++++++++- engines/agi/cycle.cpp | 11 ++++++++--- engines/agi/detection_tables.h | 2 +- engines/agi/sound.cpp | 4 ++-- engines/agi/sound.h | 4 ++-- 5 files changed, 21 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.h b/engines/agi/agi.h index b00b0b3d7e..4cc823df5a 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -152,7 +152,8 @@ enum AgiGameFeatures { GF_MENUS = (1 << 7), GF_ESCPAUSE = (1 << 8), GF_OLDAMIGAV20 = (1 << 9), - GF_CLIPCOORDS = (1 << 10) + GF_CLIPCOORDS = (1 << 10), + GF_2GSOLDSOUND = (1 << 11) }; struct AGIGameDescription; @@ -317,6 +318,12 @@ enum AgiComputerType { kAgiComputerAmigaOld = 20 // Older Amiga AGI interpreters' value (Seldom used) }; +enum AgiSoundType { + kAgiSoundPC = 1, + kAgiSoundTandy = 3, // Tandy (This value is also used by the Amiga AGI and Apple IIGS AGI) + kAgiSound2GSOld = 8 // Apple IIGS's Gold Rush! (Version 1.0M 1989-02-28 (CE), AGI 3.003) uses value 8 +}; + /** * AGI flags */ diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 5614195fcf..40d6f2d008 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -387,28 +387,33 @@ int AgiEngine::runGame() { _restartGame = false; } - // Set computer type (v20 i.e. vComputer) + // Set computer type (v20 i.e. vComputer) and sound type switch (getPlatform()) { case Common::kPlatformAtariST: setvar(vComputer, kAgiComputerAtariST); + setvar(vSoundgen, kAgiSoundPC); break; case Common::kPlatformAmiga: if (getFeatures() & GF_OLDAMIGAV20) setvar(vComputer, kAgiComputerAmigaOld); else setvar(vComputer, kAgiComputerAmiga); + setvar(vSoundgen, kAgiSoundTandy); break; case Common::kPlatformApple2GS: setvar(vComputer, kAgiComputerApple2GS); + if (getFeatures() & GF_2GSOLDSOUND) + setvar(vSoundgen, kAgiSound2GSOld); + else + setvar(vSoundgen, kAgiSoundTandy); break; case Common::kPlatformPC: default: setvar(vComputer, kAgiComputerPC); + setvar(vSoundgen, kAgiSoundPC); break; } - setvar(vSoundgen, 1); // IBM PC SOUND - // Set monitor type (v26 i.e. vMonitor) switch (_renderMode) { case Common::kRenderCGA: diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index 9c915b12f5..a3e95241c1 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -166,7 +166,7 @@ static const AGIGameDescription gameDescriptions[] = { // Gold Rush! (Apple IIgs) 1.0M 2/28/89 (CE) aka 2.01 12/22/88 // Menus not tested - GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformApple2GS), + GAME3_P("goldrush", "1.0M 1989-02-28 (CE) aka 2.01 1988-12-22", "grdir", "3f7b9ce62631434389f85371b11921d6", 0x3149, GF_2GSOLDSOUND, GID_GOLDRUSH, Common::kPlatformApple2GS), // Gold Rush! (ST) 1.01 1/13/89 aka 2.01 12/22/88 GAME3_P("goldrush", "1.01 1989-01-13 aka 2.01 1988-12-22", "grdir", "4dd4d50480a3d6c206fa227ce8142735", 0x3149, 0, GID_GOLDRUSH, Common::kPlatformAtariST), diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index b9a118c95f..c4c695c59e 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -142,7 +142,7 @@ void SoundMgr::unloadSound(int resnum) { void SoundMgr::startSound(int resnum, int flag) { int i; - AgiSoundType type; + AgiSoundEmuType type; if (_vm->_game.sounds[resnum] != NULL && _vm->_game.sounds[resnum]->isPlaying()) return; @@ -152,7 +152,7 @@ void SoundMgr::startSound(int resnum, int flag) { if (_vm->_game.sounds[resnum] == NULL) // Is this needed at all? return; - type = (AgiSoundType)_vm->_game.sounds[resnum]->type(); + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); if (type != AGI_SOUND_SAMPLE && type != AGI_SOUND_MIDI && type != AGI_SOUND_4CHN) return; diff --git a/engines/agi/sound.h b/engines/agi/sound.h index 16ec81d19a..d217d52ac6 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -89,7 +89,7 @@ struct CoCoNote { * as they're simply the different used values in AGI sound resources' * starts (The first 16-bit little endian word, to be precise). */ -enum AgiSoundType { +enum AgiSoundEmuType { AGI_SOUND_SAMPLE = 0x0001, AGI_SOUND_MIDI = 0x0002, AGI_SOUND_4CHN = 0x0008 @@ -110,7 +110,7 @@ enum AgiSoundEnv { * AGI engine sound channel structure. */ struct ChannelInfo { - AgiSoundType type; + AgiSoundEmuType type; const uint8 *ptr; // Pointer to the AgiNote data const int16 *ins; int32 size; -- cgit v1.2.3 From 85d8b4f5d848c0e1ec6c7b4ef3e6bdd839b05197 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:35:42 +0000 Subject: AGI: Make sure that sound variable is reset once music is stopped. svn-id: r49754 --- engines/agi/sound.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index c4c695c59e..c35b23ae55 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -231,6 +231,9 @@ void SoundMgr::stopSound() { _playingSound = -1; } + + if (_endflag != -1) + _vm->setflag(_endflag, true); } int SoundMgr::initSound() { -- cgit v1.2.3 From 6903fc7a070e33809ba277256b23fa1963e65db7 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:36:10 +0000 Subject: AGI: Implement FR #2813133. FR #2813133: "AGI: Proper Tandy 3-Voice/IBM PCjr Sound Support". Add proper Tandy music. Heavily based on NAGI source, thus attached its X11 license. To run it now use -e pcjr. Old one is still default for adlib but most likely will be changed in the future. Also lied ground for further separation of different sound generators. svn-id: r49755 --- engines/agi/agi.cpp | 9 +- engines/agi/module.mk | 1 + engines/agi/sound.cpp | 28 ++- engines/agi/sound.h | 25 ++- engines/agi/sound_pcjr.cpp | 497 +++++++++++++++++++++++++++++++++++++++++++++ engines/agi/sound_pcjr.h | 112 ++++++++++ 6 files changed, 659 insertions(+), 13 deletions(-) create mode 100755 engines/agi/sound_pcjr.cpp create mode 100755 engines/agi/sound_pcjr.h (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index d89b10bb32..2f87d7b8ef 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -583,15 +583,18 @@ void AgiEngine::initialize() { } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; } else { - switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB)) { + switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI)) { case MD_PCSPK: _soundemu = SOUND_EMU_PC; break; + case MD_PCJR: + _soundemu = SOUND_EMU_PCJR; + break; case MD_ADLIB: - _soundemu = SOUND_EMU_MIDI; + _soundemu = SOUND_EMU_NONE; break; default: - _soundemu = SOUND_EMU_NONE; + _soundemu = SOUND_EMU_MIDI; break; } } diff --git a/engines/agi/module.mk b/engines/agi/module.mk index 4f27447dbd..db640c02b5 100644 --- a/engines/agi/module.mk +++ b/engines/agi/module.mk @@ -32,6 +32,7 @@ MODULE_OBJS := \ sound.o \ sound_2gs.o \ sound_midi.o \ + sound_pcjr.o \ sprite.o \ text.o \ view.o \ diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index c35b23ae55..0a71bcabca 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -35,6 +35,7 @@ #include "agi/sound_2gs.h" #include "agi/sound_midi.h" +#include "agi/sound_pcjr.h" namespace Agi { @@ -127,6 +128,15 @@ static int noteToPeriod(int note) { } #endif +int SoundMgr::readBuffer(int16 *buffer, const int numSamples) { + if (_vm->_soundemu == SOUND_EMU_PCJR) + _soundGen->premixerCall(buffer, numSamples); + else + premixerCall(buffer, numSamples / 2); + + return numSamples; +} + void SoundMgr::unloadSound(int resnum) { if (_vm->_game.dirSound[resnum].flags & RES_LOADED) { if (_vm->_game.sounds[resnum]->isPlaying()) { @@ -174,6 +184,8 @@ void SoundMgr::startSound(int resnum, int flag) { case AGI_SOUND_4CHN: if (_vm->_soundemu == SOUND_EMU_MIDI) { _musicPlayer->playMIDI((MIDISound *)_vm->_game.sounds[resnum]); + } else if (_vm->_soundemu == SOUND_EMU_PCJR) { + _soundGen->play(resnum, flag); } else { PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; @@ -212,7 +224,8 @@ void SoundMgr::stopSound() { debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); _endflag = -1; - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { + + if (_vm->_soundemu != SOUND_EMU_APPLE2GS && _vm->_soundemu != SOUND_EMU_PCJR) { for (i = 0; i < NUM_CHANNELS; i++) stopNote(i); } @@ -229,6 +242,10 @@ void SoundMgr::stopSound() { _musicPlayer->stop(); } + if (_vm->_soundemu == SOUND_EMU_PCJR) { + _soundGen->stop(); + } + _playingSound = -1; } @@ -261,6 +278,9 @@ int SoundMgr::initSound() { break; case SOUND_EMU_MIDI: break; + case SOUND_EMU_PCJR: + _soundGen = new SoundGenPCJr(_vm); + break; } report("Initializing sound:\n"); @@ -281,6 +301,7 @@ int SoundMgr::initSound() { void SoundMgr::deinitSound() { debugC(3, kDebugLevelSound, "()"); + stopSound(); _mixer->stopHandle(_soundHandle); } @@ -617,7 +638,7 @@ void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) { data_available -= len; } -SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() { +SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) : _chn() { _vm = agi; _mixer = pMixer; _sampleRate = pMixer->getOutputRate(); @@ -630,6 +651,8 @@ SoundMgr::SoundMgr(AgiBase *agi, Audio::Mixer *pMixer) : _chn() { _disabledMidi = false; _useChorus = true; // FIXME: Currently always true? _midiDriver = 0; + _musicPlayer = 0; + _soundGen = 0; _gsSound = new IIgsSoundMgr; @@ -654,6 +677,7 @@ SoundMgr::~SoundMgr() { free(_sndBuffer); delete _gsSound; + delete _soundGen; delete _musicPlayer; delete _midiDriver; } diff --git a/engines/agi/sound.h b/engines/agi/sound.h index d217d52ac6..001b3e35c2 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -37,7 +37,7 @@ namespace Agi { #define SOUND_EMU_NONE 0 #define SOUND_EMU_PC 1 -#define SOUND_EMU_TANDY 2 +#define SOUND_EMU_PCJR 2 #define SOUND_EMU_MAC 3 #define SOUND_EMU_AMIGA 4 #define SOUND_EMU_APPLE2GS 5 @@ -126,6 +126,17 @@ struct ChannelInfo { class SoundMgr; +class SoundGen { +public: + SoundGen() {} + virtual ~SoundGen() {} + + virtual void play(int resnum, int flag) = 0; + virtual void stop(void) = 0; + + virtual void premixerCall(int16 *stream, int len) = 0; +}; + /** * AGI sound resource structure. */ @@ -167,7 +178,6 @@ protected: }; class AgiEngine; -class AgiBase; class IIgsSoundMgr; class MusicPlayer; @@ -176,15 +186,12 @@ struct IIgsExeInfo; class SoundMgr : public Audio::AudioStream { public: - SoundMgr(AgiBase *agi, Audio::Mixer *pMixer); + SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer); ~SoundMgr(); virtual void setVolume(uint8 volume); // AudioStream API - int readBuffer(int16 *buffer, const int numSamples) { - premixerCall(buffer, numSamples / 2); - return numSamples; - } + int readBuffer(int16 *buffer, const int numSamples); bool isStereo() const { return false; @@ -200,7 +207,7 @@ public: } int _endflag; - AgiBase *_vm; + AgiEngine *_vm; private: Audio::Mixer *_mixer; @@ -226,6 +233,8 @@ private: void premixerCall(int16 *buf, uint len); void fillAudio(void *udata, int16 *stream, uint len); + SoundGen *_soundGen; + public: void unloadSound(int); void playSound(); diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp new file mode 100755 index 0000000000..f00c4424bc --- /dev/null +++ b/engines/agi/sound_pcjr.cpp @@ -0,0 +1,497 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +/* Heavily based on code from NAGI + * + * COPYRIGHT AND PERMISSION NOTICE + * + * Copyright (c) 2001, 2001, 2002 Nick Sonneveld + * + * All rights reserved. + * + * Permission is hereby granted, free of charge, to any person obtaining a + * copy of this software and associated documentation files (the + * "Software"), to deal in the Software without restriction, including + * without limitation the rights to use, copy, modify, merge, publish, + * distribute, and/or sell copies of the Software, and to permit persons + * to whom the Software is furnished to do so, provided that the above + * copyright notice(s) and this permission notice appear in all copies of + * the Software and that both the above copyright notice(s) and this + * permission notice appear in supporting documentation. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS + * OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF + * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT + * OF THIRD PARTY RIGHTS. IN NO EVENT SHALL THE COPYRIGHT HOLDER OR + * HOLDERS INCLUDED IN THIS NOTICE BE LIABLE FOR ANY CLAIM, OR ANY SPECIAL + * INDIRECT OR CONSEQUENTIAL DAMAGES, OR ANY DAMAGES WHATSOEVER RESULTING + * FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, + * NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION + * WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. + * + * Except as contained in this notice, the name of a copyright holder + * shall not be used in advertising or otherwise to promote the sale, use + * or other dealings in this Software without prior written authorization + * + */ + +#include "agi/agi.h" +#include "agi/sound.h" +#include "agi/sound_pcjr.h" + +namespace Agi { + +// "fade out" or possibly "dissolve" +// v2.9xx +const int8 dissolveDataV2[] = { + -2, -3, -2, -1, + 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, + -100 +}; + +// v3 +const int8 dissolveDataV3[] = { + -2, -3, -2, -1, + 0x00, 0x00, 0x00, 0x00, 0x00, + 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, + 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, + 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, 0x03, + 0x04, 0x04, 0x04, 0x04, 0x04, + 0x05, 0x05, 0x05, 0x05, 0x05, + 0x06, 0x06, 0x06, 0x06, 0x06, + 0x07, 0x07, 0x07, 0x07, + 0x08, 0x08, 0x08, 0x08, + 0x09, 0x09, 0x09, 0x09, + 0x0A, 0x0A, 0x0A, 0x0A, + 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, 0x0B, + 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, 0x0C, + 0x0D, + -100 +}; + + +SoundGenPCJr::SoundGenPCJr(AgiEngine *vm) : _vm(vm) { + _chanAllocated = 10240; // preallocate something which will most likely fit + _chanData = (int16 *)malloc(_chanAllocated << 1); + + // Pick dissolve method + // + // 0 = no dissolve.. just play for as long as it's meant to be played + // this was used in older v2.4 and under games i THINK + // 1 = not used + // 2 = v2.9+ games used a shorter dissolve + // 3 (default) = v3 games used this dissolve pattern.. slightly longer + if (_vm->getVersion() >= 0x3000) + _dissolveMethod = 3; + else if (_vm->getVersion() >= 0x2900) + _dissolveMethod = 2; + else + _dissolveMethod = 0; +} + +SoundGenPCJr::~SoundGenPCJr() { + free(_chanData); +} + +void SoundGenPCJr::play(int resnum, int flag) { + PCjrSound *pcjrSound = (PCjrSound *)_vm->_game.sounds[resnum]; + + for (int i = 0; i < CHAN_MAX; i++) { + _channel[i].data = pcjrSound->getVoicePointer(i % 4); + _channel[i].duration = 0; + _channel[i].avail = 0xffff; + _channel[i].dissolveCount = 0xFFFF; + _channel[i].attenuation = 0; + _channel[i].attenuationCopy = 0; + + _tchannel[i].avail = 1; + _tchannel[i].noteCount = 0; + _tchannel[i].freqCount = 250; + _tchannel[i].freqCountPrev = -1; + _tchannel[i].atten = 0xF; // silence + _tchannel[i].genType = kGenTone; + _tchannel[i].genTypePrev = -1; + } +} + +void SoundGenPCJr::stop(void) { + int i; + + for (i = 0; i < CHAN_MAX ; i++) { + _channel[i].avail = 0; + _tchannel[i].avail = 0; + } +} + +int SoundGenPCJr::volumeCalc(SndGenChan *chan) { + int8 attenuation, dissolveValue; + + const int8 *dissolveData; + + switch (_dissolveMethod) { + case 2: + dissolveData = dissolveDataV2; + break; + case 3: + default: + dissolveData = dissolveDataV3; + break; + } + + assert(chan); + + attenuation = chan->attenuation; + if (attenuation != 0x0F) { // != silence + if (chan->dissolveCount != 0xFFFF) { + dissolveValue = dissolveData[chan->dissolveCount]; + if (dissolveValue == -100) { // if at end of list + chan->dissolveCount = 0xFFFF; + chan->attenuation = chan->attenuationCopy; + attenuation = chan->attenuation; + } else { + chan->dissolveCount++; + + attenuation += dissolveValue; + if (attenuation < 0) + attenuation = 0; + if (attenuation > 0x0F) + attenuation = 0x0F; + + chan->attenuationCopy = attenuation; + + attenuation &= 0x0F; + attenuation += _vm->getvar(vVolume); + if (attenuation > 0x0F) + attenuation = 0x0F; + } + } + //if (computer_type == 2) && (attenuation < 8) + if (attenuation < 8) + attenuation += 2; + } + + return attenuation; +} + +// read the next channel data.. fill it in *tone +// if tone isn't touched.. it should be inited so it just plays silence +// return 0 if it's passing more data +// return -1 if it's passing nothing (end of data) +int SoundGenPCJr::getNextNote(int ch, Tone *tone) { + SndGenChan *chan; + const byte *data; + + assert(tone); + assert(ch < CHAN_MAX); + + if (!_vm->getflag(fSoundOn)) + return -1; + + chan = &_channel[ch]; + if (!chan->avail) + return -1; + + while ((chan->duration == 0) && (chan->duration != 0xFFFF)) { + data = chan->data; + + // read the duration of the note + chan->duration = READ_LE_UINT16(data); // duration + + // if it's 0 then it's not going to be played + // if it's 0xFFFF then the channel data has finished. + if ((chan->duration != 0) && (chan->duration != 0xFFFF)) { + // only tone channels dissolve + if ((ch != 3) && (_dissolveMethod != 0)) // != noise?? + chan->dissolveCount = 0; + + // attenuation (volume) + chan->attenuation = data[4] & 0xF; + + // frequency + if (ch < (CHAN_MAX - 1)) { + chan->freqCount = (uint16)data[2] & 0x3F; + chan->freqCount <<= 4; + chan->freqCount |= data[3] & 0x0F; + + chan->genType = kGenTone; + } else { + int noiseFreq; + + // check for white noise (1) or periodic (0) + chan->genType = (data[3] & 0x04) ? kGenWhite : kGenPeriod; + + noiseFreq = data[3] & 0x03; + + switch (noiseFreq) { + case 0: + chan->freqCount = 32; + break; + case 1: + chan->freqCount = 64; + break; + case 2: + chan->freqCount = 128; + break; + case 3: + chan->freqCount = _channel[2].freqCount * 2; + break; + } + } + } + // data now points to the next data seg-a-ment + chan->data += 5; + } + + if (chan->duration != 0xFFFF) { + tone->freqCount = chan->freqCount; + tone->atten = volumeCalc(chan); // calc volume, sent vol is different from saved vol + tone->type = chan->genType; + chan->duration--; + } else { + // kill channel + chan->avail = 0; + chan->attenuation = 0x0F; // silent + chan->attenuationCopy = 0x0F; // dunno really + + return -1; + } + + return 0; +} + +// Formulas for noise generator +// bit0 = output + +// noise feedback for white noise mode +#define FB_WNOISE 0x12000 // bit15.d(16bits) = bit0(out) ^ bit2 +//#define FB_WNOISE 0x14000 // bit15.d(16bits) = bit0(out) ^ bit1 +//#define FB_WNOISE 0x28000 // bit16.d(17bits) = bit0(out) ^ bit2 (same to AY-3-8910) +//#define FB_WNOISE 0x50000 // bit17.d(18bits) = bit0(out) ^ bit2 + +// noise feedback for periodic noise mode +// it is correct maybe (it was in the Megadrive sound manual) +//#define FB_PNOISE 0x10000 // 16bit rorate +#define FB_PNOISE 0x08000 + +// noise generator start preset (for periodic noise) +#define NG_PRESET 0x0f35 + +//#define WAVE_HEIGHT (0x7FFF) + +// Volume table. +// +// 2dB = 20*log(a/b) +// 10^(2/20)*b = a; +// value = 0x7fff; +// value /= 1.258925411794; +const int16 volTable[16] = { + 32767, 26027, 20674, 16422, 13044, 10361, 8230, 6537, 5193, 4125, 3276, 2602, 2067, 1642, 1304, 0 +}; + +#define FREQ_DIV 111844 +#define MULT FREQ_DIV + +// fill buff +int SoundGenPCJr::chanGen(int chan, int16 *stream, int len) { + ToneChan *tpcm; + Tone toneNew; + int fillSize; + int retVal; + + tpcm = &_tchannel[chan]; + + retVal = -1; + + while (len > 0) { + if (tpcm->noteCount <= 0) { + // get new tone data + toneNew.freqCount = 0; + toneNew.atten = 0xF; + toneNew.type = kGenTone; + if ((tpcm->avail) && (getNextNote(chan, &toneNew) == 0)) { + tpcm->atten = toneNew.atten; + tpcm->freqCount = toneNew.freqCount; + tpcm->genType = toneNew.type; + + // setup counters 'n stuff + // SAMPLE_RATE samples per sec.. tone changes 60 times per sec + tpcm->noteCount = SAMPLE_RATE / 60; + retVal = 0; + } else { + // if it doesn't return an + tpcm->genType = kGenSilence; + tpcm->noteCount = len; + tpcm->avail = 0; + } + } + + // write nothing + if ((tpcm->freqCount == 0) || (tpcm->atten == 0xf)) { + tpcm->genType = kGenSilence; + } + + // find which is smaller.. the buffer or the + fillSize = (tpcm->noteCount <= len) ? tpcm->noteCount : len; + + switch (tpcm->genType) { + case kGenTone: + fillSize = fillSquare(tpcm, stream, fillSize); + break; + case kGenPeriod: + case kGenWhite: + fillSize = fillNoise(tpcm, stream, fillSize); + break; + case kGenSilence: + default: + // fill with whitespace + memset(stream, 0, fillSize * sizeof(int16)); + break; + } + + tpcm->noteCount -= fillSize; + stream += fillSize; + len -= fillSize; + } + + return retVal; +} + +int SoundGenPCJr::fillSquare(ToneChan *t, int16 *buf, int len) { + int count; + + if (t->genType != t->genTypePrev) { + // make sure the freqCount is checked + t->freqCountPrev = -1; + t->sign = 1; + t->genTypePrev = t->genType; + } + + if (t->freqCount != t->freqCountPrev) { + //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5); + t->scale = (SAMPLE_RATE / 2) * t->freqCount; + t->count = t->scale; + t->freqCountPrev = t->freqCount; + } + + count = len; + + while (count > 0) { + *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten]; + count--; + + // get next sample + t->count -= MULT; + while (t->count <= 0) { + t->sign ^= 1; + t->count += t->scale; + } + } + + return len; +} + +int SoundGenPCJr::fillNoise(ToneChan *t, int16 *buf, int len) { + int count; + + if (t->genType != t->genTypePrev) { + // make sure the freqCount is checked + t->freqCountPrev = -1; + t->genTypePrev = t->genType; + } + + if (t->freqCount != t->freqCountPrev) { + //t->scale = (int)( (double)t->samp->freq*t->freqCount/FREQ_DIV * MULT + 0.5); + t->scale = (SAMPLE_RATE / 2) * t->freqCount; + t->count = t->scale; + t->freqCountPrev = t->freqCount; + + t->feedback = (t->genType == kGenWhite) ? FB_WNOISE : FB_PNOISE; + // reset noise shifter + t->noiseState = NG_PRESET; + t->sign = t->noiseState & 1; + } + + count = len; + + while (count > 0) { + *(buf++) = t->sign ? volTable[t->atten] : -volTable[t->atten]; + count--; + + // get next sample + t->count -= MULT; + while (t->count <= 0) { + if (t->noiseState & 1) + t->noiseState ^= t->feedback; + + t->noiseState >>= 1; + t->sign = t->noiseState & 1; + t->count += t->scale; + } + } + + return len; +} + +void SoundGenPCJr::premixerCall(int16 *stream, int len) { + int streamCount; + int16 *sPtr, *cPtr; + + if (_chanAllocated < len) { + free(_chanData); + _chanData = (int16 *)malloc(len << 1); + _chanAllocated = len; + } + memset(stream, 0, len << 1); + + assert(stream); + + for (int i = 0; i < CHAN_MAX; i++) { + // get channel data(chan.userdata) + if (chanGen(i, _chanData, len) == 0) { + // divide by number of channels then add to stream + streamCount = len; + sPtr = stream; + cPtr = _chanData; + + while (streamCount--) + *(sPtr++) += *(cPtr++) / CHAN_MAX; + } + } +} + +} // End of namespace Agi diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h new file mode 100755 index 0000000000..9ef9aa2385 --- /dev/null +++ b/engines/agi/sound_pcjr.h @@ -0,0 +1,112 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef AGI_SOUND_PCJR_H +#define AGI_SOUND_PCJR_H + +namespace Agi { + +#define CHAN_MAX 4 + +#define SAMPLE_RATE 22050 + +enum GenType { + kGenSilence, + kGenTone, + kGenPeriod, + kGenWhite +}; + +struct SndGenChan { + const byte *data; + uint16 duration; + uint16 avail; // turned on (1) but when the channel's data runs out, it's set to (0) + uint16 dissolveCount; + byte attenuation; + byte attenuationCopy; + + GenType genType; + + // for the sample mixer + int freqCount; +}; + +struct ToneChan { + int avail; + + int noteCount; // length of tone.. duration + + int freqCount; + int freqCountPrev; + int atten; // volume + + GenType genType; + int genTypePrev; + + int count; + int scale; + int sign; + unsigned int noiseState; /* noise generator */ + int feedback; /* noise feedback mask */ +}; + +struct Tone { + int freqCount; + int atten; + GenType type; +}; + +class SoundGenPCJr : public SoundGen { +public: + SoundGenPCJr(AgiEngine *vm); + ~SoundGenPCJr(); + + void play(int resnum, int flag); + void stop(void); + + void premixerCall(int16 *stream, int len); + +private: + int getNextNote(int ch, Tone *tone); + int volumeCalc(SndGenChan *chan); + + int chanGen(int chan, int16 *stream, int len); + + int fillNoise(ToneChan *t, int16 *buf, int len); + int fillSquare(ToneChan *t, int16 *buf, int len); + +private: + AgiEngine *_vm; + SndGenChan _channel[CHAN_MAX]; + ToneChan _tchannel[CHAN_MAX]; + int16 *_chanData; + int _chanAllocated; + + int _dissolveMethod; +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_PCJR_H */ -- cgit v1.2.3 From ceb2909e0ad0ee4db8846bc2e6e9009364e24731 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:36:54 +0000 Subject: AGI: Split all sound generators into separate modules. Now the sound subsystem of the engine finally is possible to grasp. Also now it is obvious why CoCo3 sounds are not functioning. svn-id: r49757 --- engines/agi/module.mk | 2 + engines/agi/sound.cpp | 553 ++++--------------------------------------- engines/agi/sound.h | 141 ++--------- engines/agi/sound_2gs.cpp | 259 +++++++++++++++++--- engines/agi/sound_2gs.h | 58 ++++- engines/agi/sound_coco3.cpp | 80 +++++++ engines/agi/sound_coco3.h | 73 ++++++ engines/agi/sound_midi.cpp | 41 ++-- engines/agi/sound_midi.h | 13 +- engines/agi/sound_pcjr.cpp | 23 +- engines/agi/sound_pcjr.h | 25 +- engines/agi/sound_sarien.cpp | 357 ++++++++++++++++++++++++++++ engines/agi/sound_sarien.h | 120 ++++++++++ 13 files changed, 1036 insertions(+), 709 deletions(-) create mode 100644 engines/agi/sound_coco3.cpp create mode 100755 engines/agi/sound_coco3.h create mode 100644 engines/agi/sound_sarien.cpp create mode 100755 engines/agi/sound_sarien.h (limited to 'engines') diff --git a/engines/agi/module.mk b/engines/agi/module.mk index db640c02b5..2339d1019f 100644 --- a/engines/agi/module.mk +++ b/engines/agi/module.mk @@ -31,8 +31,10 @@ MODULE_OBJS := \ saveload.o \ sound.o \ sound_2gs.o \ + sound_coco3.o \ sound_midi.o \ sound_pcjr.o \ + sound_sarien.o \ sprite.o \ text.o \ view.o \ diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index 0a71bcabca..2ca2706259 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -23,6 +23,15 @@ * */ +#include "agi/agi.h" + +#include "agi/sound_2gs.h" +#include "agi/sound_coco3.h" +#include "agi/sound_midi.h" +#include "agi/sound_sarien.h" +#include "agi/sound_pcjr.h" + +#if 0 #include "common/md5.h" #include "common/config-manager.h" #include "common/fs.h" @@ -31,16 +40,11 @@ #include "sound/mididrv.h" -#include "agi/agi.h" -#include "agi/sound_2gs.h" -#include "agi/sound_midi.h" -#include "agi/sound_pcjr.h" +#endif namespace Agi { -#define USE_INTERPOLATION - // // TODO: add support for variable sampling rate in the output device // @@ -84,59 +88,17 @@ const uint8 *PCjrSound::getVoicePointer(uint voiceNum) { return _data + voiceStartOffset; } -static const int16 waveformRamp[WAVEFORM_SIZE] = { - 0, 8, 16, 24, 32, 40, 48, 56, - 64, 72, 80, 88, 96, 104, 112, 120, - 128, 136, 144, 152, 160, 168, 176, 184, - 192, 200, 208, 216, 224, 232, 240, 255, - 0, -248, -240, -232, -224, -216, -208, -200, - -192, -184, -176, -168, -160, -152, -144, -136, - -128, -120, -112, -104, -96, -88, -80, -72, - -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up -}; - -static const int16 waveformSquare[WAVEFORM_SIZE] = { - 255, 230, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 220, - 220, 220, 220, 220, 220, 220, 220, 110, - -255, -230, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -220, -220, -220, -220, -220, - -220, -220, -220, -110, 0, 0, 0, 0 // Square -}; - -static const int16 waveformMac[WAVEFORM_SIZE] = { - 45, 110, 135, 161, 167, 173, 175, 176, - 156, 137, 123, 110, 91, 72, 35, -2, - -60, -118, -142, -165, -170, -176, -177, -179, - -177, -176, -164, -152, -117, -82, -17, 47, - 92, 137, 151, 166, 170, 173, 171, 169, - 151, 133, 116, 100, 72, 43, -7, -57, - -99, -141, -156, -170, -174, -177, -178, -179, - -175, -172, -165, -159, -137, -114, -67, -19 -}; - +#if 0 static const uint16 period[] = { 1024, 1085, 1149, 1218, 1290, 1367, 1448, 1534, 1625, 1722, 1825, 1933 }; -#if 0 static int noteToPeriod(int note) { return 10 * (period[note % 12] >> (note / 12 - 3)); } #endif -int SoundMgr::readBuffer(int16 *buffer, const int numSamples) { - if (_vm->_soundemu == SOUND_EMU_PCJR) - _soundGen->premixerCall(buffer, numSamples); - else - premixerCall(buffer, numSamples / 2); - - return numSamples; -} - void SoundMgr::unloadSound(int resnum) { if (_vm->_game.dirSound[resnum].flags & RES_LOADED) { if (_vm->_game.sounds[resnum]->isPlaying()) { @@ -151,7 +113,6 @@ void SoundMgr::unloadSound(int resnum) { } void SoundMgr::startSound(int resnum, int flag) { - int i; AgiSoundEmuType type; if (_vm->_game.sounds[resnum] != NULL && _vm->_game.sounds[resnum]->isPlaying()) @@ -172,46 +133,8 @@ void SoundMgr::startSound(int resnum, int flag) { debugC(3, kDebugLevelSound, "startSound(resnum = %d, flag = %d) type = %d", resnum, flag, type); - switch (type) { - case AGI_SOUND_SAMPLE: { - IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; - _gsSound->playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); - break; - } - case AGI_SOUND_MIDI: - ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); - break; - case AGI_SOUND_4CHN: - if (_vm->_soundemu == SOUND_EMU_MIDI) { - _musicPlayer->playMIDI((MIDISound *)_vm->_game.sounds[resnum]); - } else if (_vm->_soundemu == SOUND_EMU_PCJR) { - _soundGen->play(resnum, flag); - } else { - - PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; - - // Initialize channel info - for (i = 0; i < NUM_CHANNELS; i++) { - _chn[i].type = type; - _chn[i].flags = AGI_SOUND_LOOP; - - if (_env) { - _chn[i].flags |= AGI_SOUND_ENVELOPE; - _chn[i].adsr = AGI_SOUND_ENV_ATTACK; - } - - _chn[i].ins = _waveform; - _chn[i].size = WAVEFORM_SIZE; - _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); - _chn[i].timer = 0; - _chn[i].vol = 0; - _chn[i].end = 0; - } - } - break; - } + _soundGen->play(resnum); - memset(_sndBuffer, 0, BUFFER_SIZE << 1); _endflag = flag; // Nat Budin reports that the flag should be reset when sound starts @@ -219,32 +142,15 @@ void SoundMgr::startSound(int resnum, int flag) { } void SoundMgr::stopSound() { - int i; - debugC(3, kDebugLevelSound, "stopSound() --> %d", _playingSound); _endflag = -1; - if (_vm->_soundemu != SOUND_EMU_APPLE2GS && _vm->_soundemu != SOUND_EMU_PCJR) { - for (i = 0; i < NUM_CHANNELS; i++) - stopNote(i); - } - if (_playingSound != -1) { if (_vm->_game.sounds[_playingSound]) // sanity checking _vm->_game.sounds[_playingSound]->stop(); - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - _gsSound->stopSounds(); - } - - if (_vm->_soundemu == SOUND_EMU_MIDI) { - _musicPlayer->stop(); - } - - if (_vm->_soundemu == SOUND_EMU_PCJR) { - _soundGen->stop(); - } + _soundGen->stop(); _playingSound = -1; } @@ -254,432 +160,57 @@ void SoundMgr::stopSound() { } int SoundMgr::initSound() { - int r = -1; + return -1; +} - memset(_sndBuffer, 0, BUFFER_SIZE << 1); - _env = false; +void SoundMgr::deinitSound() { + stopSound(); + + delete _soundGen; +} + +void SoundMgr::soundIsFinished() { + if (_endflag != -1) + _vm->setflag(_endflag, true); + + if (_playingSound != -1) + _vm->_game.sounds[_playingSound]->stop(); + _playingSound = -1; + _endflag = -1; +} + +SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) { + _vm = agi; + _endflag = -1; + _playingSound = -1; switch (_vm->_soundemu) { case SOUND_EMU_NONE: - _waveform = waveformRamp; - _env = true; - break; case SOUND_EMU_AMIGA: case SOUND_EMU_PC: - _waveform = waveformSquare; - break; case SOUND_EMU_MAC: - _waveform = waveformMac; + _soundGen = new SoundGenSarien(_vm, pMixer); + break; + case SOUND_EMU_PCJR: + _soundGen = new SoundGenPCJr(_vm, pMixer); break; case SOUND_EMU_APPLE2GS: - _disabledMidi = !loadInstruments(); + _soundGen = new SoundGen2GS(_vm, pMixer); break; case SOUND_EMU_COCO3: + _soundGen = new SoundGenCoCo3(_vm, pMixer); break; case SOUND_EMU_MIDI: + _soundGen = new SoundGenMIDI(_vm, pMixer); break; - case SOUND_EMU_PCJR: - _soundGen = new SoundGenPCJr(_vm); - break; - } - - report("Initializing sound:\n"); - - report("sound: envelopes "); - if (_env) { - report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN); - } else { - report("disabled\n"); - } - - if (_vm->_soundemu != SOUND_EMU_MIDI) - _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); - - return r; -} - -void SoundMgr::deinitSound() { - debugC(3, kDebugLevelSound, "()"); - - stopSound(); - _mixer->stopHandle(_soundHandle); -} - -void SoundMgr::stopNote(int i) { - _chn[i].adsr = AGI_SOUND_ENV_RELEASE; - - if (_useChorus) { - // Stop chorus ;) - if (_chn[i].type == AGI_SOUND_4CHN && - _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - stopNote(i + 4); - } - } -} - -void SoundMgr::playNote(int i, int freq, int vol) { - if (!_vm->getflag(fSoundOn)) - vol = 0; - else if (vol && _vm->_soundemu == SOUND_EMU_PC) - vol = 160; - - _chn[i].phase = 0; - _chn[i].freq = freq; - _chn[i].vol = vol; - _chn[i].env = 0x10000; - _chn[i].adsr = AGI_SOUND_ENV_ATTACK; - - if (_useChorus) { - // Add chorus ;) - if (_chn[i].type == AGI_SOUND_4CHN && - _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - - int newfreq = freq * 1007 / 1000; - - if (freq == newfreq) - newfreq++; - - playNote(i + 4, newfreq, vol * 2 / 3); - } - } -} - -static int cocoFrequencies[] = { - 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, - 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, - 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987, - 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975, - 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951 -}; - -void SoundMgr::playCoCoSound() { - int i = 0; - CoCoNote note; - - do { - note.read(_chn[i].ptr); - - if (note.freq != 0xff) { - playNote(0, cocoFrequencies[note.freq], note.volume); - - uint32 start_time = _vm->_system->getMillis(); - - while (_vm->_system->getMillis() < start_time + note.duration) { - _vm->_system->updateScreen(); - - _vm->_system->delayMillis(10); - } - } - } while (note.freq != 0xff); -} - -void SoundMgr::playAgiSound() { - int i; - AgiNote note; - - _playing = false; - for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) { - _playing |= !_chn[i].end; - note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer) - - if (_chn[i].end) - continue; - - if ((--_chn[i].timer) <= 0) { - stopNote(i); - - if (note.freqDiv != 0) { - int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2); - playNote(i, note.freqDiv * 10, volume); - } - - _chn[i].timer = note.duration; - - if (_chn[i].timer == 0xffff) { - _chn[i].end = 1; - _chn[i].vol = 0; - _chn[i].env = 0; - - if (_useChorus) { - // chorus - if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { - _chn[i + 4].vol = 0; - _chn[i + 4].env = 0; - } - } - } - _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note) - } - } -} - -void SoundMgr::playSound() { - int i; - - if (_endflag == -1) - return; - - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - if (_playingSound != -1) { - if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) { - playMidiSound(); - //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented"); - } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) { - //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample"); - playSampleSound(); - } - } - } else if (_vm->_soundemu == SOUND_EMU_COCO3) { - playCoCoSound(); - } else { - //debugC(3, kDebugLevelSound, "playSound: Trying to play a PCjr 4-channel sound"); - playAgiSound(); - } - - if (!_playing) { - if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { - for (i = 0; i < NUM_CHANNELS; _chn[i++].vol = 0) - ; - } - - if (_endflag != -1) - _vm->setflag(_endflag, true); - - if (_playingSound != -1) - _vm->_game.sounds[_playingSound]->stop(); - _playingSound = -1; - _endflag = -1; } } -uint32 SoundMgr::mixSound() { - register int i, p; - const int16 *src; - int c, b, m; - - memset(_sndBuffer, 0, BUFFER_SIZE << 1); - - if (!_playing || _playingSound == -1) - return BUFFER_SIZE; - - // Handle Apple IIGS sound mixing here - // TODO: Implement playing both waves in an oscillator - // TODO: Implement swap-mode in an oscillator - if (_vm->_soundemu == SOUND_EMU_APPLE2GS) { - for (uint midiChan = 0; midiChan < _gsSound->_midiChannels.size(); midiChan++) { - for (uint gsChan = 0; gsChan < _gsSound->_midiChannels[midiChan]._gsChannels.size(); gsChan++) { - IIgsChannelInfo &channel = _gsSound->_midiChannels[midiChan]._gsChannels[gsChan]; - if (channel.playing()) { // Only mix in actively playing channels - // Frequency multiplier was 1076.0 based on tests made with MESS 0.117. - // Tests made with KEGS32 averaged the multiplier to around 1045. - // So this is a guess but maybe it's 1046.5... i.e. C6's frequency? - double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note)); - channel.posAdd = doubleToFrac(hertz / getRate()); - channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0); - double tempVol = fracToDouble(channel.vol)/127.0; - for (i = 0; i < IIGS_BUFFER_SIZE; i++) { - b = channel.relocatedSample[fracToInt(channel.pos)]; - // TODO: Find out what volume/amplification setting is loud enough - // but still doesn't clip when playing many channels on it. - _sndBuffer[i] += (int16) (b * tempVol * 256/4); - channel.pos += channel.posAdd; - - if (channel.pos >= intToFrac(channel.size)) { - if (channel.loop) { - // Don't divide by zero on zero length samples - channel.pos %= intToFrac(channel.size + (channel.size == 0)); - // Probably we should loop the envelope too - channel.envSeg = 0; - channel.envVol = channel.startEnvVol; - } else { - channel.pos = channel.chanVol = 0; - channel.end = true; - break; - } - } - } - - if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) { - const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg]; - // I currently assume enveloping works with the same speed as the MIDI - // (i.e. with 1/60ths of a second ticks). - // TODO: Check if enveloping really works with the same speed as MIDI - frac_t envVolDelta = doubleToFrac(seg.inc/256.0); - if (intToFrac(seg.bp) >= channel.envVol) { - channel.envVol += envVolDelta; - if (channel.envVol >= intToFrac(seg.bp)) { - channel.envVol = intToFrac(seg.bp); - channel.envSeg += 1; - } - } else { - channel.envVol -= envVolDelta; - if (channel.envVol <= intToFrac(seg.bp)) { - channel.envVol = intToFrac(seg.bp); - channel.envSeg += 1; - } - } - } - } - } - } - _gsSound->removeStoppedSounds(); - return IIGS_BUFFER_SIZE; - } // else ... - - // Handle PCjr 4-channel sound mixing here - for (c = 0; c < NUM_CHANNELS; c++) { - if (!_chn[c].vol) - continue; - - m = _chn[c].flags & AGI_SOUND_ENVELOPE ? - _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol; - - if (_chn[c].type != AGI_SOUND_4CHN || c != 3) { - src = _chn[c].ins; - - p = _chn[c].phase; - for (i = 0; i < BUFFER_SIZE; i++) { - b = src[p >> 8]; -#ifdef USE_INTERPOLATION - b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8; -#endif - _sndBuffer[i] += (b * m) >> 4; - - p += (uint32) 118600 *4 / _chn[c].freq; - - // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what - // needs fixing, or remove it! - // FIXME - if (_chn[c].flags & AGI_SOUND_LOOP) { - p %= _chn[c].size << 8; - } else { - if (p >= _chn[c].size << 8) { - p = _chn[c].vol = 0; - _chn[c].end = 1; - break; - } - } - - } - _chn[c].phase = p; - } else { - // Add white noise - for (i = 0; i < BUFFER_SIZE; i++) { - b = _vm->_rnd->getRandomNumber(255) - 128; - _sndBuffer[i] += (b * m) >> 4; - } - } - - switch (_chn[c].adsr) { - case AGI_SOUND_ENV_ATTACK: - // not implemented - _chn[c].adsr = AGI_SOUND_ENV_DECAY; - break; - case AGI_SOUND_ENV_DECAY: - if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) { - _chn[c].env -= ENV_DECAY; - } else { - _chn[c].env = _chn[c].vol * ENV_SUSTAIN; - _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN; - } - break; - case AGI_SOUND_ENV_SUSTAIN: - break; - case AGI_SOUND_ENV_RELEASE: - if (_chn[c].env >= ENV_RELEASE) { - _chn[c].env -= ENV_RELEASE; - } else { - _chn[c].env = 0; - } - } - } - - return BUFFER_SIZE; -} - -/** - * Convert sample from 8-bit unsigned to 8-bit signed format. - * @param source Source stream containing the 8-bit unsigned sample data. - * @param dest Destination buffer for the 8-bit signed sample data. - * @param length Length of the sample data to be converted. - */ -bool SoundMgr::convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { - // Convert the wave from 8-bit unsigned to 8-bit signed format - for (uint i = 0; i < length; i++) - dest[i] = (int8) ((int) source.readByte() - 128); - return !(source.eos() || source.err()); -} - -void SoundMgr::fillAudio(void *udata, int16 *stream, uint len) { - SoundMgr *soundMgr = (SoundMgr *)udata; - uint32 p = 0; - - // current number of audio bytes in _sndBuffer - static uint32 data_available = 0; - // offset of start of audio bytes in _sndBuffer - static uint32 data_offset = 0; - - len <<= 2; - - debugC(5, kDebugLevelSound, "(%p, %p, %d)", (void *)udata, (void *)stream, len); - - while (len > data_available) { - memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); - p += data_available; - len -= data_available; - - soundMgr->playSound(); - data_available = soundMgr->mixSound() << 1; - data_offset = 0; - } - - memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); - data_offset += len; - data_available -= len; -} - -SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) : _chn() { - _vm = agi; - _mixer = pMixer; - _sampleRate = pMixer->getOutputRate(); - _endflag = -1; - _playingSound = -1; - _env = false; - _playing = false; - _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); - _waveform = 0; - _disabledMidi = false; - _useChorus = true; // FIXME: Currently always true? - _midiDriver = 0; - _musicPlayer = 0; - _soundGen = 0; - - _gsSound = new IIgsSoundMgr; - - if (_vm->_soundemu == SOUND_EMU_MIDI) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB); - - _midiDriver = MidiDriver::createMidi(midiDriver); - _musicPlayer = new MusicPlayer(_midiDriver, this); - } -} - -void SoundMgr::premixerCall(int16 *data, uint len) { - if (_vm->_soundemu != SOUND_EMU_MIDI) - fillAudio(this, data, len); -} - void SoundMgr::setVolume(uint8 volume) { // TODO } SoundMgr::~SoundMgr() { - free(_sndBuffer); - delete _gsSound; - - delete _soundGen; - delete _musicPlayer; - delete _midiDriver; } } // End of namespace Agi diff --git a/engines/agi/sound.h b/engines/agi/sound.h index 001b3e35c2..63b36e017c 100644 --- a/engines/agi/sound.h +++ b/engines/agi/sound.h @@ -26,15 +26,10 @@ #ifndef AGI_SOUND_H #define AGI_SOUND_H -#include "sound/audiostream.h" #include "sound/mixer.h" -class MidiDriver; - namespace Agi { -#define BUFFER_SIZE 410 - #define SOUND_EMU_NONE 0 #define SOUND_EMU_PC 1 #define SOUND_EMU_PCJR 2 @@ -44,13 +39,6 @@ namespace Agi { #define SOUND_EMU_COCO3 6 #define SOUND_EMU_MIDI 7 -#define WAVEFORM_SIZE 64 -#define ENV_ATTACK 10000 /**< envelope attack rate */ -#define ENV_DECAY 1000 /**< envelope decay rate */ -#define ENV_SUSTAIN 100 /**< envelope sustain level */ -#define ENV_RELEASE 7500 /**< envelope release rate */ -#define NUM_CHANNELS 7 /**< number of sound channels */ - /** * AGI sound note structure. */ @@ -70,19 +58,6 @@ struct AgiNote { } }; -struct CoCoNote { - uint8 freq; - uint8 volume; - uint16 duration; ///< Note duration - - /** Reads a CoCoNote through the given pointer. */ - void read(const uint8 *ptr) { - freq = *ptr; - volume = *(ptr + 1); - duration = READ_LE_UINT16(ptr + 2); - } -}; - /** * AGI sound resource types. * It's probably coincidence that all the values here are powers of two @@ -94,47 +69,26 @@ enum AgiSoundEmuType { AGI_SOUND_MIDI = 0x0002, AGI_SOUND_4CHN = 0x0008 }; -enum AgiSoundFlags { - AGI_SOUND_LOOP = 0x0001, - AGI_SOUND_ENVELOPE = 0x0002 -}; -enum AgiSoundEnv { - AGI_SOUND_ENV_ATTACK = 3, - AGI_SOUND_ENV_DECAY = 2, - AGI_SOUND_ENV_SUSTAIN = 1, - AGI_SOUND_ENV_RELEASE = 0 -}; - - -/** - * AGI engine sound channel structure. - */ -struct ChannelInfo { - AgiSoundEmuType type; - const uint8 *ptr; // Pointer to the AgiNote data - const int16 *ins; - int32 size; - uint32 phase; - uint32 flags; // ORs values from AgiSoundFlags - AgiSoundEnv adsr; - int32 timer; - uint32 end; - uint32 freq; - uint32 vol; - uint32 env; -}; class SoundMgr; class SoundGen { public: - SoundGen() {} + SoundGen(AgiEngine *vm, Audio::Mixer *pMixer) : _vm(vm), _mixer(pMixer) { + _sampleRate = pMixer->getOutputRate(); + } + virtual ~SoundGen() {} - virtual void play(int resnum, int flag) = 0; + virtual void play(int resnum) = 0; virtual void stop(void) = 0; - virtual void premixerCall(int16 *stream, int len) = 0; + AgiEngine *_vm; + + Audio::Mixer *_mixer; + Audio::SoundHandle _soundHandle; + + uint32 _sampleRate; }; /** @@ -177,81 +131,30 @@ protected: uint16 _type; ///< Sound resource type }; -class AgiEngine; -class IIgsSoundMgr; -class MusicPlayer; - -struct IIgsExeInfo; - -class SoundMgr : public Audio::AudioStream { +class SoundMgr { public: SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer); ~SoundMgr(); - virtual void setVolume(uint8 volume); - // AudioStream API - int readBuffer(int16 *buffer, const int numSamples); + void setVolume(uint8 volume); - bool isStereo() const { - return false; - } - - bool endOfData() const { - return false; - } + void unloadSound(int); + void playSound(); + int initSound(); + void deinitSound(); + void startSound(int, int); + void stopSound(); - int getRate() const { - // FIXME: Ideally, we should use _sampleRate. - return 22050; - } + void soundIsFinished(); +private: int _endflag; AgiEngine *_vm; -private: - Audio::Mixer *_mixer; - Audio::SoundHandle _soundHandle; - - MusicPlayer *_musicPlayer; - MidiDriver *_midiDriver; - - uint32 _sampleRate; - - bool _playing; - ChannelInfo _chn[NUM_CHANNELS]; - IIgsSoundMgr *_gsSound; - int _playingSound; - uint8 _env; - bool _disabledMidi; - - int16 *_sndBuffer; - const int16 *_waveform; - - bool _useChorus; - - void premixerCall(int16 *buf, uint len); - void fillAudio(void *udata, int16 *stream, uint len); - SoundGen *_soundGen; -public: - void unloadSound(int); - void playSound(); - int initSound(); - void deinitSound(); - void startSound(int, int); - void stopSound(); - void stopNote(int i); - void playNote(int i, int freq, int vol); - void playAgiSound(); - void playCoCoSound(); - uint32 mixSound(); - bool loadInstruments(); - void playMidiSound(); - void playSampleSound(); - const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const; - static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length); + int _playingSound; }; } // End of namespace Agi diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp index ce4aa160a0..056eac2d5c 100644 --- a/engines/agi/sound_2gs.cpp +++ b/engines/agi/sound_2gs.cpp @@ -23,10 +23,9 @@ * */ -#include "common/md5.h" #include "common/config-manager.h" #include "common/fs.h" -#include "common/random.h" +#include "common/md5.h" #include "common/str-array.h" #include "agi/agi.h" @@ -34,6 +33,194 @@ namespace Agi { +SoundGen2GS::SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { + _disabledMidi = !loadInstruments(); + + _playingSound = -1; + _playing = false; + + _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); + + _midiChannels.resize(16); // Set the amount of available MIDI channels + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +SoundGen2GS::~SoundGen2GS() { + _mixer->stopHandle(_soundHandle); + + free(_sndBuffer); +} + +int SoundGen2GS::readBuffer(int16 *buffer, const int numSamples) { + fillAudio(buffer, numSamples / 2); + + return numSamples; +} + +void SoundGen2GS::play(int resnum) { + AgiSoundEmuType type; + + _playingSound = resnum; + + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); + + assert (type == AGI_SOUND_SAMPLE || type == AGI_SOUND_MIDI); + + switch (type) { + case AGI_SOUND_SAMPLE: { + IIgsSample *sampleRes = (IIgsSample *) _vm->_game.sounds[_playingSound]; + playSampleSound(sampleRes->getHeader(), sampleRes->getSample()); + break; + } + case AGI_SOUND_MIDI: + ((IIgsMidi *) _vm->_game.sounds[_playingSound])->rewind(); + break; + default: + break; + } +} + +void SoundGen2GS::stop() { + _playingSound = -1; + + // Stops all sounds on all MIDI channels + for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->stopSounds(); +} + +void SoundGen2GS::playSound() { + if (_playingSound == -1) + return; + + if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_MIDI) { + playMidiSound(); + //warning("playSound: Trying to play an Apple IIGS MIDI sound. Not yet implemented"); + } else if (_vm->_game.sounds[_playingSound]->type() == AGI_SOUND_SAMPLE) { + //debugC(3, kDebugLevelSound, "playSound: Trying to play an Apple IIGS sample"); + playSampleSound(); + } + + if (!_playing) { + _vm->_sound->soundIsFinished(); + + _playingSound = -1; + } +} + +uint32 SoundGen2GS::mixSound() { + int i, b; + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + + if (!_playing || _playingSound == -1) + return BUFFER_SIZE; + + // Handle Apple IIGS sound mixing here + // TODO: Implement playing both waves in an oscillator + // TODO: Implement swap-mode in an oscillator + for (uint midiChan = 0; midiChan < _midiChannels.size(); midiChan++) { + for (uint gsChan = 0; gsChan < _midiChannels[midiChan]._gsChannels.size(); gsChan++) { + IIgsChannelInfo &channel = _midiChannels[midiChan]._gsChannels[gsChan]; + if (channel.playing()) { // Only mix in actively playing channels + // Frequency multiplier was 1076.0 based on tests made with MESS 0.117. + // Tests made with KEGS32 averaged the multiplier to around 1045. + // So this is a guess but maybe it's 1046.5... i.e. C6's frequency? + double hertz = C6_FREQ * pow(SEMITONE, fracToDouble(channel.note)); + channel.posAdd = doubleToFrac(hertz / getRate()); + channel.vol = doubleToFrac(fracToDouble(channel.envVol) * fracToDouble(channel.chanVol) / 127.0); + double tempVol = fracToDouble(channel.vol)/127.0; + for (i = 0; i < IIGS_BUFFER_SIZE; i++) { + b = channel.relocatedSample[fracToInt(channel.pos)]; + // TODO: Find out what volume/amplification setting is loud enough + // but still doesn't clip when playing many channels on it. + _sndBuffer[i] += (int16) (b * tempVol * 256/4); + channel.pos += channel.posAdd; + + if (channel.pos >= intToFrac(channel.size)) { + if (channel.loop) { + // Don't divide by zero on zero length samples + channel.pos %= intToFrac(channel.size + (channel.size == 0)); + // Probably we should loop the envelope too + channel.envSeg = 0; + channel.envVol = channel.startEnvVol; + } else { + channel.pos = channel.chanVol = 0; + channel.end = true; + break; + } + } + } + + if (channel.envSeg < ENVELOPE_SEGMENT_COUNT) { + const IIgsEnvelopeSegment &seg = channel.ins->env.seg[channel.envSeg]; + // I currently assume enveloping works with the same speed as the MIDI + // (i.e. with 1/60ths of a second ticks). + // TODO: Check if enveloping really works with the same speed as MIDI + frac_t envVolDelta = doubleToFrac(seg.inc/256.0); + if (intToFrac(seg.bp) >= channel.envVol) { + channel.envVol += envVolDelta; + if (channel.envVol >= intToFrac(seg.bp)) { + channel.envVol = intToFrac(seg.bp); + channel.envSeg += 1; + } + } else { + channel.envVol -= envVolDelta; + if (channel.envVol <= intToFrac(seg.bp)) { + channel.envVol = intToFrac(seg.bp); + channel.envSeg += 1; + } + } + } + } + } + } + + removeStoppedSounds(); + + return IIGS_BUFFER_SIZE; +} + +/** + * Convert sample from 8-bit unsigned to 8-bit signed format. + * @param source Source stream containing the 8-bit unsigned sample data. + * @param dest Destination buffer for the 8-bit signed sample data. + * @param length Length of the sample data to be converted. + */ +static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { + // Convert the wave from 8-bit unsigned to 8-bit signed format + for (uint i = 0; i < length; i++) + dest[i] = (int8) ((int) source.readByte() - 128); + return !(source.eos() || source.err()); +} + +void SoundGen2GS::fillAudio(int16 *stream, uint len) { + uint32 p = 0; + + // current number of audio bytes in _sndBuffer + static uint32 data_available = 0; + // offset of start of audio bytes in _sndBuffer + static uint32 data_offset = 0; + + len <<= 2; + + debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len); + + while (len > data_available) { + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); + p += data_available; + len -= data_available; + + playSound(); + data_available = mixSound() << 1; + data_offset = 0; + } + + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); + data_offset += len; + data_available -= len; +} + IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { _data = data; // Save the resource pointer _ptr = _data + 2; // Set current position to just after the header @@ -77,7 +264,7 @@ IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : _sample = new int8[_header.sampleSize]; if (_sample != NULL) - _isValid = SoundMgr::convertWave(stream, _sample, _header.sampleSize); + _isValid = convertWave(stream, _sample, _header.sampleSize); } if (!_isValid) // Check for errors @@ -248,23 +435,23 @@ static const IIgsExeInfo IIgsExeInfos[] = { {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} }; -void IIgsSoundMgr::stopSounds() { - // Stops all sounds on all MIDI channels - for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) - iter->stopSounds(); -} - -void SoundMgr::playSampleSound() { +void SoundGen2GS::playSampleSound() { if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); return; } if (_playingSound != -1) - _playing = _gsSound->activeSounds() > 0; + _playing = activeSounds() > 0; } -bool IIgsSoundMgr::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { +void SoundGen2GS::stopSounds() { + // Stops all sounds on all MIDI channels + for (iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) + iter->stopSounds(); +} + +bool SoundGen2GS::playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample) { stopSounds(); IIgsMidiChannel &channel = _midiChannels[kSfxMidiChannel]; @@ -283,7 +470,7 @@ void IIgsMidiChannel::stopSounds() { _gsChannels.clear(); } -void SoundMgr::playMidiSound() { +void SoundGen2GS::playMidiSound() { if (_disabledMidi) return; @@ -352,28 +539,28 @@ void SoundMgr::playMidiSound() { case MIDI_CMD_NOTE_OFF: parm1 = *p++; parm2 = *p++; - _gsSound->midiNoteOff(ch, parm1, parm2); + midiNoteOff(ch, parm1, parm2); break; case MIDI_CMD_NOTE_ON: parm1 = *p++; parm2 = *p++; - _gsSound->midiNoteOn(ch, parm1, parm2); + midiNoteOn(ch, parm1, parm2); break; case MIDI_CMD_CONTROLLER: parm1 = *p++; parm2 = *p++; - _gsSound->midiController(ch, parm1, parm2); + midiController(ch, parm1, parm2); break; case MIDI_CMD_PROGRAM_CHANGE: parm1 = *p++; - _gsSound->midiProgramChange(ch, parm1); + midiProgramChange(ch, parm1); break; case MIDI_CMD_PITCH_WHEEL: parm1 = *p++; parm2 = *p++; uint16 wheelPos = ((parm2 & 0x7F) << 7) | (parm1 & 0x7F); // 14-bit value - _gsSound->midiPitchWheel(wheelPos); + midiPitchWheel(wheelPos); break; } } @@ -381,19 +568,19 @@ void SoundMgr::playMidiSound() { midiObj->setPtr(p); } -void IIgsSoundMgr::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { +void SoundGen2GS::midiNoteOff(uint8 channel, uint8 note, uint8 velocity) { _midiChannels[channel].noteOff(note, velocity); debugC(3, kDebugLevelSound, "note off, channel %02x, note %02x, velocity %02x", channel, note, velocity); } -void IIgsSoundMgr::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { +void SoundGen2GS::midiNoteOn(uint8 channel, uint8 note, uint8 velocity) { _midiChannels[channel].noteOn(note, velocity); debugC(3, kDebugLevelSound, "note on, channel %02x, note %02x, velocity %02x", channel, note, velocity); } // TODO: Check if controllers behave differently on different MIDI channels // TODO: Doublecheck what other controllers than the volume controller do -void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) { +void SoundGen2GS::midiController(uint8 channel, uint8 controller, uint8 value) { IIgsMidiChannel &midiChannel = _midiChannels[channel]; // The tested Apple IIGS AGI MIDI resources only used @@ -413,31 +600,27 @@ void IIgsSoundMgr::midiController(uint8 channel, uint8 controller, uint8 value) debugC(3, kDebugLevelSound, "controller %02x, ch %02x, val %02x%s", controller, channel, value, unimplemented ? " (Unimplemented)" : ""); } -void IIgsSoundMgr::midiProgramChange(uint8 channel, uint8 program) { +void SoundGen2GS::midiProgramChange(uint8 channel, uint8 program) { _midiChannels[channel].setInstrument(getInstrument(program), _wave.begin()); debugC(3, kDebugLevelSound, "program change %02x, channel %02x", program, channel); } -void IIgsSoundMgr::midiPitchWheel(uint8 wheelPos) { +void SoundGen2GS::midiPitchWheel(uint8 wheelPos) { // In all the tested Apple IIGS AGI MIDI resources // pitch wheel commands always used 0x2000 (Center position). // Therefore it should be quite safe to ignore this command. debugC(3, kDebugLevelSound, "pitch wheel position %04x (Unimplemented)", wheelPos); } -IIgsSoundMgr::IIgsSoundMgr() { - _midiChannels.resize(16); // Set the amount of available MIDI channels -} - -const IIgsInstrumentHeader* IIgsSoundMgr::getInstrument(uint8 program) const { +const IIgsInstrumentHeader* SoundGen2GS::getInstrument(uint8 program) const { return &_instruments[_midiProgToInst->map(program)]; } -void IIgsSoundMgr::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { +void SoundGen2GS::setProgramChangeMapping(const MidiProgramChangeMapping *mapping) { _midiProgToInst = mapping; } -void IIgsSoundMgr::removeStoppedSounds() { +void SoundGen2GS::removeStoppedSounds() { for (Common::Array::iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) iter->removeStoppedSounds(); } @@ -448,7 +631,7 @@ void IIgsMidiChannel::removeStoppedSounds() { _gsChannels.remove_at(i); } -uint IIgsSoundMgr::activeSounds() const { +uint SoundGen2GS::activeSounds() const { uint result = 0; for (Common::Array::const_iterator iter = _midiChannels.begin(); iter != _midiChannels.end(); ++iter) @@ -561,14 +744,14 @@ bool IIgsChannelInfo::playing() { * Finds information about an Apple IIGS AGI executable based on the game ID. * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. */ -const IIgsExeInfo *SoundMgr::getIIgsExeInfo(enum AgiGameID gameid) const { +const IIgsExeInfo *SoundGen2GS::getIIgsExeInfo(enum AgiGameID gameid) const { for (int i = 0; i < ARRAYSIZE(IIgsExeInfos); i++) if (IIgsExeInfos[i].gameid == gameid) return &IIgsExeInfos[i]; return NULL; } -bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { +bool SoundGen2GS::loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo) { bool loadedOk = false; // Was loading successful? Common::File file; @@ -628,7 +811,7 @@ bool IIgsSoundMgr::loadInstrumentHeaders(const Common::FSNode &exePath, const II return loadedOk; } -bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { +bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo) { Common::File file; // Open the wave file and read it into memory @@ -650,7 +833,7 @@ bool IIgsSoundMgr::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInf uint8Wave->seek(0); // Seek wave to its start // Convert the wave file from 8-bit unsigned to 8-bit signed and save the result _wave.resize(uint8Wave->size()); - return SoundMgr::convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); + return convertWave(*uint8Wave, _wave.begin(), uint8Wave->size()); } else { // Couldn't read the wave file or it had incorrect size warning("Error loading Apple IIGS wave file (%s), not loading instruments", wavePath.getPath().c_str()); return false; @@ -676,7 +859,7 @@ private: Common::StringArray _str; }; -bool SoundMgr::loadInstruments() { +bool SoundGen2GS::loadInstruments() { // Check that the platform is Apple IIGS, as only it uses custom instruments if (_vm->getPlatform() != Common::kPlatformApple2GS) { debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); @@ -729,8 +912,8 @@ bool SoundMgr::loadInstruments() { // load the instrument headers and their sample data. // None of the tested SIERRASTANDARD-files have zeroes in them so // there's no need to check for prematurely ending samples here. - _gsSound->setProgramChangeMapping(&exeInfo->instSet.progToInst); - return _gsSound->loadWaveFile(*waveFsnode, *exeInfo) && _gsSound->loadInstrumentHeaders(*exeFsnode, *exeInfo); + setProgramChangeMapping(&exeInfo->instSet.progToInst); + return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo); } } // End of namespace Agi diff --git a/engines/agi/sound_2gs.h b/engines/agi/sound_2gs.h index 3669d29955..12dede0b69 100644 --- a/engines/agi/sound_2gs.h +++ b/engines/agi/sound_2gs.h @@ -27,9 +27,12 @@ #define AGI_SOUND_2GS_H #include "common/frac.h" +#include "sound/audiostream.h" namespace Agi { +#define BUFFER_SIZE 410 + // Apple IIGS MIDI uses 60 ticks per second (Based on tests with Apple IIGS // KQ1 and SQ1 under MESS 0.124a). So we make the audio buffer size to be a // 1/60th of a second in length. That should be getSampleRate() / 60 samples @@ -268,39 +271,78 @@ protected: uint8 _volume; ///< MIDI controller number 7 (Volume) }; +class SoundGen2GS : public SoundGen, public Audio::AudioStream { +public: + SoundGen2GS(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGen2GS(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } + +private: + bool _disabledMidi; + int _playingSound; + bool _playing; + + int16 *_sndBuffer; + /** * Class for managing Apple IIGS sound channels. * TODO: Check what instruments are used by default on the MIDI channels * FIXME: Some instrument choices sound wrong */ -class IIgsSoundMgr { -public: +private: typedef Common::Array::const_iterator const_iterator; typedef Common::Array::iterator iterator; static const uint kSfxMidiChannel = 0; ///< The MIDI channel used for playing sound effects -public: - // For initializing - IIgsSoundMgr(); + + bool loadInstruments(); + const IIgsExeInfo *getIIgsExeInfo(enum AgiGameID gameid) const; + void setProgramChangeMapping(const MidiProgramChangeMapping *mapping); bool loadInstrumentHeaders(const Common::FSNode &exePath, const IIgsExeInfo &exeInfo); bool loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo &exeInfo); + // Miscellaneous methods + void fillAudio(int16 *stream, uint len); + uint32 mixSound(); + void playSound(); uint activeSounds() const; ///< How many active sounds are playing? void stopSounds(); ///< Stops all sounds void removeStoppedSounds(); ///< Removes all stopped sounds from the MIDI channels + // For playing Apple IIGS AGI samples (Sound effects etc) bool playSampleSound(const IIgsSampleHeader &sampleHeader, const int8 *sample); + void playMidiSound(); + void playSampleSound(); + // MIDI commands void midiNoteOff(uint8 channel, uint8 note, uint8 velocity); void midiNoteOn(uint8 channel, uint8 note, uint8 velocity); void midiController(uint8 channel, uint8 controller, uint8 value); void midiProgramChange(uint8 channel, uint8 program); void midiPitchWheel(uint8 wheelPos); -protected: + //protected: const IIgsInstrumentHeader* getInstrument(uint8 program) const; -public: + //public: Common::Array _midiChannels; ///< Information about each MIDI channel -protected: + //protected: Common::Array _wave; ///< Sample data used by the Apple IIGS MIDI instruments const MidiProgramChangeMapping *_midiProgToInst; ///< MIDI program change to instrument number mapping Common::Array _instruments; ///< Instruments used by the Apple IIGS AGI diff --git a/engines/agi/sound_coco3.cpp b/engines/agi/sound_coco3.cpp new file mode 100644 index 0000000000..f054be0682 --- /dev/null +++ b/engines/agi/sound_coco3.cpp @@ -0,0 +1,80 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "agi/agi.h" + +#include "agi/sound_coco3.h" + +namespace Agi { + +static int cocoFrequencies[] = { + 130, 138, 146, 155, 164, 174, 184, 195, 207, 220, 233, 246, + 261, 277, 293, 311, 329, 349, 369, 391, 415, 440, 466, 493, + 523, 554, 587, 622, 659, 698, 739, 783, 830, 880, 932, 987, + 1046, 1108, 1174, 1244, 1318, 1396, 1479, 1567, 1661, 1760, 1864, 1975, + 2093, 2217, 2349, 2489, 2637, 2793, 2959, 3135, 3322, 3520, 3729, 3951 +}; + +SoundGenCoCo3::SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { +} + +SoundGenCoCo3::~SoundGenCoCo3() { +} + +void SoundGenCoCo3::play(int resnum) { + int i = cocoFrequencies[0]; // Silence warning + + i = i + 1; + +#if 0 + int i = 0; + CoCoNote note; + + do { + note.read(_chn[i].ptr); + + if (note.freq != 0xff) { + playNote(0, cocoFrequencies[note.freq], note.volume); + + uint32 start_time = _vm->_system->getMillis(); + + while (_vm->_system->getMillis() < start_time + note.duration) { + _vm->_system->updateScreen(); + + _vm->_system->delayMillis(10); + } + } + } while (note.freq != 0xff); +#endif +} + +void SoundGenCoCo3::stop() { +} + +int SoundGenCoCo3::readBuffer(int16 *buffer, const int numSamples) { + return numSamples; +} + +} // End of namespace Agi diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h new file mode 100755 index 0000000000..b60f1937cd --- /dev/null +++ b/engines/agi/sound_coco3.h @@ -0,0 +1,73 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef AGI_SOUND_COCO3_H +#define AGI_SOUND_COCO3_H + +#include "sound/audiostream.h" + +namespace Agi { + +struct CoCoNote { + uint8 freq; + uint8 volume; + uint16 duration; ///< Note duration + + /** Reads a CoCoNote through the given pointer. */ + void read(const uint8 *ptr) { + freq = *ptr; + volume = *(ptr + 1); + duration = READ_LE_UINT16(ptr + 2); + } +}; + +class SoundGenCoCo3 : public SoundGen, public Audio::AudioStream { +public: + SoundGenCoCo3(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenCoCo3(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_COCO3_H */ diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp index b31a4228fb..551df527cc 100755 --- a/engines/agi/sound_midi.cpp +++ b/engines/agi/sound_midi.cpp @@ -70,7 +70,10 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A warning("Error creating MIDI sound from resource %d (Type %d, length %d)", resnum, _type, len); } -MusicPlayer::MusicPlayer(MidiDriver *driver, SoundMgr *manager) : _parser(0), _driver(driver), _isPlaying(false), _passThrough(false), _isGM(false), _manager(manager) { +SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) { + MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB); + _driver = MidiDriver::createMidi(midiDriver); + memset(_channel, 0, sizeof(_channel)); memset(_channelVolume, 255, sizeof(_channelVolume)); _masterVolume = 0; @@ -79,7 +82,7 @@ MusicPlayer::MusicPlayer(MidiDriver *driver, SoundMgr *manager) : _parser(0), _d _midiMusicData = NULL; } -MusicPlayer::~MusicPlayer() { +SoundGenMIDI::~SoundGenMIDI() { _driver->setTimerCallback(NULL, NULL); stop(); this->close(); @@ -88,12 +91,12 @@ MusicPlayer::~MusicPlayer() { delete[] _midiMusicData; } -void MusicPlayer::setChannelVolume(int channel) { +void SoundGenMIDI::setChannelVolume(int channel) { int newVolume = _channelVolume[channel] * _masterVolume / 255; _channel[channel]->volume(newVolume); } -void MusicPlayer::setVolume(int volume) { +void SoundGenMIDI::setVolume(int volume) { Common::StackLock lock(_mutex); volume = CLIP(volume, 0, 255); @@ -108,7 +111,7 @@ void MusicPlayer::setVolume(int volume) { } } -int MusicPlayer::open() { +int SoundGenMIDI::open() { // Don't ever call open without first setting the output driver! if (!_driver) return 255; @@ -121,14 +124,14 @@ int MusicPlayer::open() { return 0; } -void MusicPlayer::close() { +void SoundGenMIDI::close() { stop(); if (_driver) _driver->close(); _driver = 0; } -void MusicPlayer::send(uint32 b) { +void SoundGenMIDI::send(uint32 b) { if (_passThrough) { _driver->send(b); return; @@ -163,11 +166,12 @@ void MusicPlayer::send(uint32 b) { _channel[channel]->send(b); } -void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { +void SoundGenMIDI::metaEvent(byte type, byte *data, uint16 length) { switch (type) { case 0x2F: // End of Track stop(); + _vm->_sound->soundIsFinished(); break; default: //warning("Unhandled meta event: %02x", type); @@ -175,19 +179,23 @@ void MusicPlayer::metaEvent(byte type, byte *data, uint16 length) { } } -void MusicPlayer::onTimer(void *refCon) { - MusicPlayer *music = (MusicPlayer *)refCon; +void SoundGenMIDI::onTimer(void *refCon) { + SoundGenMIDI *music = (SoundGenMIDI *)refCon; Common::StackLock lock(music->_mutex); if (music->_parser) music->_parser->onTimer(); } -void MusicPlayer::playMIDI(MIDISound *track) { +void SoundGenMIDI::play(int resnum) { + MIDISound *track; + stop(); _isGM = true; + track = (MIDISound *)_vm->_game.sounds[resnum]; + // Convert AGI Sound data to MIDI int midiMusicSize = convertSND2MIDI(track->_data, &_midiMusicData); @@ -206,7 +214,7 @@ void MusicPlayer::playMIDI(MIDISound *track) { } } -void MusicPlayer::stop() { +void SoundGenMIDI::stop() { Common::StackLock lock(_mutex); if (!_isPlaying) @@ -217,22 +225,19 @@ void MusicPlayer::stop() { _parser->unloadMusic(); _parser = NULL; } - - if (_manager->_endflag != -1) - _manager->_vm->setflag(_manager->_endflag, true); } -void MusicPlayer::pause() { +void SoundGenMIDI::pause() { setVolume(-1); _isPlaying = false; } -void MusicPlayer::resume() { +void SoundGenMIDI::resume() { syncVolume(); _isPlaying = true; } -void MusicPlayer::syncVolume() { +void SoundGenMIDI::syncVolume() { int volume = ConfMan.getInt("music_volume"); if (ConfMan.getBool("mute")) { volume = -1; diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h index 48216ceb12..26b75e0d70 100755 --- a/engines/agi/sound_midi.h +++ b/engines/agi/sound_midi.h @@ -46,10 +46,13 @@ protected: uint16 _type; ///< Sound resource type }; -class MusicPlayer : public MidiDriver { +class SoundGenMIDI : public SoundGen, public MidiDriver { public: - MusicPlayer(MidiDriver *driver, SoundMgr *manager); - ~MusicPlayer(); + SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenMIDI(); + + void play(int resnum); + void stop(); bool isPlaying() { return _isPlaying; } void setPlaying(bool playing) { _isPlaying = playing; } @@ -60,8 +63,6 @@ public: void setNativeMT32(bool b) { _nativeMT32 = b; } bool hasNativeMT32() { return _nativeMT32; } - void playMIDI(MIDISound *track); - void stop(); void pause(); void resume(); void setLoop(bool loop) { _looping = loop; } @@ -86,7 +87,7 @@ public: MidiParser *_parser; Common::Mutex _mutex; -protected: +private: static void onTimer(void *data); void setChannelVolume(int channel); diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp index f00c4424bc..b9d701d7f7 100755 --- a/engines/agi/sound_pcjr.cpp +++ b/engines/agi/sound_pcjr.cpp @@ -105,7 +105,7 @@ const int8 dissolveDataV3[] = { }; -SoundGenPCJr::SoundGenPCJr(AgiEngine *vm) : _vm(vm) { +SoundGenPCJr::SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer) { _chanAllocated = 10240; // preallocate something which will most likely fit _chanData = (int16 *)malloc(_chanAllocated << 1); @@ -122,13 +122,19 @@ SoundGenPCJr::SoundGenPCJr(AgiEngine *vm) : _vm(vm) { _dissolveMethod = 2; else _dissolveMethod = 0; + + _dissolveMethod = 3; + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); } SoundGenPCJr::~SoundGenPCJr() { free(_chanData); + + _mixer->stopHandle(_soundHandle); } -void SoundGenPCJr::play(int resnum, int flag) { +void SoundGenPCJr::play(int resnum) { PCjrSound *pcjrSound = (PCjrSound *)_vm->_game.sounds[resnum]; for (int i = 0; i < CHAN_MAX; i++) { @@ -467,7 +473,7 @@ int SoundGenPCJr::fillNoise(ToneChan *t, int16 *buf, int len) { return len; } -void SoundGenPCJr::premixerCall(int16 *stream, int len) { +int SoundGenPCJr::readBuffer(int16 *stream, const int len) { int streamCount; int16 *sPtr, *cPtr; @@ -480,6 +486,8 @@ void SoundGenPCJr::premixerCall(int16 *stream, int len) { assert(stream); + bool finished = true; + for (int i = 0; i < CHAN_MAX; i++) { // get channel data(chan.userdata) if (chanGen(i, _chanData, len) == 0) { @@ -487,11 +495,18 @@ void SoundGenPCJr::premixerCall(int16 *stream, int len) { streamCount = len; sPtr = stream; cPtr = _chanData; - + while (streamCount--) *(sPtr++) += *(cPtr++) / CHAN_MAX; + + finished = false; } } + + if (finished) + _vm->_sound->soundIsFinished(); + + return len; } } // End of namespace Agi diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h index 9ef9aa2385..fe0e762f4e 100755 --- a/engines/agi/sound_pcjr.h +++ b/engines/agi/sound_pcjr.h @@ -26,6 +26,8 @@ #ifndef AGI_SOUND_PCJR_H #define AGI_SOUND_PCJR_H +#include "sound/audiostream.h" + namespace Agi { #define CHAN_MAX 4 @@ -78,15 +80,29 @@ struct Tone { GenType type; }; -class SoundGenPCJr : public SoundGen { +class SoundGenPCJr : public SoundGen, public Audio::AudioStream { public: - SoundGenPCJr(AgiEngine *vm); + SoundGenPCJr(AgiEngine *vm, Audio::Mixer *pMixer); ~SoundGenPCJr(); - void play(int resnum, int flag); + void play(int resnum); void stop(void); - void premixerCall(int16 *stream, int len); + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } private: int getNextNote(int ch, Tone *tone); @@ -98,7 +114,6 @@ private: int fillSquare(ToneChan *t, int16 *buf, int len); private: - AgiEngine *_vm; SndGenChan _channel[CHAN_MAX]; ToneChan _tchannel[CHAN_MAX]; int16 *_chanData; diff --git a/engines/agi/sound_sarien.cpp b/engines/agi/sound_sarien.cpp new file mode 100644 index 0000000000..08bdd47497 --- /dev/null +++ b/engines/agi/sound_sarien.cpp @@ -0,0 +1,357 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "common/md5.h" +#include "common/config-manager.h" +#include "common/fs.h" +#include "common/random.h" +#include "common/str-array.h" + +#include "sound/mididrv.h" + +#include "agi/agi.h" + +#include "agi/sound_sarien.h" + +namespace Agi { + +#define USE_INTERPOLATION + +static const int16 waveformRamp[WAVEFORM_SIZE] = { + 0, 8, 16, 24, 32, 40, 48, 56, + 64, 72, 80, 88, 96, 104, 112, 120, + 128, 136, 144, 152, 160, 168, 176, 184, + 192, 200, 208, 216, 224, 232, 240, 255, + 0, -248, -240, -232, -224, -216, -208, -200, + -192, -184, -176, -168, -160, -152, -144, -136, + -128, -120, -112, -104, -96, -88, -80, -72, + -64, -56, -48, -40, -32, -24, -16, -8 // Ramp up +}; + +static const int16 waveformSquare[WAVEFORM_SIZE] = { + 255, 230, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 220, + 220, 220, 220, 220, 220, 220, 220, 110, + -255, -230, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -220, -220, -220, -220, -220, + -220, -220, -220, -110, 0, 0, 0, 0 // Square +}; + +static const int16 waveformMac[WAVEFORM_SIZE] = { + 45, 110, 135, 161, 167, 173, 175, 176, + 156, 137, 123, 110, 91, 72, 35, -2, + -60, -118, -142, -165, -170, -176, -177, -179, + -177, -176, -164, -152, -117, -82, -17, 47, + 92, 137, 151, 166, 170, 173, 171, 169, + 151, 133, 116, 100, 72, 43, -7, -57, + -99, -141, -156, -170, -174, -177, -178, -179, + -175, -172, -165, -159, -137, -114, -67, -19 +}; + +SoundGenSarien::SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _chn() { + _sndBuffer = (int16 *)calloc(2, BUFFER_SIZE); + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + _env = false; + _playingSound = -1; + _playing = false; + _useChorus = true; // FIXME: Currently always true? + + switch (_vm->_soundemu) { + case SOUND_EMU_NONE: + _waveform = waveformRamp; + _env = true; + break; + case SOUND_EMU_AMIGA: + case SOUND_EMU_PC: + _waveform = waveformSquare; + break; + case SOUND_EMU_MAC: + _waveform = waveformMac; + break; + } + + report("Initializing sound:\n"); + + report("sound: envelopes "); + if (_env) { + report("enabled (decay=%d, sustain=%d)\n", ENV_DECAY, ENV_SUSTAIN); + } else { + report("disabled\n"); + } + + _mixer->playStream(Audio::Mixer::kMusicSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); +} + +SoundGenSarien::~SoundGenSarien() { + _mixer->stopHandle(_soundHandle); + + free(_sndBuffer); +} + +int SoundGenSarien::readBuffer(int16 *buffer, const int numSamples) { + fillAudio(buffer, numSamples / 2); + + return numSamples; +} + +void SoundGenSarien::play(int resnum) { + AgiSoundEmuType type; + + type = (AgiSoundEmuType)_vm->_game.sounds[resnum]->type(); + + assert(type == AGI_SOUND_4CHN); + + _playingSound = resnum; + + PCjrSound *pcjrSound = (PCjrSound *) _vm->_game.sounds[resnum]; + + // Initialize channel info + for (int i = 0; i < NUM_CHANNELS; i++) { + _chn[i].type = type; + _chn[i].flags = AGI_SOUND_LOOP; + + if (_env) { + _chn[i].flags |= AGI_SOUND_ENVELOPE; + _chn[i].adsr = AGI_SOUND_ENV_ATTACK; + } + + _chn[i].ins = _waveform; + _chn[i].size = WAVEFORM_SIZE; + _chn[i].ptr = pcjrSound->getVoicePointer(i % 4); + _chn[i].timer = 0; + _chn[i].vol = 0; + _chn[i].end = 0; + } + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); +} + +void SoundGenSarien::stop() { + _playingSound = -1; + + for (int i = 0; i < NUM_CHANNELS; i++) + stopNote(i); +} + +void SoundGenSarien::stopNote(int i) { + _chn[i].adsr = AGI_SOUND_ENV_RELEASE; + + if (_useChorus) { + // Stop chorus ;) + if (_chn[i].type == AGI_SOUND_4CHN && + _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + stopNote(i + 4); + } + } +} + +void SoundGenSarien::playNote(int i, int freq, int vol) { + if (!_vm->getflag(fSoundOn)) + vol = 0; + else if (vol && _vm->_soundemu == SOUND_EMU_PC) + vol = 160; + + _chn[i].phase = 0; + _chn[i].freq = freq; + _chn[i].vol = vol; + _chn[i].env = 0x10000; + _chn[i].adsr = AGI_SOUND_ENV_ATTACK; + + if (_useChorus) { + // Add chorus ;) + if (_chn[i].type == AGI_SOUND_4CHN && + _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + + int newfreq = freq * 1007 / 1000; + + if (freq == newfreq) + newfreq++; + + playNote(i + 4, newfreq, vol * 2 / 3); + } + } +} + +void SoundGenSarien::playSound() { + int i; + AgiNote note; + + if (_playingSound == -1) + return; + + _playing = false; + for (i = 0; i < (_vm->_soundemu == SOUND_EMU_PC ? 1 : 4); i++) { + _playing |= !_chn[i].end; + note.read(_chn[i].ptr); // Read a single note (Doesn't advance the pointer) + + if (_chn[i].end) + continue; + + if ((--_chn[i].timer) <= 0) { + stopNote(i); + + if (note.freqDiv != 0) { + int volume = (note.attenuation == 0x0F) ? 0 : (0xFF - note.attenuation * 2); + playNote(i, note.freqDiv * 10, volume); + } + + _chn[i].timer = note.duration; + + if (_chn[i].timer == 0xffff) { + _chn[i].end = 1; + _chn[i].vol = 0; + _chn[i].env = 0; + + if (_useChorus) { + // chorus + if (_chn[i].type == AGI_SOUND_4CHN && _vm->_soundemu == SOUND_EMU_NONE && i < 3) { + _chn[i + 4].vol = 0; + _chn[i + 4].env = 0; + } + } + } + _chn[i].ptr += 5; // Advance the pointer to the next note data (5 bytes per note) + } + } + + if (!_playing) { + _vm->_sound->soundIsFinished(); + + _playingSound = -1; + } +} + +uint32 SoundGenSarien::mixSound() { + register int i, p; + const int16 *src; + int c, b, m; + + memset(_sndBuffer, 0, BUFFER_SIZE << 1); + + if (!_playing || _playingSound == -1) + return BUFFER_SIZE; + + // Handle PCjr 4-channel sound mixing here + for (c = 0; c < NUM_CHANNELS; c++) { + if (!_chn[c].vol) + continue; + + m = _chn[c].flags & AGI_SOUND_ENVELOPE ? + _chn[c].vol * _chn[c].env >> 16 : _chn[c].vol; + + if (_chn[c].type != AGI_SOUND_4CHN || c != 3) { + src = _chn[c].ins; + + p = _chn[c].phase; + for (i = 0; i < BUFFER_SIZE; i++) { + b = src[p >> 8]; +#ifdef USE_INTERPOLATION + b += ((src[((p >> 8) + 1) % _chn[c].size] - src[p >> 8]) * (p & 0xff)) >> 8; +#endif + _sndBuffer[i] += (b * m) >> 4; + + p += (uint32) 118600 *4 / _chn[c].freq; + + // FIXME: Fingolfin asks: why is there a FIXME here? Please either clarify what + // needs fixing, or remove it! + // FIXME + if (_chn[c].flags & AGI_SOUND_LOOP) { + p %= _chn[c].size << 8; + } else { + if (p >= _chn[c].size << 8) { + p = _chn[c].vol = 0; + _chn[c].end = 1; + break; + } + } + + } + _chn[c].phase = p; + } else { + // Add white noise + for (i = 0; i < BUFFER_SIZE; i++) { + b = _vm->_rnd->getRandomNumber(255) - 128; + _sndBuffer[i] += (b * m) >> 4; + } + } + + switch (_chn[c].adsr) { + case AGI_SOUND_ENV_ATTACK: + // not implemented + _chn[c].adsr = AGI_SOUND_ENV_DECAY; + break; + case AGI_SOUND_ENV_DECAY: + if (_chn[c].env > _chn[c].vol * ENV_SUSTAIN + ENV_DECAY) { + _chn[c].env -= ENV_DECAY; + } else { + _chn[c].env = _chn[c].vol * ENV_SUSTAIN; + _chn[c].adsr = AGI_SOUND_ENV_SUSTAIN; + } + break; + case AGI_SOUND_ENV_SUSTAIN: + break; + case AGI_SOUND_ENV_RELEASE: + if (_chn[c].env >= ENV_RELEASE) { + _chn[c].env -= ENV_RELEASE; + } else { + _chn[c].env = 0; + } + } + } + + return BUFFER_SIZE; +} + +void SoundGenSarien::fillAudio(int16 *stream, uint len) { + uint32 p = 0; + + // current number of audio bytes in _sndBuffer + static uint32 data_available = 0; + // offset of start of audio bytes in _sndBuffer + static uint32 data_offset = 0; + + len <<= 2; + + debugC(5, kDebugLevelSound, "(%p, %d)", (void *)stream, len); + + while (len > data_available) { + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, data_available); + p += data_available; + len -= data_available; + + playSound(); + data_available = mixSound() << 1; + data_offset = 0; + } + + memcpy((uint8 *)stream + p, (uint8*)_sndBuffer + data_offset, len); + data_offset += len; + data_available -= len; +} + +} // End of namespace Agi diff --git a/engines/agi/sound_sarien.h b/engines/agi/sound_sarien.h new file mode 100755 index 0000000000..54222ba624 --- /dev/null +++ b/engines/agi/sound_sarien.h @@ -0,0 +1,120 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef AGI_SOUND_SARIEN_H +#define AGI_SOUND_SARIEN_H + +#include "sound/audiostream.h" + +namespace Agi { + +#define BUFFER_SIZE 410 + +#define WAVEFORM_SIZE 64 +#define ENV_ATTACK 10000 /**< envelope attack rate */ +#define ENV_DECAY 1000 /**< envelope decay rate */ +#define ENV_SUSTAIN 100 /**< envelope sustain level */ +#define ENV_RELEASE 7500 /**< envelope release rate */ +#define NUM_CHANNELS 7 /**< number of sound channels */ + +enum AgiSoundFlags { + AGI_SOUND_LOOP = 0x0001, + AGI_SOUND_ENVELOPE = 0x0002 +}; +enum AgiSoundEnv { + AGI_SOUND_ENV_ATTACK = 3, + AGI_SOUND_ENV_DECAY = 2, + AGI_SOUND_ENV_SUSTAIN = 1, + AGI_SOUND_ENV_RELEASE = 0 +}; + + +/** + * AGI engine sound channel structure. + */ +struct ChannelInfo { + AgiSoundEmuType type; + const uint8 *ptr; // Pointer to the AgiNote data + const int16 *ins; + int32 size; + uint32 phase; + uint32 flags; // ORs values from AgiSoundFlags + AgiSoundEnv adsr; + int32 timer; + uint32 end; + uint32 freq; + uint32 vol; + uint32 env; +}; + +class SoundGenSarien : public SoundGen, public Audio::AudioStream { +public: + SoundGenSarien(AgiEngine *vm, Audio::Mixer *pMixer); + ~SoundGenSarien(); + + void play(int resnum); + void stop(void); + + // AudioStream API + int readBuffer(int16 *buffer, const int numSamples); + + bool isStereo() const { + return false; + } + + bool endOfData() const { + return false; + } + + int getRate() const { + // FIXME: Ideally, we should use _sampleRate. + return 22050; + } + +private: + ChannelInfo _chn[NUM_CHANNELS]; + uint8 _env; + + int16 *_sndBuffer; + const int16 *_waveform; + + bool _useChorus; + + bool _playing; + int _playingSound; + +private: + void playSound(); + uint32 mixSound(); + void fillAudio(int16 *stream, uint len); + + void stopNote(int i); + void playNote(int i, int freq, int vol); + +}; + +} // End of namespace Agi + +#endif /* AGI_SOUND_SARIEN_H */ -- cgit v1.2.3 From db6673c408865b201808e01ab5db796f2e794058 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:38:39 +0000 Subject: AGI: rearranged class methods a bit and cleanup. svn-id: r49758 --- engines/agi/sound.cpp | 12 - engines/agi/sound_2gs.cpp | 644 +++++++++++++++++++++++----------------------- 2 files changed, 322 insertions(+), 334 deletions(-) (limited to 'engines') diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index 2ca2706259..9dda3e91f5 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -31,18 +31,6 @@ #include "agi/sound_sarien.h" #include "agi/sound_pcjr.h" -#if 0 -#include "common/md5.h" -#include "common/config-manager.h" -#include "common/fs.h" -#include "common/random.h" -#include "common/str-array.h" - -#include "sound/mididrv.h" - - -#endif - namespace Agi { // diff --git a/engines/agi/sound_2gs.cpp b/engines/agi/sound_2gs.cpp index 056eac2d5c..cc1cd0f6d5 100644 --- a/engines/agi/sound_2gs.cpp +++ b/engines/agi/sound_2gs.cpp @@ -181,19 +181,6 @@ uint32 SoundGen2GS::mixSound() { return IIGS_BUFFER_SIZE; } -/** - * Convert sample from 8-bit unsigned to 8-bit signed format. - * @param source Source stream containing the 8-bit unsigned sample data. - * @param dest Destination buffer for the 8-bit signed sample data. - * @param length Length of the sample data to be converted. - */ -static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { - // Convert the wave from 8-bit unsigned to 8-bit signed format - for (uint i = 0; i < length; i++) - dest[i] = (int8) ((int) source.readByte() - 128); - return !(source.eos() || source.err()); -} - void SoundGen2GS::fillAudio(int16 *stream, uint len) { uint32 p = 0; @@ -221,220 +208,6 @@ void SoundGen2GS::fillAudio(int16 *stream, uint len) { data_available -= len; } -IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - _data = data; // Save the resource pointer - _ptr = _data + 2; // Set current position to just after the header - _len = len; // Save the resource's length - _type = READ_LE_UINT16(data); // Read sound resource's type - _midiTicks = _soundBufTicks = 0; - _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); -} - -IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { - Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); - - // Check that the header was read ok and that it's of the correct type - if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource - uint32 sampleStartPos = stream.pos(); - uint32 tailLen = stream.size() - sampleStartPos; - - if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream - // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes - // of sample data although header says it should have 16384 bytes. - warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", - resnum, tailLen, _header.sampleSize); - - _header.sampleSize = (uint16) tailLen; // Use the part that's left - } - - if (_header.pitch > 0x7F) { // Check if the pitch is invalid - warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); - - _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too - } - - // Finalize the header info using the 8-bit unsigned sample data - _header.finalize(stream); - - // Convert sample data from 8-bit unsigned to 8-bit signed format - stream.seek(sampleStartPos); - _sample = new int8[_header.sampleSize]; - - if (_sample != NULL) - _isValid = convertWave(stream, _sample, _header.sampleSize); - } - - if (!_isValid) // Check for errors - warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); -} - -/** Reads an Apple IIGS envelope from then given stream. */ -bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { - for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { - seg[segNum].bp = stream.readByte(); - seg[segNum].inc = stream.readUint16LE(); - } - - return !(stream.eos() || stream.err()); -} - -/** Reads an Apple IIGS wave information structure from the given stream. */ -bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - top = stream.readByte(); - addr = stream.readByte() * 256; - size = (1 << (stream.readByte() & 7)) * 256; - - // Read packed mode byte and parse it into parts - byte packedModeByte = stream.readByte(); - channel = (packedModeByte >> 4) & 1; // Bit 4 - mode = (packedModeByte >> 1) & 3; // Bits 1-2 - halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) - - relPitch = stream.readSint16LE(); - - // Zero the wave address if we want to ignore the wave address info - if (ignoreAddr) - addr = 0; - - return !(stream.eos() || stream.err()); -} - -bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { - uint32 startPos = uint8Wave.pos(); // Save stream's starting position - uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address - - // Calculate the true sample size (A zero ends the sample prematurely) - uint trueSize = size; // Set a default value for the result - for (uint i = 0; i < size; i++) { - if (uint8Wave.readByte() == 0) { - trueSize = i; - // A zero in the sample stream turns off looping - // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) - if (mode == OSC_MODE_LOOP) - mode = OSC_MODE_ONESHOT; - break; - } - } - size = trueSize; // Set the true sample size - - uint8Wave.seek(startPos); // Seek back to the stream's starting position - - return true; -} - -bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) - if (!waves[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { - // First read the A waves and then the B waves for the oscillators - for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) - for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) - if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) - return false; - - count = oscillatorCount; // Set the oscillator count - - return true; -} - -bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { - for (uint i = 0; i < count; i++) - if (!osc[i].finalize(uint8Wave)) - return false; - - return true; -} - -bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { - env.read(stream); - relseg = stream.readByte(); - /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. - bendrange = stream.readByte(); - vibdepth = stream.readByte(); - vibspeed = stream.readByte(); - /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. - byte wac = stream.readByte(); // Read A wave count - byte wbc = stream.readByte(); // Read B wave count - oscList.read(stream, wac, ignoreAddr); // Read the oscillators - return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match -} - -bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return oscList.finalize(uint8Wave); -} - -bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { - type = stream.readUint16LE(); - pitch = stream.readByte(); - unknownByte_Ofs3 = stream.readByte(); - volume = stream.readByte(); - unknownByte_Ofs5 = stream.readByte(); - instrumentSize = stream.readUint16LE(); - sampleSize = stream.readUint16LE(); - // Read the instrument header *ignoring* its wave address info - - return instrument.read(stream, true); -} - -bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { - return instrument.finalize(uint8Wave); -} - -/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV1 = { - {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, - 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, - 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, - 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, - 25, 13, 13, 25}, - 5 -}; - -/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ -static const MidiProgramChangeMapping progToInstMappingV2 = { - {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, - 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, - 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, - 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, - 27, 15, 15, 27}, - 6 -}; - -/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ -static const InstrumentSetInfo instSetV1 = { - 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 -}; - -/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ -static const InstrumentSetInfo instSetV2 = { - 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 -}; - -/** Information about different Apple IIGS AGI executables. */ -static const IIgsExeInfo IIgsExeInfos[] = { - {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, - {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, - {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, - {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, - {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, - {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, - {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, - {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, - {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, - {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, - {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, - {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, - {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} -}; - void SoundGen2GS::playSampleSound() { if (_vm->_soundemu != SOUND_EMU_APPLE2GS) { warning("Trying to play a sample but not using Apple IIGS sound emulation mode"); @@ -462,14 +235,6 @@ bool SoundGen2GS::playSampleSound(const IIgsSampleHeader &sampleHeader, const in return true; } -void IIgsMidiChannel::stopSounds() { - // Stops all sounds on this single MIDI channel - for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - iter->stop(); - - _gsChannels.clear(); -} - void SoundGen2GS::playMidiSound() { if (_disabledMidi) return; @@ -625,12 +390,6 @@ void SoundGen2GS::removeStoppedSounds() { iter->removeStoppedSounds(); } -void IIgsMidiChannel::removeStoppedSounds() { - for (int i = _gsChannels.size() - 1; i >= 0; i--) - if (!_gsChannels[i].playing()) - _gsChannels.remove_at(i); -} - uint SoundGen2GS::activeSounds() const { uint result = 0; @@ -640,12 +399,206 @@ uint SoundGen2GS::activeSounds() const { return result; } -uint IIgsMidiChannel::activeSounds() const { - uint result = 0; +IIgsMidi::IIgsMidi(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + _data = data; // Save the resource pointer + _ptr = _data + 2; // Set current position to just after the header + _len = len; // Save the resource's length + _type = READ_LE_UINT16(data); // Read sound resource's type + _midiTicks = _soundBufTicks = 0; + _isValid = (_type == AGI_SOUND_MIDI) && (_data != NULL) && (_len >= 2); - for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) - if (!iter->end) - result++; + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS midi sound from resource %d (Type %d, length %d)", resnum, _type, len); +} + +/** + * Convert sample from 8-bit unsigned to 8-bit signed format. + * @param source Source stream containing the 8-bit unsigned sample data. + * @param dest Destination buffer for the 8-bit signed sample data. + * @param length Length of the sample data to be converted. + */ +static bool convertWave(Common::SeekableReadStream &source, int8 *dest, uint length) { + // Convert the wave from 8-bit unsigned to 8-bit signed format + for (uint i = 0; i < length; i++) + dest[i] = (int8) ((int) source.readByte() - 128); + return !(source.eos() || source.err()); +} + +IIgsSample::IIgsSample(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : AgiSound(manager) { + Common::MemoryReadStream stream(data, len, DisposeAfterUse::YES); + + // Check that the header was read ok and that it's of the correct type + if (_header.read(stream) && _header.type == AGI_SOUND_SAMPLE) { // An Apple IIGS AGI sample resource + uint32 sampleStartPos = stream.pos(); + uint32 tailLen = stream.size() - sampleStartPos; + + if (tailLen < _header.sampleSize) { // Check if there's no room for the sample data in the stream + // Apple IIGS Manhunter I: Sound resource 16 has only 16074 bytes + // of sample data although header says it should have 16384 bytes. + warning("Apple IIGS sample (%d) too short (%d bytes. Should be %d bytes). Using the part that's left", + resnum, tailLen, _header.sampleSize); + + _header.sampleSize = (uint16) tailLen; // Use the part that's left + } + + if (_header.pitch > 0x7F) { // Check if the pitch is invalid + warning("Apple IIGS sample (%d) has too high pitch (0x%02x)", resnum, _header.pitch); + + _header.pitch &= 0x7F; // Apple IIGS AGI probably did it this way too + } + + // Finalize the header info using the 8-bit unsigned sample data + _header.finalize(stream); + + // Convert sample data from 8-bit unsigned to 8-bit signed format + stream.seek(sampleStartPos); + _sample = new int8[_header.sampleSize]; + + if (_sample != NULL) + _isValid = convertWave(stream, _sample, _header.sampleSize); + } + + if (!_isValid) // Check for errors + warning("Error creating Apple IIGS sample from resource %d (Type %d, length %d)", resnum, _header.type, len); +} + +/** Reads an Apple IIGS envelope from then given stream. */ +bool IIgsEnvelope::read(Common::SeekableReadStream &stream) { + for (int segNum = 0; segNum < ENVELOPE_SEGMENT_COUNT; segNum++) { + seg[segNum].bp = stream.readByte(); + seg[segNum].inc = stream.readUint16LE(); + } + + return !(stream.eos() || stream.err()); +} + +/** Reads an Apple IIGS wave information structure from the given stream. */ +bool IIgsWaveInfo::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + top = stream.readByte(); + addr = stream.readByte() * 256; + size = (1 << (stream.readByte() & 7)) * 256; + + // Read packed mode byte and parse it into parts + byte packedModeByte = stream.readByte(); + channel = (packedModeByte >> 4) & 1; // Bit 4 + mode = (packedModeByte >> 1) & 3; // Bits 1-2 + halt = (packedModeByte & 1) != 0; // Bit 0 (Converted to boolean) + + relPitch = stream.readSint16LE(); + + // Zero the wave address if we want to ignore the wave address info + if (ignoreAddr) + addr = 0; + + return !(stream.eos() || stream.err()); +} + +bool IIgsWaveInfo::finalize(Common::SeekableReadStream &uint8Wave) { + uint32 startPos = uint8Wave.pos(); // Save stream's starting position + uint8Wave.seek(addr, SEEK_CUR); // Seek to wave's address + + // Calculate the true sample size (A zero ends the sample prematurely) + uint trueSize = size; // Set a default value for the result + for (uint i = 0; i < size; i++) { + if (uint8Wave.readByte() == 0) { + trueSize = i; + // A zero in the sample stream turns off looping + // (At least that's what MESS 0.117 and KEGS32 0.91 seem to do) + if (mode == OSC_MODE_LOOP) + mode = OSC_MODE_ONESHOT; + break; + } + } + size = trueSize; // Set the true sample size + + uint8Wave.seek(startPos); // Seek back to the stream's starting position + + return true; +} + +bool IIgsOscillator::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < WAVES_PER_OSCILLATOR; i++) + if (!waves[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsOscillatorList::read(Common::SeekableReadStream &stream, uint oscillatorCount, bool ignoreAddr) { + // First read the A waves and then the B waves for the oscillators + for (uint waveNum = 0; waveNum < WAVES_PER_OSCILLATOR; waveNum++) + for (uint oscNum = 0; oscNum < oscillatorCount; oscNum++) + if (!osc[oscNum].waves[waveNum].read(stream, ignoreAddr)) + return false; + + count = oscillatorCount; // Set the oscillator count + + return true; +} + +bool IIgsOscillatorList::finalize(Common::SeekableReadStream &uint8Wave) { + for (uint i = 0; i < count; i++) + if (!osc[i].finalize(uint8Wave)) + return false; + + return true; +} + +bool IIgsInstrumentHeader::read(Common::SeekableReadStream &stream, bool ignoreAddr) { + env.read(stream); + relseg = stream.readByte(); + /*byte priority =*/ stream.readByte(); // Not needed? 32 in all tested data. + bendrange = stream.readByte(); + vibdepth = stream.readByte(); + vibspeed = stream.readByte(); + /*byte spare =*/ stream.readByte(); // Not needed? 0 in all tested data. + byte wac = stream.readByte(); // Read A wave count + byte wbc = stream.readByte(); // Read B wave count + oscList.read(stream, wac, ignoreAddr); // Read the oscillators + return (wac == wbc) && !(stream.eos() || stream.err()); // A and B wave counts must match +} + +bool IIgsInstrumentHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return oscList.finalize(uint8Wave); +} + +bool IIgsSampleHeader::read(Common::SeekableReadStream &stream) { + type = stream.readUint16LE(); + pitch = stream.readByte(); + unknownByte_Ofs3 = stream.readByte(); + volume = stream.readByte(); + unknownByte_Ofs5 = stream.readByte(); + instrumentSize = stream.readUint16LE(); + sampleSize = stream.readUint16LE(); + // Read the instrument header *ignoring* its wave address info + + return instrument.read(stream, true); +} + +bool IIgsSampleHeader::finalize(Common::SeekableReadStream &uint8Wave) { + return instrument.finalize(uint8Wave); +} + +void IIgsMidiChannel::stopSounds() { + // Stops all sounds on this single MIDI channel + for (iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + iter->stop(); + + _gsChannels.clear(); +} + +void IIgsMidiChannel::removeStoppedSounds() { + for (int i = _gsChannels.size() - 1; i >= 0; i--) + if (!_gsChannels[i].playing()) + _gsChannels.remove_at(i); +} + +uint IIgsMidiChannel::activeSounds() const { + uint result = 0; + + for (const_iterator iter = _gsChannels.begin(); iter != _gsChannels.end(); ++iter) + if (!iter->end) + result++; return result; } @@ -740,6 +693,129 @@ bool IIgsChannelInfo::playing() { return !this->end; } +/** + * A function object (i.e. a functor) for testing if a Common::FSNode + * object's name is equal (Ignoring case) to a string or to at least + * one of the strings in a list of strings. Can be used e.g. with find_if(). + */ +struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction { +// FIXME: This should be replaced; use SearchMan instead + fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} + fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } + bool operator()(const Common::FSNode ¶m) const { + for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) + if (param.getName().equalsIgnoreCase(*iter)) + return true; + return false; + } +private: + Common::StringArray _str; +}; + +bool SoundGen2GS::loadInstruments() { + // Check that the platform is Apple IIGS, as only it uses custom instruments + if (_vm->getPlatform() != Common::kPlatformApple2GS) { + debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); + return true; + } + + // Get info on the particular Apple IIGS AGI game's executable + const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); + if (exeInfo == NULL) { + warning("Unsupported Apple IIGS game, not loading instruments"); + return false; + } + + // List files in the game path + Common::FSList fslist; + Common::FSNode dir(ConfMan.get("path")); + if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { + warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); + return false; + } + + // Populate executable filenames list (Long filename and short filename) for searching + Common::StringArray exeNames; + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); + exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); + + // Populate wave filenames list (Long filename and short filename) for searching + Common::StringArray waveNames; + waveNames.push_back("SIERRASTANDARD"); + waveNames.push_back("SIERRAST"); + + // Search for the executable file and the wave file (i.e. check if any of the filenames match) + Common::FSList::const_iterator exeFsnode, waveFsnode; + exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); + waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); + + // Make sure that we found the executable file + if (exeFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); + return false; + } + + // Make sure that we found the wave file + if (waveFsnode == fslist.end()) { + warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); + return false; + } + + // Set the MIDI program change to instrument number mapping and + // load the instrument headers and their sample data. + // None of the tested SIERRASTANDARD-files have zeroes in them so + // there's no need to check for prematurely ending samples here. + setProgramChangeMapping(&exeInfo->instSet.progToInst); + return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo); +} + +/** Older Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV1 = { + {19, 20, 22, 23, 21, 24, 5, 5, 5, 5, + 6, 7, 10, 9, 11, 9, 15, 8, 5, 5, + 17, 16, 18, 12, 14, 5, 5, 5, 5, 5, + 0, 1, 2, 9, 3, 4, 15, 2, 2, 2, + 25, 13, 13, 25}, + 5 +}; + +/** Newer Apple IIGS AGI MIDI program change to instrument number mapping. */ +static const MidiProgramChangeMapping progToInstMappingV2 = { + {21, 22, 24, 25, 23, 26, 6, 6, 6, 6, + 7, 9, 12, 8, 13, 11, 17, 10, 6, 6, + 19, 18, 20, 14, 16, 6, 6, 6, 6, 6, + 0, 1, 2, 4, 3, 5, 17, 2, 2, 2, + 27, 15, 15, 27}, + 6 +}; + +/** Older Apple IIGS AGI instrument set. Used only by Space Quest I (AGI v1.002). */ +static const InstrumentSetInfo instSetV1 = { + 1192, 26, "7ee16bbc135171ffd6b9120cc7ff1af2", "edd3bf8905d9c238e02832b732fb2e18", progToInstMappingV1 +}; + +/** Newer Apple IIGS AGI instrument set (AGI v1.003+). Used by all others than Space Quest I. */ +static const InstrumentSetInfo instSetV2 = { + 1292, 28, "b7d428955bb90721996de1cbca25e768", "c05fb0b0e11deefab58bc68fbd2a3d07", progToInstMappingV2 +}; + +/** Information about different Apple IIGS AGI executables. */ +static const IIgsExeInfo IIgsExeInfos[] = { + {GID_SQ1, "SQ", 0x1002, 138496, 0x80AD, instSetV1}, + {GID_LSL1, "LL", 0x1003, 141003, 0x844E, instSetV2}, + {GID_AGIDEMO, "DEMO", 0x1005, 141884, 0x8469, instSetV2}, + {GID_KQ1, "KQ", 0x1006, 141894, 0x8469, instSetV2}, + {GID_PQ1, "PQ", 0x1007, 141882, 0x8469, instSetV2}, + {GID_MIXEDUP, "MG", 0x1013, 142552, 0x84B7, instSetV2}, + {GID_KQ2, "KQ2", 0x1013, 143775, 0x84B7, instSetV2}, + {GID_KQ3, "KQ3", 0x1014, 144312, 0x84B7, instSetV2}, + {GID_SQ2, "SQ2", 0x1014, 107882, 0x6563, instSetV2}, + {GID_MH1, "MH", 0x2004, 147678, 0x8979, instSetV2}, + {GID_KQ4, "KQ4", 0x2006, 147652, 0x8979, instSetV2}, + {GID_BC, "BC", 0x3001, 148192, 0x8979, instSetV2}, + {GID_GOLDRUSH, "GR", 0x3003, 148268, 0x8979, instSetV2} +}; + /** * Finds information about an Apple IIGS AGI executable based on the game ID. * @return A non-null IIgsExeInfo pointer if successful, otherwise NULL. @@ -840,80 +916,4 @@ bool SoundGen2GS::loadWaveFile(const Common::FSNode &wavePath, const IIgsExeInfo } } -/** - * A function object (i.e. a functor) for testing if a Common::FSNode - * object's name is equal (Ignoring case) to a string or to at least - * one of the strings in a list of strings. Can be used e.g. with find_if(). - */ -struct fsnodeNameEqualsIgnoreCase : public Common::UnaryFunction { -// FIXME: This should be replaced; use SearchMan instead - fsnodeNameEqualsIgnoreCase(const Common::StringArray &str) : _str(str) {} - fsnodeNameEqualsIgnoreCase(const Common::String str) { _str.push_back(str); } - bool operator()(const Common::FSNode ¶m) const { - for (Common::StringArray::const_iterator iter = _str.begin(); iter != _str.end(); ++iter) - if (param.getName().equalsIgnoreCase(*iter)) - return true; - return false; - } -private: - Common::StringArray _str; -}; - -bool SoundGen2GS::loadInstruments() { - // Check that the platform is Apple IIGS, as only it uses custom instruments - if (_vm->getPlatform() != Common::kPlatformApple2GS) { - debugC(3, kDebugLevelSound, "Platform isn't Apple IIGS so not loading any instruments"); - return true; - } - - // Get info on the particular Apple IIGS AGI game's executable - const IIgsExeInfo *exeInfo = getIIgsExeInfo((enum AgiGameID) _vm->getGameID()); - if (exeInfo == NULL) { - warning("Unsupported Apple IIGS game, not loading instruments"); - return false; - } - - // List files in the game path - Common::FSList fslist; - Common::FSNode dir(ConfMan.get("path")); - if (!dir.getChildren(fslist, Common::FSNode::kListFilesOnly)) { - warning("Invalid game path (\"%s\"), not loading Apple IIGS instruments", dir.getPath().c_str()); - return false; - } - - // Populate executable filenames list (Long filename and short filename) for searching - Common::StringArray exeNames; - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS16"); - exeNames.push_back(Common::String(exeInfo->exePrefix) + ".SYS"); - - // Populate wave filenames list (Long filename and short filename) for searching - Common::StringArray waveNames; - waveNames.push_back("SIERRASTANDARD"); - waveNames.push_back("SIERRAST"); - - // Search for the executable file and the wave file (i.e. check if any of the filenames match) - Common::FSList::const_iterator exeFsnode, waveFsnode; - exeFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(exeNames)); - waveFsnode = Common::find_if(fslist.begin(), fslist.end(), fsnodeNameEqualsIgnoreCase(waveNames)); - - // Make sure that we found the executable file - if (exeFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS game executable (%s), not loading instruments", exeNames.begin()->c_str()); - return false; - } - - // Make sure that we found the wave file - if (waveFsnode == fslist.end()) { - warning("Couldn't find Apple IIGS wave file (%s), not loading instruments", waveNames.begin()->c_str()); - return false; - } - - // Set the MIDI program change to instrument number mapping and - // load the instrument headers and their sample data. - // None of the tested SIERRASTANDARD-files have zeroes in them so - // there's no need to check for prematurely ending samples here. - setProgramChangeMapping(&exeInfo->instSet.progToInst); - return loadWaveFile(*waveFsnode, *exeInfo) && loadInstrumentHeaders(*exeFsnode, *exeInfo); -} - } // End of namespace Agi -- cgit v1.2.3 From 859212df2523e8b15076d968018dbf98618fd60f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:44:51 +0000 Subject: Implement translation support for ScummVM GUI. Based on patch #2903830: "Updated Translation Prototype" by alexbevi which in turn is based on patch #1739965 by jvprat. Currently it builds all translations right into ScummVM. Once the feature will be accepted more widely, i.e. more translations will pop up, it will be trivial to move translation strings to external file. Finished translation: Russian Unfinished translation: Hungarian Things which are nice to do: - Language code -> language mapping for more user friendness - Specifying fonts to be used with language - Updating of interface language without restart. It will require moving of much code to reflowLayout() methods for each dialog The .po files must be in single byte encodings. I.e. no support for Unicode. svn-id: r49759 --- engines/dialogs.cpp | 27 ++++++++++++++------------- 1 file changed, 14 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 954bc81470..4e4a656cc0 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -28,6 +28,7 @@ #include "common/savefile.h" #include "common/system.h" #include "common/events.h" +#include "common/translation.h" #include "graphics/scaler.h" @@ -85,37 +86,37 @@ MainMenuDialog::MainMenuDialog(Engine *engine) StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); version->setAlign(Graphics::kTextAlignCenter); - new GUI::ButtonWidget(this, "GlobalMenu.Resume", "Resume", kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("Resume"), kPlayCmd, 'P'); - _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", "Load", kLoadCmd, 'L'); + _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("Load"), kLoadCmd, 'L'); // TODO: setEnabled -> setVisible _loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)); - _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", "Save", kSaveCmd, 'S'); + _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("Save"), kSaveCmd, 'S'); // TODO: setEnabled -> setVisible _saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)); - new GUI::ButtonWidget(this, "GlobalMenu.Options", "Options", kOptionsCmd, 'O'); + new GUI::ButtonWidget(this, "GlobalMenu.Options", _("Options"), kOptionsCmd, 'O'); // The help button is disabled by default. // To enable "Help", an engine needs to use a subclass of MainMenuDialog // (at least for now, we might change how this works in the future). - _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", "Help", kHelpCmd, 'H'); + _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("Help"), kHelpCmd, 'H'); _helpButton->setEnabled(false); - new GUI::ButtonWidget(this, "GlobalMenu.About", "About", kAboutCmd, 'A'); + new GUI::ButtonWidget(this, "GlobalMenu.About", _("About"), kAboutCmd, 'A'); - _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", "Return to Launcher", kRTLCmd, 'R'); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("Return to Launcher"), kRTLCmd, 'R'); _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL)); - new GUI::ButtonWidget(this, "GlobalMenu.Quit", "Quit", kQuitCmd, 'Q'); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("Quit"), kQuitCmd, 'Q'); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions)); - _loadDialog = new GUI::SaveLoadChooser("Load game:", "Load"); + _loadDialog = new GUI::SaveLoadChooser(_("Load game:"), _("Load")); _loadDialog->setSaveMode(false); - _saveDialog = new GUI::SaveLoadChooser("Save game:", "Save"); + _saveDialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save")); _saveDialog->setSaveMode(true); } @@ -297,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // Add the buttons // - new GUI::ButtonWidget(this, "GlobalConfig.Ok", "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, "GlobalConfig.Cancel", "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("OK"), GUI::kOKCmd, 'O'); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("Cancel"), GUI::kCloseCmd, 'C'); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "GlobalConfig.Keys", "Keys", kKeysCmd, 'K'); + new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("Keys"), kKeysCmd, 'K'); _keysDialog = NULL; #endif } -- cgit v1.2.3 From 09b776ad1f421ac947826771b06c02975b2dcbb9 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:45:14 +0000 Subject: AGI: Made proper Tandy emulator default for PC games. svn-id: r49760 --- engines/agi/sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/sound.cpp b/engines/agi/sound.cpp index 9dda3e91f5..cb4e307ea6 100644 --- a/engines/agi/sound.cpp +++ b/engines/agi/sound.cpp @@ -175,10 +175,10 @@ SoundMgr::SoundMgr(AgiEngine *agi, Audio::Mixer *pMixer) { switch (_vm->_soundemu) { case SOUND_EMU_NONE: case SOUND_EMU_AMIGA: - case SOUND_EMU_PC: case SOUND_EMU_MAC: _soundGen = new SoundGenSarien(_vm, pMixer); break; + case SOUND_EMU_PC: case SOUND_EMU_PCJR: _soundGen = new SoundGenPCJr(_vm, pMixer); break; -- cgit v1.2.3 From 48d0d3008b3e886f06f63a9a67733cb3de8fcb0a Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:46:04 +0000 Subject: SCUMM: Fix bug #1879604. Bug 1879604: "MANIACNES: Music not played when loading game". Actually previous attempt to fix this bug was not successful since first entry of script 5 does not have needed functionality. Now we resume music manually. svn-id: r49763 --- engines/scumm/saveload.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/scumm/saveload.cpp b/engines/scumm/saveload.cpp index 7362dcd8cf..762b38fba2 100644 --- a/engines/scumm/saveload.cpp +++ b/engines/scumm/saveload.cpp @@ -577,6 +577,10 @@ bool ScummEngine::loadState(int slot, bool compat) { // Fixes bug #1766072: MANIACNES: Music Doesn't Start On Load Game if (_game.platform == Common::kPlatformNES) { runScript(5, 0, 0, 0); + + if (VAR(224)) { + _sound->addSoundToQueue(VAR(224)); + } } return true; -- cgit v1.2.3 From ba72975d3f5e88691506c670158ccda2e542013b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:46:23 +0000 Subject: SCUMM: Fix bug #1328120: Bug #1328120: "MANIACNES: Screen width incorrect, camera halts sometimes". Fixed by workaround and was tested with intro and on the kitchen, where now it is possible to see Edna without her noticing you first. svn-id: r49764 --- engines/scumm/scumm.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index bb50ce7bb2..862353bf95 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -2081,6 +2081,12 @@ void ScummEngine::scummLoop_updateScummVars() { if (_game.version >= 7) { VAR(VAR_CAMERA_POS_X) = camera._cur.x; VAR(VAR_CAMERA_POS_Y) = camera._cur.y; + } else if (_game.platform == Common::kPlatformNES) { + // WORKAROUND: + // Since there are 2 2-stripes wide borders in MM NES screen, + // we have to compensate for it here. This fixes paning effects. + // Fixes bug #1328120: "MANIACNES: Screen width incorrect, camera halts sometimes" + VAR(VAR_CAMERA_POS_X) = (camera._cur.x >> V12_X_SHIFT) + 2; } else if (_game.version <= 2) { VAR(VAR_CAMERA_POS_X) = camera._cur.x >> V12_X_SHIFT; } else { -- cgit v1.2.3 From 3fafa07ab0aeb65fedad159fb0cf345cc8f5f278 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:47:31 +0000 Subject: GUI: Added in-place hotkeys for widgets. Now it is possible to specify hotkeys in place for ButtonWidget and CheckboxWidget (the only widgets with hotkeys now). Use de-facto standard with putting hotkey between tildes (~). Like '~O~pen'. The tildes gets stripped before after hotkey is extracted. This is done for giving translators possibility to specify their own hotkeys. Old hotkeys defined at widget instance creation are left for leaving possibility to specify non-printable hotkeys such as Common::ASCII_ESCAPE. Translation files were updated respectively. svn-id: r49766 --- engines/dialogs.cpp | 22 +++++++++++----------- engines/scumm/dialogs.cpp | 7 ++++--- 2 files changed, 15 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 4e4a656cc0..0f391692e8 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -86,31 +86,31 @@ MainMenuDialog::MainMenuDialog(Engine *engine) StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); version->setAlign(Graphics::kTextAlignCenter); - new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("Resume"), kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), kPlayCmd, 'P'); - _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("Load"), kLoadCmd, 'L'); + _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), kLoadCmd); // TODO: setEnabled -> setVisible _loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)); - _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("Save"), kSaveCmd, 'S'); + _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), kSaveCmd); // TODO: setEnabled -> setVisible _saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)); - new GUI::ButtonWidget(this, "GlobalMenu.Options", _("Options"), kOptionsCmd, 'O'); + new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), kOptionsCmd); // The help button is disabled by default. // To enable "Help", an engine needs to use a subclass of MainMenuDialog // (at least for now, we might change how this works in the future). - _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("Help"), kHelpCmd, 'H'); + _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), kHelpCmd); _helpButton->setEnabled(false); - new GUI::ButtonWidget(this, "GlobalMenu.About", _("About"), kAboutCmd, 'A'); + new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), kAboutCmd); - _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("Return to Launcher"), kRTLCmd, 'R'); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), kRTLCmd); _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL)); - new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("Quit"), kQuitCmd, 'Q'); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), kQuitCmd); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions)); @@ -298,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // Add the buttons // - new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("OK"), GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("Cancel"), GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), GUI::kOKCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), GUI::kCloseCmd); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("Keys"), kKeysCmd, 'K'); + new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), kKeysCmd); _keysDialog = NULL; #endif } diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index d9c24ddca2..258b1875fe 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -26,6 +26,7 @@ #include "common/savefile.h" #include "common/system.h" #include "common/events.h" +#include "common/translation.h" #include "graphics/scaler.h" @@ -283,9 +284,9 @@ HelpDialog::HelpDialog(const GameSettings &game) _numPages = ScummHelp::numPages(_game.id); - _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", "Previous", kPrevCmd, 'P'); - _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", "Next", kNextCmd, 'N'); - new GUI::ButtonWidget(this, "ScummHelp.Close", "Close", GUI::kCloseCmd, 'C'); + _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), kPrevCmd); + _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), kNextCmd); + new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), GUI::kCloseCmd); _prevButton->clearFlags(WIDGET_ENABLED); _numLines = HELP_NUM_LINES; -- cgit v1.2.3 From 9d4d191baa0eafcdd470f33bd589e204bd8e5863 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:50:49 +0000 Subject: SAGA: fix timers. Second parameter to intallTimerCallback is in _micro_seconds. Correct calls which assumed milliseconds. svn-id: r49771 --- engines/saga/music.cpp | 2 +- engines/saga/puzzle.cpp | 10 +++++----- 2 files changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index f38e47dc48..8b8f26d5a0 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -234,7 +234,7 @@ void Music::setVolume(int volume, int time) { return; } - _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 100L, this); + _vm->getTimerManager()->installTimerProc(&musicVolumeGaugeCallback, time * 3000L, this); } bool Music::isPlaying() { diff --git a/engines/saga/puzzle.cpp b/engines/saga/puzzle.cpp index 957ab3c8b6..5b13473d77 100644 --- a/engines/saga/puzzle.cpp +++ b/engines/saga/puzzle.cpp @@ -411,12 +411,12 @@ void Puzzle::solicitHint() { switch (_hintRqState) { case kRQSpeaking: if (_vm->_actor->isSpeaking()) { - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50 * 1000000, this); break; } _hintRqState = _hintNextRqState; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 333333, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 100*1000000/3, this); break; case kRQNoHint: @@ -439,11 +439,11 @@ void Puzzle::solicitHint() { // Roll to see if Sakka scolds if (_vm->_rnd.getRandomNumber(1)) { _hintRqState = kRQSakkaDenies; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 200*1000000, this); } else { _hintRqState = kRQSpeaking; _hintNextRqState = kRQHintRequested; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this); } break; @@ -456,7 +456,7 @@ void Puzzle::solicitHint() { _hintRqState = kRQSpeaking; _hintNextRqState = kRQHintRequestedStage2; - _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50000, this); + _vm->getTimerManager()->installTimerProc(&hintTimerCallback, 50*1000000, this); _vm->_interface->converseClear(); _vm->_interface->converseAddText(optionsStr[_lang][kROAccept], 0, 1, 0, 0 ); -- cgit v1.2.3 From a8a44a07d15aa3012ca27b38db3c702c3a40b0a3 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:51:10 +0000 Subject: SCI: Fix timer. installTimerProc requires interval specified in milliseconds, not microseconds. Correct palVary method accordingly. svn-id: r49772 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index f9d320122b..d28fb2ada1 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -455,7 +455,7 @@ void GfxPalette::startPalVary(uint16 paletteId, uint16 ticks) { _palVaryId = paletteId; _palVaryStart = g_system->getMillis(); _palVaryEnd = _palVaryStart + ticks * 1000 / 60; - g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000 / 60, this); + g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60, this); } void GfxPalette::togglePalVary(bool pause) { -- cgit v1.2.3 From 01f9006ee7e8d0fd153f42fb00afbc25c4804d2b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:52:35 +0000 Subject: GUI: Implement tooltips. FR #2821513. FR #2821513: "GUI: add tooltips". Added tooltips for Add Game button, clear field buttons and couple other. Current problem: Only first call correctly restores text. I could not find where restore information gets lost. svn-id: r49774 --- engines/dialogs.cpp | 22 +++++++++++----------- engines/scumm/dialogs.cpp | 6 +++--- 2 files changed, 14 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/dialogs.cpp b/engines/dialogs.cpp index 0f391692e8..2397a474c6 100644 --- a/engines/dialogs.cpp +++ b/engines/dialogs.cpp @@ -86,31 +86,31 @@ MainMenuDialog::MainMenuDialog(Engine *engine) StaticTextWidget *version = new StaticTextWidget(this, "GlobalMenu.Version", gScummVMVersionDate); version->setAlign(Graphics::kTextAlignCenter); - new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), kPlayCmd, 'P'); + new GUI::ButtonWidget(this, "GlobalMenu.Resume", _("~R~esume"), 0, kPlayCmd, 'P'); - _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), kLoadCmd); + _loadButton = new GUI::ButtonWidget(this, "GlobalMenu.Load", _("~L~oad"), 0, kLoadCmd); // TODO: setEnabled -> setVisible _loadButton->setEnabled(_engine->hasFeature(Engine::kSupportsLoadingDuringRuntime)); - _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), kSaveCmd); + _saveButton = new GUI::ButtonWidget(this, "GlobalMenu.Save", _("~S~ave"), 0, kSaveCmd); // TODO: setEnabled -> setVisible _saveButton->setEnabled(_engine->hasFeature(Engine::kSupportsSavingDuringRuntime)); - new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), kOptionsCmd); + new GUI::ButtonWidget(this, "GlobalMenu.Options", _("~O~ptions"), 0, kOptionsCmd); // The help button is disabled by default. // To enable "Help", an engine needs to use a subclass of MainMenuDialog // (at least for now, we might change how this works in the future). - _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), kHelpCmd); + _helpButton = new GUI::ButtonWidget(this, "GlobalMenu.Help", _("~H~elp"), 0, kHelpCmd); _helpButton->setEnabled(false); - new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), kAboutCmd); + new GUI::ButtonWidget(this, "GlobalMenu.About", _("~A~bout"), 0, kAboutCmd); - _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), kRTLCmd); + _rtlButton = new GUI::ButtonWidget(this, "GlobalMenu.RTL", _("~R~eturn to Launcher"), 0, kRTLCmd); _rtlButton->setEnabled(_engine->hasFeature(Engine::kSupportsRTL)); - new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), kQuitCmd); + new GUI::ButtonWidget(this, "GlobalMenu.Quit", _("~Q~uit"), 0, kQuitCmd); _aboutDialog = new GUI::AboutDialog(); _optionsDialog = new ConfigDialog(_engine->hasFeature(Engine::kSupportsSubtitleOptions)); @@ -298,11 +298,11 @@ ConfigDialog::ConfigDialog(bool subtitleControls) // Add the buttons // - new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), GUI::kOKCmd); - new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), GUI::kCloseCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Ok", _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Cancel", _("~C~ancel"), 0, GUI::kCloseCmd); #ifdef SMALL_SCREEN_DEVICE - new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), kKeysCmd); + new GUI::ButtonWidget(this, "GlobalConfig.Keys", _("~K~eys"), 0, kKeysCmd); _keysDialog = NULL; #endif } diff --git a/engines/scumm/dialogs.cpp b/engines/scumm/dialogs.cpp index 258b1875fe..1e0bf6d4be 100644 --- a/engines/scumm/dialogs.cpp +++ b/engines/scumm/dialogs.cpp @@ -284,9 +284,9 @@ HelpDialog::HelpDialog(const GameSettings &game) _numPages = ScummHelp::numPages(_game.id); - _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), kPrevCmd); - _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), kNextCmd); - new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), GUI::kCloseCmd); + _prevButton = new GUI::ButtonWidget(this, "ScummHelp.Prev", _("~P~revious"), 0, kPrevCmd); + _nextButton = new GUI::ButtonWidget(this, "ScummHelp.Next", _("~N~ext"), 0, kNextCmd); + new GUI::ButtonWidget(this, "ScummHelp.Close", _("~C~lose"), 0, GUI::kCloseCmd); _prevButton->clearFlags(WIDGET_ENABLED); _numLines = HELP_NUM_LINES; -- cgit v1.2.3 From eef983c2c6eec26c29d032818a838c563e0a0b98 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:55:07 +0000 Subject: AGI: enable MIDI in options since now there are ways to play it. svn-id: r49781 --- engines/agi/detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index a809d24467..aa4d368fca 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -145,7 +145,7 @@ static const ADParams detectionParams = { // Flags 0, // Additional GUI options (for every game} - Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, + Common::GUIO_NOSPEECH, // Maximum directory depth 1 }; -- cgit v1.2.3 From 2bcafcb02dd406a36fd0a11c6b0df742840a9a7e Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:55:31 +0000 Subject: Sound: add PCJR as a pseudodriver. Since AGI distinguishes between PCSPK and PCJR/Tandy, make it as a pseudodriver. svn-id: r49782 --- engines/agi/agi.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 2f87d7b8ef..21b28fd445 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -583,7 +583,7 @@ void AgiEngine::initialize() { } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; } else { - switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI)) { + switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI)) { case MD_PCSPK: _soundemu = SOUND_EMU_PC; break; -- cgit v1.2.3 From 67bc7115804b6f256f776fc761f7fffffa901c31 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:56:12 +0000 Subject: GUI: Implement MIDI drivers as GUI options. Proper version of patch #2988641: "GSoC: Select drivers in GUI based on output types". So far only SCUMM engine supports this feature. svn-id: r49783 --- engines/scumm/detection.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index d8b758c8b2..667dab91de 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -883,7 +883,7 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { } } - dg.setGUIOptions(x->game.guioptions); + dg.setGUIOptions(x->game.guioptions | MidiDriver::midiDriverFlags2GUIO(x->game.midi)); detectedGames.push_back(dg); } -- cgit v1.2.3 From 01bc5dda944f121187a4499f03d3a3814741f093 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:57:28 +0000 Subject: GUI: Implemented Languages as GUI options. SCUMM and AdvancedDetector support this feature. svn-id: r49786 --- engines/advancedDetector.cpp | 1 + engines/game.cpp | 4 ++++ engines/game.h | 1 + engines/scumm/detection.cpp | 1 + 4 files changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 061eec2faf..ee0c5c7c62 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -208,6 +208,7 @@ static void updateGameDescriptor(GameDescriptor &desc, const ADGameDescription * desc["extra"] = realDesc->extra; desc.setGUIOptions(realDesc->guioptions | params.guioptions); + desc.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(realDesc->language)); } GameList AdvancedMetaEngine::detectGames(const Common::FSList &fslist) const { diff --git a/engines/game.cpp b/engines/game.cpp index c7f26019d6..dea6d37485 100644 --- a/engines/game.cpp +++ b/engines/game.cpp @@ -73,6 +73,10 @@ void GameDescriptor::setGUIOptions(uint32 guioptions) { erase("guioptions"); } +void GameDescriptor::appendGUIOptions(const Common::String &str) { + setVal("guioptions", getVal("guioptions", "") + " " + str); +} + void GameDescriptor::updateDesc(const char *extra) { // TODO: The format used here (LANG/PLATFORM/EXTRA) is not set in stone. // We may want to change the order (PLATFORM/EXTRA/LANG, anybody?), or diff --git a/engines/game.h b/engines/game.h index 49136ecf5a..b125421ff6 100644 --- a/engines/game.h +++ b/engines/game.h @@ -83,6 +83,7 @@ public: void updateDesc(const char *extra = 0); void setGUIOptions(uint32 options); + void appendGUIOptions(const Common::String &str); Common::String &gameid() { return getVal("gameid"); } Common::String &description() { return getVal("description"); } diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 667dab91de..21da732064 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -884,6 +884,7 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { } dg.setGUIOptions(x->game.guioptions | MidiDriver::midiDriverFlags2GUIO(x->game.midi)); + dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); detectedGames.push_back(dg); } -- cgit v1.2.3 From 0b83afce03572eb513dd2802a8ad4c0377600f84 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:57:47 +0000 Subject: MOHAWK: Sync with latest GUI changes. svn-id: r49787 --- engines/mohawk/dialogs.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/dialogs.cpp b/engines/mohawk/dialogs.cpp index c5327dbeea..c09763cbb3 100644 --- a/engines/mohawk/dialogs.cpp +++ b/engines/mohawk/dialogs.cpp @@ -30,6 +30,7 @@ #include "gui/GuiManager.h" #include "common/savefile.h" +#include "common/translation.h" namespace Mohawk { @@ -77,11 +78,11 @@ enum { }; MystOptionsDialog::MystOptionsDialog(MohawkEngine_Myst* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) { - _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z'); - _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Transitions Enabled", kTransCmd, 'T'); + _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd); + _transitionsCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~T~ransitions Enabled"), 0, kTransCmd); - new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd); } MystOptionsDialog::~MystOptionsDialog() { @@ -111,11 +112,11 @@ void MystOptionsDialog::handleCommand(GUI::CommandSender *sender, uint32 cmd, ui } RivenOptionsDialog::RivenOptionsDialog(MohawkEngine_Riven* vm) : GUI::OptionsDialog("", 120, 120, 360, 200), _vm(vm) { - _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, "Zip Mode Activated", kZipCmd, 'Z'); - _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, "Water Effect Enabled", kWaterCmd, 'W'); + _zipModeCheckbox = new GUI::CheckboxWidget(this, 15, 10, 300, 15, _("~Z~ip Mode Activated"), 0, kZipCmd); + _waterEffectCheckbox = new GUI::CheckboxWidget(this, 15, 30, 300, 15, _("~W~ater Effect Enabled"), 0, kWaterCmd); - new GUI::ButtonWidget(this, 95, 160, 120, 25, "OK", GUI::kOKCmd, 'O'); - new GUI::ButtonWidget(this, 225, 160, 120, 25, "Cancel", GUI::kCloseCmd, 'C'); + new GUI::ButtonWidget(this, 95, 160, 120, 25, _("~O~K"), 0, GUI::kOKCmd); + new GUI::ButtonWidget(this, 225, 160, 120, 25, _("~C~ancel"), 0, GUI::kCloseCmd); } RivenOptionsDialog::~RivenOptionsDialog() { -- cgit v1.2.3 From 44a39ffbc66dbc9f019f041a47aaf9ba5a24d19f Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:59:23 +0000 Subject: AdvancedDetector: Add new parameter directoryGlobs. Without this parameter mass detection gave tons of false alarms. Use globbing for narrowing down the depth search. svn-id: r49788 --- engines/advancedDetector.cpp | 19 ++++++++++++++++--- engines/advancedDetector.h | 10 +++++++++- engines/agi/detection.cpp | 4 +++- engines/agos/detection.cpp | 4 +++- engines/cine/detection.cpp | 4 +++- engines/cruise/detection.cpp | 4 +++- engines/draci/detection.cpp | 4 +++- engines/drascula/detection.cpp | 4 +++- engines/gob/detection.cpp | 4 +++- engines/groovie/detection.cpp | 4 +++- engines/kyra/detection.cpp | 4 +++- engines/lure/detection.cpp | 4 +++- engines/m4/detection.cpp | 4 +++- engines/made/detection.cpp | 4 +++- engines/mohawk/detection.cpp | 4 +++- engines/parallaction/detection.cpp | 4 +++- engines/saga/detection.cpp | 4 +++- engines/sci/detection.cpp | 4 +++- engines/teenagent/detection.cpp | 3 ++- engines/tinsel/detection.cpp | 4 +++- engines/touche/detection.cpp | 4 +++- engines/tucker/detection.cpp | 3 ++- 22 files changed, 83 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index ee0c5c7c62..974970ff0f 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -341,7 +341,7 @@ static void reportUnknown(const Common::FSNode &path, const SizeMD5Map &filesSiz static ADGameDescList detectGameFilebased(const FileMap &allFiles, const ADParams ¶ms); -static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth) { +static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, int depth, const char **directoryGlobs) { if (depth <= 0) return; @@ -354,10 +354,23 @@ static void composeFileHashMap(const Common::FSList &fslist, FileMap &allFiles, if (file->isDirectory()) { Common::FSList files; + if (!directoryGlobs) + continue; + + bool matched = false; + for (const char *glob = *directoryGlobs; *glob; glob++) + if (file->getName().matchString(glob, true)) { + matched = true; + break; + } + + if (!matched) + continue; + if (!file->getChildren(files, Common::FSNode::kListAll)) continue; - composeFileHashMap(files, allFiles, depth - 1); + composeFileHashMap(files, allFiles, depth - 1, directoryGlobs); } Common::String tstr = file->getName(); @@ -385,7 +398,7 @@ static ADGameDescList detectGame(const Common::FSList &fslist, const ADParams &p // First we compose a hashmap of all files in fslist. // Includes nifty stuff like removing trailing dots and ignoring case. - composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth)); + composeFileHashMap(fslist, allFiles, (params.depth == 0 ? 1 : params.depth), params.directoryGlobs); // Check which files are included in some ADGameDescription *and* present // in fslist. Compute MD5s and file sizes for these files. diff --git a/engines/advancedDetector.h b/engines/advancedDetector.h index a48dd0c1d2..de4fc3bbf8 100644 --- a/engines/advancedDetector.h +++ b/engines/advancedDetector.h @@ -192,11 +192,19 @@ struct ADParams { uint32 guioptions; /** - * * Maximum depth of directories to look up * If set to 0, the depth is 1 level */ uint32 depth; + + /** + * Case-insensitive list of directory globs which could be used for + * going deeper int directory structure. + * @see String::matchString() method for format description. + * + * @note Last item must be 0 + */ + const char **directoryGlobs; }; diff --git a/engines/agi/detection.cpp b/engines/agi/detection.cpp index aa4d368fca..d1bed5d716 100644 --- a/engines/agi/detection.cpp +++ b/engines/agi/detection.cpp @@ -147,7 +147,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOSPEECH, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; using namespace Agi; diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index 9a23dde426..cec2db2c10 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -104,7 +104,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOLAUNCHLOAD, // Maximum directory depth - 2 + 2, + // List of directory globs + 0 }; using namespace AGOS; diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp index bcc4951140..b92ad8a0a2 100644 --- a/engines/cine/detection.cpp +++ b/engines/cine/detection.cpp @@ -82,7 +82,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class CineMetaEngine : public AdvancedMetaEngine { diff --git a/engines/cruise/detection.cpp b/engines/cruise/detection.cpp index 9088b8261e..e43fadf598 100644 --- a/engines/cruise/detection.cpp +++ b/engines/cruise/detection.cpp @@ -239,7 +239,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOSPEECH | Common::GUIO_NOMIDI, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class CruiseMetaEngine : public AdvancedMetaEngine { diff --git a/engines/draci/detection.cpp b/engines/draci/detection.cpp index 39834ab5fa..e1025e698a 100644 --- a/engines/draci/detection.cpp +++ b/engines/draci/detection.cpp @@ -96,7 +96,9 @@ const ADParams detectionParams = { // Global GUI options Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class DraciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/drascula/detection.cpp b/engines/drascula/detection.cpp index a0781e0bff..c10222cadd 100644 --- a/engines/drascula/detection.cpp +++ b/engines/drascula/detection.cpp @@ -266,7 +266,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOMIDI, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class DrasculaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/gob/detection.cpp b/engines/gob/detection.cpp index 3d83f12e39..a1eb8055aa 100644 --- a/engines/gob/detection.cpp +++ b/engines/gob/detection.cpp @@ -109,7 +109,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOLAUNCHLOAD, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class GobMetaEngine : public AdvancedMetaEngine { diff --git a/engines/groovie/detection.cpp b/engines/groovie/detection.cpp index 1f7156b2fc..b30c2361d2 100644 --- a/engines/groovie/detection.cpp +++ b/engines/groovie/detection.cpp @@ -178,7 +178,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOSUBTITLES | Common::GUIO_NOSFX, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; diff --git a/engines/kyra/detection.cpp b/engines/kyra/detection.cpp index 4ed314934d..f3e6c7c8cc 100644 --- a/engines/kyra/detection.cpp +++ b/engines/kyra/detection.cpp @@ -63,7 +63,9 @@ const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class KyraMetaEngine : public AdvancedMetaEngine { diff --git a/engines/lure/detection.cpp b/engines/lure/detection.cpp index d8c7b483f8..dd2a702e2a 100644 --- a/engines/lure/detection.cpp +++ b/engines/lure/detection.cpp @@ -198,7 +198,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOSPEECH, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class LureMetaEngine : public AdvancedMetaEngine { diff --git a/engines/m4/detection.cpp b/engines/m4/detection.cpp index 80a899f1ac..4b204996f3 100644 --- a/engines/m4/detection.cpp +++ b/engines/m4/detection.cpp @@ -402,7 +402,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOMIDI, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class M4MetaEngine : public AdvancedMetaEngine { diff --git a/engines/made/detection.cpp b/engines/made/detection.cpp index 081bb98006..dd2becd3b8 100644 --- a/engines/made/detection.cpp +++ b/engines/made/detection.cpp @@ -495,7 +495,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class MadeMetaEngine : public AdvancedMetaEngine { diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index a01f4a8759..9c3154a8bd 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -143,7 +143,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game) Common::GUIO_NONE, // Maximum directory depth - 2 + 2, + // List of directory globs + 0 }; class MohawkMetaEngine : public AdvancedMetaEngine { diff --git a/engines/parallaction/detection.cpp b/engines/parallaction/detection.cpp index 2ecaf1c2d6..e00a087923 100644 --- a/engines/parallaction/detection.cpp +++ b/engines/parallaction/detection.cpp @@ -242,7 +242,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NOLAUNCHLOAD, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class ParallactionMetaEngine : public AdvancedMetaEngine { diff --git a/engines/saga/detection.cpp b/engines/saga/detection.cpp index b57b056806..7913291527 100644 --- a/engines/saga/detection.cpp +++ b/engines/saga/detection.cpp @@ -124,7 +124,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class SagaMetaEngine : public AdvancedMetaEngine { diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index b402f7cc0b..7163c879b1 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -312,7 +312,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class SciMetaEngine : public AdvancedMetaEngine { diff --git a/engines/teenagent/detection.cpp b/engines/teenagent/detection.cpp index 4c61e20b7a..a2dab9658d 100644 --- a/engines/teenagent/detection.cpp +++ b/engines/teenagent/detection.cpp @@ -92,7 +92,8 @@ static const ADParams detectionParams = { 0, 0, Common::GUIO_NONE, - 1 + 1, + 0 }; #define MAX_SAVES 20 diff --git a/engines/tinsel/detection.cpp b/engines/tinsel/detection.cpp index c46a93fb38..d6bdad6032 100644 --- a/engines/tinsel/detection.cpp +++ b/engines/tinsel/detection.cpp @@ -97,7 +97,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class TinselMetaEngine : public AdvancedMetaEngine { diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index 72f87a2f3f..f336c2e008 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -136,7 +136,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1 + 1, + // List of directory globs + 0 }; class ToucheMetaEngine : public AdvancedMetaEngine { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index 7f88a8ff2f..0a9dec9b46 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -115,7 +115,8 @@ static const ADParams detectionParams = { 0, 0, Common::GUIO_NONE, - 1 + 1, + 0 }; static const ADGameDescription tuckerDemoGameDescription = { -- cgit v1.2.3 From f2a62bb1f5bdc422eda47b5d673614e02d796035 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 10:59:43 +0000 Subject: MOHAWK: Properly add detection for Riven DVD. svn-id: r49789 --- engines/mohawk/detection.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index 9c3154a8bd..c3a0c17251 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -123,6 +123,13 @@ static const PlainGameDescriptor mohawkGames[] = { #include "mohawk/detection_tables.h" +static const char *directoryGlobs[] = { + "all", + "assets1", + "data", + 0 +}; + static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure (const byte *)Mohawk::gameDescriptions, @@ -145,7 +152,7 @@ static const ADParams detectionParams = { // Maximum directory depth 2, // List of directory globs - 0 + directoryGlobs }; class MohawkMetaEngine : public AdvancedMetaEngine { -- cgit v1.2.3 From 03ed49169c22cf169369ccec005e6e6e6cb129dd Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 11:00:07 +0000 Subject: AGOS: Readd Simon1 Acorn CD detection. svn-id: r49790 --- engines/agos/detection.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agos/detection.cpp b/engines/agos/detection.cpp index cec2db2c10..646e63dacf 100644 --- a/engines/agos/detection.cpp +++ b/engines/agos/detection.cpp @@ -84,6 +84,11 @@ static const PlainGameDescriptor simonGames[] = { #include "agos/detection_tables.h" +static const char *directoryGlobs[] = { + "execute", // Used by Simon1 Acorn CD + 0 +}; + static const ADParams detectionParams = { // Pointer to ADGameDescription or its superset structure (const byte *)AGOS::gameDescriptions, @@ -106,7 +111,7 @@ static const ADParams detectionParams = { // Maximum directory depth 2, // List of directory globs - 0 + directoryGlobs }; using namespace AGOS; -- cgit v1.2.3 From b6940caaaa59a534774425104f48733f8277d82b Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Tue, 15 Jun 2010 11:04:35 +0000 Subject: SCUMM: Added directory globs for in-depth search. The code was compied from AdvancedDetector. Currently it is set up to detect Mac indy3/loom which contains it data in Rooms 1, Roooms 2 and Rooms 3 directories. svn-id: r49798 --- engines/scumm/detection.cpp | 19 ++++++++++++++++--- engines/scumm/detection_tables.h | 9 +++++++++ 2 files changed, 25 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 21da732064..c164ac38fd 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -381,7 +381,7 @@ static void computeGameSettingsFromMD5(const Common::FSList &fslist, const GameF } } -static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth) { +static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map, int depth, const char **globs) { if (depth <= 0) return; @@ -395,10 +395,23 @@ static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map d.md5Entry = 0; fileMD5Map[file->getName()] = d; } else { + if (!directoryGlobs) + continue; + + bool matched = false; + for (const char *glob = *globs; *glob; glob++) + if (file->getName().matchString(glob, true)) { + matched = true; + break; + } + + if (!matched) + continue; + Common::FSList files; if (file->getChildren(files, Common::FSNode::kListAll)) { - composeFileHashMap(files, fileMD5Map, depth - 1); + composeFileHashMap(files, fileMD5Map, depth - 1, directoryGlobs); } } } @@ -410,7 +423,7 @@ static void detectGames(const Common::FSList &fslist, Common::Listgameid; ++gfp) { diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index 0b90af4ec4..db6d04b785 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -48,6 +48,15 @@ namespace Scumm { #pragma mark --- Tables --- #pragma mark - +/** + * This table contains list of directories which could contain game data + * and which should be looked into during detection. + */ +static const char *directoryGlobs[] = { + "rooms *", // Mac version of indy3/loom + 0 +}; + /** * This table contains all game IDs supported by the SCUMM engine, and maps -- cgit v1.2.3 From deb907de637b963af91aa530251fad5ad6b45025 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 15 Jun 2010 11:19:32 +0000 Subject: Bugfixes to depth processing that was causing the 'Microprose Design Group' message not to appear in the first intro scene svn-id: r49801 --- engines/m4/graphics.cpp | 10 +++++----- engines/m4/graphics.h | 9 ++++----- engines/m4/mads_views.cpp | 4 ++-- 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 36de60af6c..d7a0c9edfc 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -400,8 +400,8 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest * Copies a given image onto a destination surface with scaling, transferring only pixels that meet * the specified depth requirement on a secondary surface contain depth information */ -void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthsSurface, - int scale, int transparentColour) { +void M4Surface::copyFrom(M4Surface *src, int destX, int destY, Common::Point destAdjust, + int depth, M4Surface *depthsSurface, int scale, int transparentColour) { if (scale == 100) { // Copy the specified area @@ -426,8 +426,8 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf byte *data = src->getBasePtr(); byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); byte *depthsData = depthsSurface->getBasePtr(); - byte *depthsPtr = depthsData + (src->width() * copyRect.top + copyRect.left); - byte *destPtr = (byte *)pixels + (destY * width()) + destX; + byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX; + byte *destPtr = (byte *)pixels + ((destY + destAdjust.y) * pitch) + destX + destAdjust.x; // 100% scaling variation for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { @@ -520,7 +520,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surf if (spriteHeight <= 0) return; - byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); + byte *destPixelsP = this->getBasePtr(destX + spriteLeft + destAdjust.x, destY + spriteTop + destAdjust.y); const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop); spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 6901b72e87..24c0edf223 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -157,10 +157,9 @@ public: void reset(); void frameRect(const Common::Rect &r, uint8 color); void fillRect(const Common::Rect &r, uint8 color); - void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, - int transparentColour = -1); - void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, int scale, - int transparentColour = -1); + void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColour = -1); + void copyFrom(M4Surface *src, int destX, int destY, Common::Point destAdjust, int depth, M4Surface *depthSurface, + int scale, int transparentColour = -1); void update() { if (_isScreen) { @@ -182,7 +181,7 @@ public: } inline void copyTo(M4Surface *dest, int destX, int destY, int depth, M4Surface *depthsSurface, int scale, int transparentColour = -1) { - dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour); + dest->copyFrom(this, destX, destY, Common::Point(0, 0), depth, depthsSurface, scale, transparentColour); } void scrollX(int xAmount); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index af4177e6bb..5a7abcf484 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -196,7 +196,7 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { // Minimalised drawing assert(slot.spriteListIndex < (int)_sprites.size()); M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - spr->copyTo(view, slot.xp, slot.yp + yOffset, slot.depth, _owner._depthSurface, slot.scale, 0); + view->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, slot.scale, 0); } else { int xp, yp; M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1); @@ -211,7 +211,7 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { if (slot.depth > 1) { // Draw the frame with depth processing - spr->copyTo(view, xp, yp + yOffset, slot.depth, _owner._depthSurface, 100, 0); + view->copyFrom(spr, xp, yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, 100, 0); } else { // No depth, so simply draw the image spr->copyTo(view, xp, yp + yOffset, 0); -- cgit v1.2.3 From 5b484b5be7a9b9abbaf6b686e59b2ee9f88acb2d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 11:44:55 +0000 Subject: Fixed compilation when SCI32 code is not enabled svn-id: r49805 --- engines/sci/console.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 0c017af281..1c6f4461a8 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2191,6 +2191,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { break; case KSIG_REF: { switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { +#ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); @@ -2201,6 +2202,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { Common::hexdump((const byte *) array->getRawData(), array->getSize(), 16, 0); break; } +#endif default: { int size; const SegmentRef block = _engine->_gamestate->_segMan->dereference(reg); -- cgit v1.2.3 From 59d0035b033ac4791bfa91245418852a66e4e63a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 12:01:49 +0000 Subject: SCI: move portrait methods to gfxPaint16 svn-id: r49806 --- engines/sci/engine/kgraphics.cpp | 6 +++--- engines/sci/graphics/gui.cpp | 20 -------------------- engines/sci/graphics/gui.h | 4 ---- engines/sci/graphics/paint16.cpp | 20 ++++++++++++++++++++ engines/sci/graphics/paint16.h | 4 ++++ 5 files changed, 27 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index f025d03a09..cf6bd41fa9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -698,7 +698,7 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { case 0: { // load if (argc == 2) { Common::String resourceName = s->_segMan->getString(argv[1]); - s->r_acc = g_sci->_gui->portraitLoad(resourceName); + s->r_acc = g_sci->_gfxPaint16->kernelPortraitLoad(resourceName); } else { warning("kPortrait(loadResource) called with unsupported argc %d", argc); } @@ -715,7 +715,7 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { uint seq = argv[8].toUint16() & 0xff; // argv[9] is usually 0??!! - g_sci->_gui->portraitShow(resourceName, position, resourceNum, noun, verb, cond, seq); + g_sci->_gfxPaint16->kernelPortraitShow(resourceName, position, resourceNum, noun, verb, cond, seq); return SIGNAL_REG; } else { warning("kPortrait(show) called with unsupported argc %d", argc); @@ -725,7 +725,7 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { case 2: { // unload if (argc == 2) { uint16 portraitId = argv[1].toUint16(); - g_sci->_gui->portraitUnload(portraitId); + g_sci->_gfxPaint16->kernelPortraitUnload(portraitId); } else { warning("kPortrait(unload) called with unsupported argc %d", argc); } diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 63ac6c0a05..677359c201 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -43,7 +43,6 @@ #include "sci/graphics/animate.h" #include "sci/graphics/controls.h" #include "sci/graphics/menu.h" -#include "sci/graphics/portrait.h" #include "sci/graphics/text16.h" #include "sci/graphics/transitions.h" #include "sci/graphics/view.h" @@ -112,23 +111,4 @@ void SciGui::textColors(int argc, reg_t *argv) { _text16->CodeSetColors(argc, argv); } -reg_t SciGui::portraitLoad(Common::String resourceName) { - //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName); - return NULL_REG; -} - -void SciGui::portraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { - Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), this, _screen, _palette, _audio, resourceName); - // TODO: cache portraits - // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates - // on kDrawCel, yeah this whole stuff makes sense) - position.x += _ports->getPort()->left; position.y += _ports->getPort()->top; - _screen->adjustToUpscaledCoordinates(position.y, position.x); - myPortrait->doit(position, resourceId, noun, verb, cond, seq); - delete myPortrait; -} - -void SciGui::portraitUnload(uint16 portraitId) { -} - } // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index 8e4abdf5b7..73c37de099 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -57,10 +57,6 @@ public: virtual void textFonts(int argc, reg_t *argv); virtual void textColors(int argc, reg_t *argv); - virtual reg_t portraitLoad(Common::String resourceName); - virtual void portraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); - virtual void portraitUnload(uint16 portraitId); - protected: GfxCursor *_cursor; EngineState *_s; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 6a13f792cb..eb3fea969a 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -42,6 +42,7 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" +#include "sci/graphics/portrait.h" #include "sci/graphics/text16.h" #include "sci/graphics/transitions.h" @@ -580,4 +581,23 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) { } } +reg_t GfxPaint16::kernelPortraitLoad(Common::String resourceName) { + //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName); + return NULL_REG; +} + +void GfxPaint16::kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { + Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), this, _screen, _palette, _audio, resourceName); + // TODO: cache portraits + // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates + // on kDrawCel, yeah this whole stuff makes sense) + position.x += _ports->getPort()->left; position.y += _ports->getPort()->top; + _screen->adjustToUpscaledCoordinates(position.y, position.x); + myPortrait->doit(position, resourceId, noun, verb, cond, seq); + delete myPortrait; +} + +void GfxPaint16::kernelPortraitUnload(uint16 portraitId) { +} + } // End of namespace Sci diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 65f9dd0d9c..7a1a3bd7eb 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -91,6 +91,10 @@ public: void kernelShakeScreen(uint16 shakeCount, uint16 directions); + reg_t kernelPortraitLoad(Common::String resourceName); + void kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); + void kernelPortraitUnload(uint16 portraitId); + private: ResourceManager *_resMan; SegManager *_segMan; -- cgit v1.2.3 From 69bfbdfa0406cd12c2275d481e296cf4f1e3faad Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:08:40 +0000 Subject: SCI: Move ResourceSource to new header resource_intern.h svn-id: r49807 --- engines/sci/resource.cpp | 1 + engines/sci/resource.h | 29 +++------------------ engines/sci/resource_audio.cpp | 1 + engines/sci/resource_intern.h | 59 ++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 25 deletions(-) create mode 100644 engines/sci/resource_intern.h (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 1906510d24..d25c3286df 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -28,6 +28,7 @@ #include "common/file.h" #include "sci/resource.h" +#include "sci/resource_intern.h" #include "sci/util.h" namespace Sci { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 7fbb3ca9a2..e94eaf4d57 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -23,11 +23,10 @@ * */ -#ifndef SCI_SCICORE_RESOURCE_H -#define SCI_SCICORE_RESOURCE_H +#ifndef SCI_RESOURCE_H +#define SCI_RESOURCE_H #include "common/fs.h" -#include "common/macresman.h" #include "common/str.h" #include "sci/graphics/helpers.h" // for ViewType @@ -122,27 +121,7 @@ const char *getResourceTypeName(ResourceType restype); class ResourceManager; - -struct ResourceSource { - ResSourceType source_type; - bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? - const Common::FSNode *resourceFile; - int volume_number; - ResourceSource *associated_map; - uint32 audioCompressionType; - int32 *audioCompressionOffsetMapping; - Common::MacResManager macResMan; - ResourceSource() { - source_type = kSourceDirectory; - scanned = false; - resourceFile = 0; - volume_number = 0; - associated_map = NULL; - audioCompressionType = 0; - audioCompressionOffsetMapping = NULL; - } -}; +struct ResourceSource; class ResourceId { public: @@ -538,4 +517,4 @@ private: } // End of namespace Sci -#endif // SCI_SCICORE_RESOURCE_H +#endif // SCI_RESOURCE_H diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 0e60239331..d2f1d53e11 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -28,6 +28,7 @@ #include "common/file.h" #include "sci/resource.h" +#include "sci/resource_intern.h" #include "sci/util.h" namespace Sci { diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h new file mode 100644 index 0000000000..01f1f45180 --- /dev/null +++ b/engines/sci/resource_intern.h @@ -0,0 +1,59 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef SCI_RESOURCE_INTERN_H +#define SCI_RESOURCE_INTERN_H + +#include "common/macresman.h" + +#include "sci/resource.h" + +namespace Sci { + +struct ResourceSource { + ResSourceType source_type; + bool scanned; + Common::String location_name; // FIXME: Replace by FSNode ? + const Common::FSNode *resourceFile; + int volume_number; + ResourceSource *associated_map; + uint32 audioCompressionType; + int32 *audioCompressionOffsetMapping; + Common::MacResManager macResMan; + ResourceSource() { + source_type = kSourceDirectory; + scanned = false; + resourceFile = 0; + volume_number = 0; + associated_map = NULL; + audioCompressionType = 0; + audioCompressionOffsetMapping = NULL; + } +}; + + +} // End of namespace Sci + +#endif // SCI_RESOURCE_INTERN_H -- cgit v1.2.3 From e32f3d5a4344953d9fdec6b9bd1627a4eb8de156 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:09:03 +0000 Subject: SCI: cleanup svn-id: r49808 --- engines/sci/resource.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.h b/engines/sci/resource.h index e94eaf4d57..822d1d31f4 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -34,10 +34,7 @@ #include "sci/sci.h" namespace Common { -class ReadStream; -class WriteStream; class File; -class FSNode; } namespace Sci { @@ -192,6 +189,10 @@ public: byte *_header; uint32 _headerSize; + /** + * Write the resource to the specified stream. + * This method is used only by the "dump" debugger command. + */ void writeToStream(Common::WriteStream *stream) const; uint32 getAudioCompressionType(); -- cgit v1.2.3 From 98e1f1a193a27cad12a888c8375c523420b25cbe Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:09:30 +0000 Subject: SCI: Only use MacResManager if needed; start to OOPify ResourceSource svn-id: r49809 --- engines/sci/resource.cpp | 76 +++++++++++++++++++++++++----------------- engines/sci/resource_audio.cpp | 14 ++------ engines/sci/resource_intern.h | 26 +++++++-------- 3 files changed, 62 insertions(+), 54 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index d25c3286df..0de1a3f2bd 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -26,6 +26,7 @@ // Resource library #include "common/file.h" +#include "common/macresman.h" #include "sci/resource.h" #include "sci/resource_intern.h" @@ -144,7 +145,7 @@ Resource::Resource() { Resource::~Resource() { delete[] data; - if (_source && _source->source_type == kSourcePatch) + if (_source && _source->getSourceType() == kSourcePatch) delete _source; } @@ -166,14 +167,33 @@ uint32 Resource::getAudioCompressionType() { return _source->audioCompressionType; } + +ResourceSource::ResourceSource(ResSourceType type) + : _sourceType(type) { + scanned = false; + resourceFile = 0; + volume_number = 0; + associated_map = NULL; + audioCompressionType = 0; + audioCompressionOffsetMapping = NULL; + + if (_sourceType == kSourceMacResourceFork) + _macResMan = new Common::MacResManager(); + else + _macResMan = NULL; +} + +ResourceSource::~ResourceSource() { + delete _macResMan; +} + //-- resMan helper functions -- // Resource source list management ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(); + ResourceSource *newsrc = new ResourceSource(kSourceExtMap); - newsrc->source_type = kSourceExtMap; newsrc->location_name = file_name; newsrc->volume_number = volume_nr; @@ -182,9 +202,8 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volum } ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(); + ResourceSource *newsrc = new ResourceSource(kSourceExtMap); - newsrc->source_type = kSourceExtMap; newsrc->location_name = mapFile->getName(); newsrc->resourceFile = mapFile; newsrc->volume_number = volume_nr; @@ -194,9 +213,8 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i } ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { - ResourceSource *newsrc = new ResourceSource(); + ResourceSource *newsrc = new ResourceSource(type); - newsrc->source_type = type; newsrc->location_name = filename; newsrc->volume_number = number; newsrc->associated_map = map; @@ -208,9 +226,8 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty } ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::FSNode *resFile, int number) { - ResourceSource *newsrc = new ResourceSource(); + ResourceSource *newsrc = new ResourceSource(type); - newsrc->source_type = type; newsrc->location_name = resFile->getName(); newsrc->resourceFile = resFile; newsrc->volume_number = number; @@ -223,9 +240,8 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty } ResourceSource *ResourceManager::addPatchDir(const char *dirname) { - ResourceSource *newsrc = new ResourceSource(); + ResourceSource *newsrc = new ResourceSource(kSourceDirectory); - newsrc->source_type = kSourceDirectory; newsrc->location_name = dirname; _sources.push_back(newsrc); @@ -235,7 +251,7 @@ ResourceSource *ResourceManager::addPatchDir(const char *dirname) { ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { ResourceSource *src = *it; - if ((src->source_type == kSourceVolume || src->source_type == kSourceAudioVolume) + if ((src->getSourceType() == kSourceVolume || src->getSourceType() == kSourceAudioVolume) && src->associated_map == map && src->volume_number == volume_nr) return src; } @@ -327,11 +343,12 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc static uint32 resTypeToMacTag(ResourceType type); void ResourceManager::loadResource(Resource *res) { - if (res->_source->source_type == kSourcePatch && loadFromPatchFile(res)) + if (res->_source->getSourceType() == kSourcePatch && loadFromPatchFile(res)) return; - if (res->_source->source_type == kSourceMacResourceFork) { - Common::SeekableReadStream *stream = res->_source->macResMan.getResource(resTypeToMacTag(res->_id.type), res->_id.number); + if (res->_source->getSourceType() == kSourceMacResourceFork) { + assert(res->_source->_macResMan); + Common::SeekableReadStream *stream = res->_source->_macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); if (!stream) error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); @@ -353,7 +370,7 @@ void ResourceManager::loadResource(Resource *res) { return; } - switch(res->_source->source_type) { + switch(res->_source->getSourceType()) { case kSourceWave: fileStream->seek(res->_fileOffset, SEEK_SET); loadFromWaveFile(res, fileStream); @@ -605,7 +622,7 @@ void ResourceManager::scanNewSources() { if (!source->scanned) { source->scanned = true; - switch (source->source_type) { + switch (source->getSourceType()) { case kSourceDirectory: readResourcePatches(source); @@ -874,7 +891,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { rsrc = *it; - if (rsrc->source_type == kSourceExtMap) { + if (rsrc->getSourceType() == kSourceExtMap) { if (rsrc->resourceFile) { fileStream = rsrc->resourceFile->createReadStream(); } else { @@ -884,7 +901,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { fileStream = file; } break; - } else if (rsrc->source_type == kSourceMacResourceFork) + } else if (rsrc->getSourceType() == kSourceMacResourceFork) return kResVersionSci11Mac; } @@ -963,7 +980,7 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { rsrc = *it; - if (rsrc->source_type == kSourceVolume) { + if (rsrc->getSourceType() == kSourceVolume) { if (rsrc->resourceFile) { fileStream = rsrc->resourceFile->createReadStream(); } else { @@ -973,7 +990,7 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { fileStream = file; } break; - } else if (rsrc->source_type == kSourceMacResourceFork) + } else if (rsrc->getSourceType() == kSourceMacResourceFork) return kResVersionSci11Mac; } @@ -1213,8 +1230,7 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { delete stream; } - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; + psrcPatch = new ResourceSource(kSourcePatch); psrcPatch->location_name = name; processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); } @@ -1263,8 +1279,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } if (bAdd) { - psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; + psrcPatch = new ResourceSource(kSourcePatch); psrcPatch->location_name = name; processPatch(psrcPatch, (ResourceType)i, resourceNr); } @@ -1449,10 +1464,11 @@ static uint32 resTypeToMacTag(ResourceType type) { } int ResourceManager::readMacResourceFork(ResourceSource *source) { - if (!source->macResMan.open(source->location_name.c_str())) + assert(source->_macResMan); + if (!source->_macResMan->open(source->location_name.c_str())) error("%s is not a valid Mac resource fork", source->location_name.c_str()); - Common::MacResTagArray tagArray = source->macResMan.getResTagArray(); + Common::MacResTagArray tagArray = source->_macResMan->getResTagArray(); for (uint32 i = 0; i < tagArray.size(); i++) { ResourceType type = kResourceTypeInvalid; @@ -1467,11 +1483,11 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { if (type == kResourceTypeInvalid) continue; - Common::MacResIDArray idArray = source->macResMan.getResIDArray(tagArray[i]); + Common::MacResIDArray idArray = source->_macResMan->getResIDArray(tagArray[i]); for (uint32 j = 0; j < idArray.size(); j++) { // Get the size of the file - Common::SeekableReadStream *stream = source->macResMan.getResource(tagArray[i], idArray[j]); + Common::SeekableReadStream *stream = source->_macResMan->getResource(tagArray[i], idArray[j]); // Some IBIS resources have a size of 0, so we skip them if (!stream) @@ -1671,7 +1687,7 @@ ResourceCompression ResourceManager::getViewCompression() { if (!res) continue; - if (res->_source->source_type != kSourceVolume) + if (res->_source->getSourceType() != kSourceVolume) continue; fileStream = getVolumeFile(res->_source); diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index d2f1d53e11..85758e9ef0 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -155,23 +155,15 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { gmPatchFile = "TALEGM.PAT"; if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource; - psrcPatch->source_type = kSourcePatch; - psrcPatch->resourceFile = 0; + ResourceSource *psrcPatch = new ResourceSource(kSourcePatch); psrcPatch->location_name = gmPatchFile; - psrcPatch->audioCompressionType = 0; - psrcPatch->audioCompressionOffsetMapping = NULL; processPatch(psrcPatch, kResourceTypePatch, 4); } } void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { - ResourceSource *resSrc = new ResourceSource; - resSrc->source_type = kSourceWave; - resSrc->resourceFile = 0; + ResourceSource *resSrc = new ResourceSource(kSourceWave); resSrc->location_name = name; - resSrc->volume_number = 0; - resSrc->audioCompressionType = 0; Resource *newRes = 0; @@ -211,7 +203,7 @@ void ResourceManager::removeAudioResource(ResourceId resId) { if (_resMap.contains(resId)) { Resource *res = _resMap.getVal(resId); - if (res->_source->source_type == kSourceAudioVolume) { + if (res->_source->getSourceType() == kSourceAudioVolume) { if (res->_status == kResStatusLocked) { warning("Failed to remove resource %s (still in use)", resId.toString().c_str()); } else { diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 01f1f45180..89fde718d7 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -26,14 +26,16 @@ #ifndef SCI_RESOURCE_INTERN_H #define SCI_RESOURCE_INTERN_H -#include "common/macresman.h" - #include "sci/resource.h" +namespace Common { + class MacResManager; +} + namespace Sci { struct ResourceSource { - ResSourceType source_type; + const ResSourceType _sourceType; bool scanned; Common::String location_name; // FIXME: Replace by FSNode ? const Common::FSNode *resourceFile; @@ -41,16 +43,14 @@ struct ResourceSource { ResourceSource *associated_map; uint32 audioCompressionType; int32 *audioCompressionOffsetMapping; - Common::MacResManager macResMan; - ResourceSource() { - source_type = kSourceDirectory; - scanned = false; - resourceFile = 0; - volume_number = 0; - associated_map = NULL; - audioCompressionType = 0; - audioCompressionOffsetMapping = NULL; - } + Common::MacResManager *_macResMan; + +public: + + ResourceSource(ResSourceType type); + ~ResourceSource(); + + ResSourceType getSourceType() const { return _sourceType; } }; -- cgit v1.2.3 From dea38106f84873a62c4a342c564dbfe9f38ff480 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:09:51 +0000 Subject: SCI: Change ResourceSource to a class, further OOPify it. In particular, renamed location_name to _name and made it const and protected. Thus it cannot be changed after creation, and only read access is now possible, via a getter method. svn-id: r49810 --- engines/sci/resource.cpp | 62 ++++++++++++++++++------------------------ engines/sci/resource.h | 2 +- engines/sci/resource_audio.cpp | 12 ++++---- engines/sci/resource_intern.h | 11 +++++--- 4 files changed, 40 insertions(+), 47 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 0de1a3f2bd..0d7e435aa0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -168,8 +168,8 @@ uint32 Resource::getAudioCompressionType() { } -ResourceSource::ResourceSource(ResSourceType type) - : _sourceType(type) { +ResourceSource::ResourceSource(ResSourceType type, const Common::String &name) + : _sourceType(type), _name(name) { scanned = false; resourceFile = 0; volume_number = 0; @@ -192,9 +192,8 @@ ResourceSource::~ResourceSource() { // Resource source list management ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(kSourceExtMap); + ResourceSource *newsrc = new ResourceSource(kSourceExtMap, file_name); - newsrc->location_name = file_name; newsrc->volume_number = volume_nr; _sources.push_back(newsrc); @@ -202,9 +201,8 @@ ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volum } ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(kSourceExtMap); + ResourceSource *newsrc = new ResourceSource(kSourceExtMap, mapFile->getName()); - newsrc->location_name = mapFile->getName(); newsrc->resourceFile = mapFile; newsrc->volume_number = volume_nr; @@ -213,9 +211,8 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i } ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { - ResourceSource *newsrc = new ResourceSource(type); + ResourceSource *newsrc = new ResourceSource(type, filename); - newsrc->location_name = filename; newsrc->volume_number = number; newsrc->associated_map = map; if (type == kSourceAudioVolume) @@ -226,9 +223,8 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty } ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::FSNode *resFile, int number) { - ResourceSource *newsrc = new ResourceSource(type); + ResourceSource *newsrc = new ResourceSource(type, resFile->getName()); - newsrc->location_name = resFile->getName(); newsrc->resourceFile = resFile; newsrc->volume_number = number; newsrc->associated_map = map; @@ -240,9 +236,7 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty } ResourceSource *ResourceManager::addPatchDir(const char *dirname) { - ResourceSource *newsrc = new ResourceSource(kSourceDirectory); - - newsrc->location_name = dirname; + ResourceSource *newsrc = new ResourceSource(kSourceDirectory, dirname); _sources.push_back(newsrc); return 0; @@ -291,9 +285,9 @@ bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) bool ResourceManager::loadFromPatchFile(Resource *res) { Common::File file; - const char *filename = res->_source->location_name.c_str(); + const Common::String &filename = res->_source->getLocationName(); if (file.open(filename) == false) { - warning("Failed to open patch file %s", filename); + warning("Failed to open patch file %s", filename.c_str()); res->unalloc(); return false; } @@ -309,7 +303,7 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc if (source->resourceFile) return source->resourceFile->createReadStream(); - const char *filename = source->location_name.c_str(); + const char *filename = source->getLocationName().c_str(); // check if file is already opened while (it != _volumeFiles.end()) { @@ -365,7 +359,7 @@ void ResourceManager::loadResource(Resource *res) { Common::SeekableReadStream *fileStream = getVolumeFile(res->_source); if (!fileStream) { - warning("Failed to open %s", res->_source->location_name.c_str()); + warning("Failed to open %s", res->_source->getLocationName().c_str()); res->unalloc(); return; } @@ -896,7 +890,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { fileStream = rsrc->resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - file->open(rsrc->location_name); + file->open(rsrc->getLocationName()); if (file->isOpen()) fileStream = file; } @@ -985,7 +979,7 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { fileStream = rsrc->resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - file->open(rsrc->location_name); + file->open(rsrc->getLocationName()); if (file->isOpen()) fileStream = file; } @@ -1089,8 +1083,8 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource fileStream = source->resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); - if (!file->open(source->location_name)) { - warning("ResourceManager::processPatch(): failed to open %s", source->location_name.c_str()); + if (!file->open(source->getLocationName())) { + warning("ResourceManager::processPatch(): failed to open %s", source->getLocationName().c_str()); return; } fileStream = file; @@ -1098,7 +1092,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource int fsize = fileStream->size(); if (fsize < 3) { - debug("Patching %s failed - file too small", source->location_name.c_str()); + debug("Patching %s failed - file too small", source->getLocationName().c_str()); return; } @@ -1108,7 +1102,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource delete fileStream; if (patchType != checkForType) { - debug("Patching %s failed - resource type mismatch", source->location_name.c_str()); + debug("Patching %s failed - resource type mismatch", source->getLocationName().c_str()); return; } @@ -1132,7 +1126,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource if (patchDataOffset + 2 >= fsize) { debug("Patching %s failed - patch starting at offset %d can't be in file of size %d", - source->location_name.c_str(), patchDataOffset + 2, fsize); + source->getLocationName().c_str(), patchDataOffset + 2, fsize); return; } @@ -1150,7 +1144,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource newrsc->size = fsize - patchDataOffset - 2; newrsc->_headerSize = patchDataOffset; newrsc->_fileOffset = 0; - debugC(1, kDebugLevelResMan, "Patching %s - OK", source->location_name.c_str()); + debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str()); } void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { @@ -1230,8 +1224,7 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { delete stream; } - psrcPatch = new ResourceSource(kSourcePatch); - psrcPatch->location_name = name; + psrcPatch = new ResourceSource(kSourcePatch, name); processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); } } @@ -1279,8 +1272,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } if (bAdd) { - psrcPatch = new ResourceSource(kSourcePatch); - psrcPatch->location_name = name; + psrcPatch = new ResourceSource(kSourcePatch, name); processPatch(psrcPatch, (ResourceType)i, resourceNr); } } @@ -1300,7 +1292,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { return SCI_ERROR_RESMAP_NOT_FOUND; } else { Common::File *file = new Common::File(); - if (!file->open(map->location_name)) + if (!file->open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; fileStream = file; } @@ -1316,7 +1308,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { if (fileStream->eos() || fileStream->err()) { delete fileStream; - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } if (offset == 0xFFFFFFFF) @@ -1360,7 +1352,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { return SCI_ERROR_RESMAP_NOT_FOUND; } else { Common::File *file = new Common::File(); - if (!file->open(map->location_name)) + if (!file->open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; fileStream = file; } @@ -1407,7 +1399,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { } if (fileStream->eos() || fileStream->err()) { delete fileStream; - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } resId = ResourceId((ResourceType)type, number); @@ -1465,8 +1457,8 @@ static uint32 resTypeToMacTag(ResourceType type) { int ResourceManager::readMacResourceFork(ResourceSource *source) { assert(source->_macResMan); - if (!source->_macResMan->open(source->location_name.c_str())) - error("%s is not a valid Mac resource fork", source->location_name.c_str()); + if (!source->_macResMan->open(source->getLocationName().c_str())) + error("%s is not a valid Mac resource fork", source->getLocationName().c_str()); Common::MacResTagArray tagArray = source->_macResMan->getResTagArray(); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 822d1d31f4..7677209d2d 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -118,7 +118,7 @@ const char *getResourceTypeName(ResourceType restype); class ResourceManager; -struct ResourceSource; +class ResourceSource; class ResourceId { public: diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 85758e9ef0..f7f5077455 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -37,7 +37,7 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { Common::SeekableReadStream *fileStream = getVolumeFile(source); if (!fileStream) { - warning("Failed to open %s", source->location_name.c_str()); + warning("Failed to open %s", source->getLocationName().c_str()); return; } @@ -155,15 +155,13 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { gmPatchFile = "TALEGM.PAT"; if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource(kSourcePatch); - psrcPatch->location_name = gmPatchFile; + ResourceSource *psrcPatch = new ResourceSource(kSourcePatch, gmPatchFile); processPatch(psrcPatch, kResourceTypePatch, 4); } } void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { - ResourceSource *resSrc = new ResourceSource(kSourceWave); - resSrc->location_name = name; + ResourceSource *resSrc = new ResourceSource(kSourceWave, name); Resource *newRes = 0; @@ -352,7 +350,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { Common::File file; - if (!file.open(map->location_name)) + if (!file.open(map->getLocationName())) return SCI_ERROR_RESMAP_NOT_FOUND; bool oldFormat = (file.readUint16LE() >> 11) == kResourceTypeAudio; @@ -364,7 +362,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { uint32 size = file.readUint32LE(); if (file.eos() || file.err()) { - warning("Error while reading %s", map->location_name.c_str()); + warning("Error while reading %s", map->getLocationName().c_str()); return SCI_ERROR_RESMAP_NOT_FOUND; } diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 89fde718d7..60cf1b99a4 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -34,10 +34,13 @@ namespace Common { namespace Sci { -struct ResourceSource { +class ResourceSource { +protected: const ResSourceType _sourceType; + const Common::String _name; + +public: bool scanned; - Common::String location_name; // FIXME: Replace by FSNode ? const Common::FSNode *resourceFile; int volume_number; ResourceSource *associated_map; @@ -46,11 +49,11 @@ struct ResourceSource { Common::MacResManager *_macResMan; public: - - ResourceSource(ResSourceType type); + ResourceSource(ResSourceType type, const Common::String &name); ~ResourceSource(); ResSourceType getSourceType() const { return _sourceType; } + const Common::String &getLocationName() const { return _name; } }; -- cgit v1.2.3 From 793c04f43b3d75b4b6d1ff2a2a93f2a496c0065f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:10:18 +0000 Subject: SCI: Changed some 'const char *' to Common::String svn-id: r49811 --- engines/sci/resource.cpp | 14 +++++++------- engines/sci/resource.h | 8 ++++---- engines/sci/resource_audio.cpp | 4 ++-- engines/sci/resource_intern.h | 1 - 4 files changed, 13 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 0d7e435aa0..f60c6a3c96 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -191,8 +191,8 @@ ResourceSource::~ResourceSource() { // Resource source list management -ResourceSource *ResourceManager::addExternalMap(const char *file_name, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(kSourceExtMap, file_name); +ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, int volume_nr) { + ResourceSource *newsrc = new ResourceSource(kSourceExtMap, filename); newsrc->volume_number = volume_nr; @@ -210,7 +210,7 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const char *filename, int number) { +ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::String &filename, int number) { ResourceSource *newsrc = new ResourceSource(type, filename); newsrc->volume_number = number; @@ -235,7 +235,7 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty return newsrc; } -ResourceSource *ResourceManager::addPatchDir(const char *dirname) { +ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) { ResourceSource *newsrc = new ResourceSource(kSourceDirectory, dirname); _sources.push_back(newsrc); @@ -459,7 +459,7 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, kSourceVolume, name.c_str(), number); + addSource(map, kSourceVolume, name, number); } #ifdef ENABLE_SCI32 // GK1CD hires content @@ -472,7 +472,7 @@ int ResourceManager::addAppropriateSources() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); - addSource(0, kSourceMacResourceFork, filename.c_str(), atoi(filename.c_str() + 4)); + addSource(0, kSourceMacResourceFork, filename, atoi(filename.c_str() + 4)); } #ifdef ENABLE_SCI32 // Mac SCI32 games have extra folders for patches @@ -504,7 +504,7 @@ int ResourceManager::addAppropriateSources() { int resNumber = atoi(strrchr(resName.c_str(), '.') + 1); if (mapNumber == resNumber) { - addSource(addExternalMap(mapName.c_str(), mapNumber), kSourceVolume, resName.c_str(), mapNumber); + addSource(addExternalMap(mapName, mapNumber), kSourceVolume, resName, mapNumber); break; } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 7677209d2d..9b498b59de 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -322,7 +322,7 @@ protected: * Add a path to the resource manager's list of sources. * @return a pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addPatchDir(const char *path); + ResourceSource *addPatchDir(const Common::String &path); ResourceSource *getVolume(ResourceSource *map, int volume_nr); @@ -333,7 +333,7 @@ protected: * @param filename The name of the source to add * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addSource(ResourceSource *map, ResSourceType type, const char *filename, + ResourceSource *addSource(ResourceSource *map, ResSourceType type, const Common::String &filename, int number); ResourceSource *addSource(ResourceSource *map, ResSourceType type, @@ -345,7 +345,7 @@ protected: * @param volume_nr The volume number the map starts at, 0 for volume_number = volume_nr; @@ -201,7 +201,7 @@ ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, } ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ResourceSource(kSourceExtMap, mapFile->getName()); + ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName()); newsrc->resourceFile = mapFile; newsrc->volume_number = volume_nr; @@ -236,7 +236,7 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType ty } ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) { - ResourceSource *newsrc = new ResourceSource(kSourceDirectory, dirname); + ResourceSource *newsrc = new DirectoryResourceSource(dirname); _sources.push_back(newsrc); return 0; @@ -1224,7 +1224,7 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { delete stream; } - psrcPatch = new ResourceSource(kSourcePatch, name); + psrcPatch = new PatchResourceSource(name); processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); } } @@ -1272,7 +1272,7 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { } if (bAdd) { - psrcPatch = new ResourceSource(kSourcePatch, name); + psrcPatch = new PatchResourceSource(name); processPatch(psrcPatch, (ResourceType)i, resourceNr); } } diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 9721a884dc..1b001ad975 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -155,13 +155,13 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { gmPatchFile = "TALEGM.PAT"; if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { - ResourceSource *psrcPatch = new ResourceSource(kSourcePatch, gmPatchFile); + ResourceSource *psrcPatch = new PatchResourceSource(gmPatchFile); processPatch(psrcPatch, kResourceTypePatch, 4); } } void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { - ResourceSource *resSrc = new ResourceSource(kSourceWave, name); + ResourceSource *resSrc = new WaveResourceSource(name); Resource *newRes = 0; diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index ceae474b39..1a8e6ec747 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -50,12 +50,57 @@ public: public: ResourceSource(ResSourceType type, const Common::String &name); - ~ResourceSource(); + virtual ~ResourceSource(); ResSourceType getSourceType() const { return _sourceType; } const Common::String &getLocationName() const { return _name; } }; +class DirectoryResourceSource : public ResourceSource { +public: + DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {} +}; + +class PatchResourceSource : public ResourceSource { +public: + PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {} +}; + +class VolumeResourceSource : public ResourceSource { +public: + VolumeResourceSource(const Common::String &name) : ResourceSource(kSourceVolume, name) {} +}; + +class ExtMapResourceSource : public ResourceSource { +public: + ExtMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtMap, name) {} +}; + +class IntMapResourceSource : public ResourceSource { +public: + IntMapResourceSource(const Common::String &name) : ResourceSource(kSourceIntMap, name) {} +}; + +class AudioVolumeResourceSource : public ResourceSource { +public: + AudioVolumeResourceSource(const Common::String &name) : ResourceSource(kSourceAudioVolume, name) {} +}; + +class ExtAudioMapResourceSource : public ResourceSource { +public: + ExtAudioMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtAudioMap, name) {} +}; + +class WaveResourceSource : public ResourceSource { +public: + WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} +}; + +class MacResourceForkResourceSource : public ResourceSource { +public: + MacResourceForkResourceSource(const Common::String &name) : ResourceSource(kSourceMacResourceFork, name) {} +}; + } // End of namespace Sci #endif // SCI_RESOURCE_INTERN_H -- cgit v1.2.3 From 17a51121623a971b249cd33a8b581fe44b3e5616 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:11:04 +0000 Subject: SCI: Convert code to use ResourceSource subclasses svn-id: r49813 --- engines/sci/resource.cpp | 36 ++++++++++++++++++------------------ engines/sci/resource.h | 19 +++---------------- engines/sci/resource_audio.cpp | 4 ++-- engines/sci/resource_intern.h | 16 +++++++++++++++- 4 files changed, 38 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 9691fa3f9c..83dd64339d 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -210,25 +210,25 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::String &filename, int number) { - ResourceSource *newsrc = new ResourceSource(type, filename); +ResourceSource *ResourceManager::addSource(ResourceSource *map, ResourceSource *newsrc, int number) { + assert(newsrc); newsrc->volume_number = number; newsrc->associated_map = map; - if (type == kSourceAudioVolume) + if (newsrc->getSourceType() == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); _sources.push_back(newsrc); return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResSourceType type, const Common::FSNode *resFile, int number) { - ResourceSource *newsrc = new ResourceSource(type, resFile->getName()); +ResourceSource *ResourceManager::addSource(ResourceSource *map, ResourceSource *newsrc, const Common::FSNode *resFile, int number) { + assert(newsrc); newsrc->resourceFile = resFile; newsrc->volume_number = number; newsrc->associated_map = map; - if (type == kSourceAudioVolume) + if (newsrc->getSourceType() == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); _sources.push_back(newsrc); @@ -459,12 +459,12 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, kSourceVolume, name, number); + addSource(map, new VolumeResourceSource(name), number); } #ifdef ENABLE_SCI32 // GK1CD hires content if (Common::File::exists("alt.map") && Common::File::exists("resource.alt")) - addSource(addExternalMap("alt.map", 10), kSourceVolume, "resource.alt", 10); + addSource(addExternalMap("alt.map", 10), new VolumeResourceSource("resource.alt"), 10); #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme @@ -472,7 +472,7 @@ int ResourceManager::addAppropriateSources() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); - addSource(0, kSourceMacResourceFork, filename, atoi(filename.c_str() + 4)); + addSource(0, new MacResourceForkResourceSource(filename), atoi(filename.c_str() + 4)); } #ifdef ENABLE_SCI32 // Mac SCI32 games have extra folders for patches @@ -484,7 +484,7 @@ int ResourceManager::addAppropriateSources() { // There can also be a "Patches" resource fork with patches if (Common::File::exists("Patches")) - addSource(0, kSourceMacResourceFork, "Patches", 100); + addSource(0, new MacResourceForkResourceSource("Patches"), 100); } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; @@ -504,7 +504,7 @@ int ResourceManager::addAppropriateSources() { int resNumber = atoi(strrchr(resName.c_str(), '.') + 1); if (mapNumber == resNumber) { - addSource(addExternalMap(mapName, mapNumber), kSourceVolume, resName, mapNumber); + addSource(addExternalMap(mapName, mapNumber), new VolumeResourceSource(resName), mapNumber); break; } } @@ -513,7 +513,7 @@ int ResourceManager::addAppropriateSources() { // SCI2.1 resource patches if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) { // We add this resource with a map which surely won't exist - addSource(addExternalMap("resmap.pat", 100), kSourceVolume, "ressci.pat", 100); + addSource(addExternalMap("resmap.pat", 100), new VolumeResourceSource("ressci.pat"), 100); } } #else @@ -523,7 +523,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("."); if (Common::File::exists("message.map")) - addSource(addExternalMap("message.map"), kSourceVolume, "resource.msg", 0); + addSource(addExternalMap("message.map"), new VolumeResourceSource("resource.msg"), 0); return 1; } @@ -567,7 +567,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { #ifdef ENABLE_SCI32 if (sci21PatchMap && sci21PatchRes) - addSource(sci21PatchMap, kSourceVolume, sci21PatchRes, 100); + addSource(sci21PatchMap, new VolumeResourceSource(sci21PatchRes->getName()), sci21PatchRes, 100); #endif // Now find all the resource.0?? files @@ -582,7 +582,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { const char *dot = strrchr(filename.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, kSourceVolume, file, number); + addSource(map, new VolumeResourceSource(file->getName()), file, number); } } @@ -597,12 +597,12 @@ int ResourceManager::addInternalSources() { Common::List::iterator itr = resources->begin(); while (itr != resources->end()) { - ResourceSource *src = addSource(NULL, kSourceIntMap, "MAP", itr->number); + ResourceSource *src = addSource(NULL, new IntMapResourceSource("MAP"), itr->number); if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) - addSource(src, kSourceAudioVolume, "RESOURCE.SFX", 0); + addSource(src, new AudioVolumeResourceSource("RESOURCE.SFX"), 0); else if (Common::File::exists("RESOURCE.AUD")) - addSource(src, kSourceAudioVolume, "RESOURCE.AUD", 0); + addSource(src, new AudioVolumeResourceSource("RESOURCE.AUD"), 0); ++itr; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 9b498b59de..cb43c9e13a 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -69,18 +69,6 @@ enum { MAX_OPENED_VOLUMES = 5 ///< Max number of simultaneously opened volumes }; -enum ResSourceType { - kSourceDirectory = 0, - kSourcePatch, - kSourceVolume, - kSourceExtMap, - kSourceIntMap, - kSourceAudioVolume, - kSourceExtAudioMap, - kSourceWave, - kSourceMacResourceFork -}; - enum ResourceType { kResourceTypeView = 0, kResourceTypePic, @@ -329,14 +317,13 @@ protected: /** * Adds a source to the resource manager's list of sources. * @param map The map associated with this source - * @param type The source type - * @param filename The name of the source to add + * @param source The new source to add * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addSource(ResourceSource *map, ResSourceType type, const Common::String &filename, + ResourceSource *addSource(ResourceSource *map, ResourceSource *source, int number); - ResourceSource *addSource(ResourceSource *map, ResSourceType type, + ResourceSource *addSource(ResourceSource *map, ResourceSource *source, const Common::FSNode *resFile, int number); /** diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 1b001ad975..416e4ea361 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -433,7 +433,7 @@ void ResourceManager::setAudioLanguage(int language) { return; } - _audioMapSCI1 = addSource(NULL, kSourceExtAudioMap, fullname, language); + _audioMapSCI1 = addSource(NULL, new ExtAudioMapResourceSource(fullname), language); // Search for audio volumes for this language and add them to the source list Common::ArchiveMemberList files; @@ -443,7 +443,7 @@ void ResourceManager::setAudioLanguage(int language) { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(_audioMapSCI1, kSourceAudioVolume, name, number); + addSource(_audioMapSCI1, new AudioVolumeResourceSource(name), number); } scanNewSources(); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 1a8e6ec747..c3642cda1b 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -34,6 +34,19 @@ namespace Common { namespace Sci { +enum ResSourceType { + kSourceDirectory = 0, + kSourcePatch, + kSourceVolume, + kSourceExtMap, + kSourceIntMap, + kSourceAudioVolume, + kSourceExtAudioMap, + kSourceWave, + kSourceMacResourceFork +}; + + class ResourceSource { protected: const ResSourceType _sourceType; @@ -48,8 +61,9 @@ public: int32 *audioCompressionOffsetMapping; Common::MacResManager *_macResMan; -public: +protected: ResourceSource(ResSourceType type, const Common::String &name); +public: virtual ~ResourceSource(); ResSourceType getSourceType() const { return _sourceType; } -- cgit v1.2.3 From 8c06425ee3cac66469c817ab96cd0ab3688cdae6 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:11:30 +0000 Subject: SCI: Remove 'map' param from addSource, and let AudioVolumeResourceSource subclass VolumeResourceSource svn-id: r49814 --- engines/sci/resource.cpp | 30 ++++++++++++++---------------- engines/sci/resource.h | 7 ++----- engines/sci/resource_audio.cpp | 4 ++-- engines/sci/resource_intern.h | 13 +++++++++---- 4 files changed, 27 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 83dd64339d..08ca46f881 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -210,11 +210,10 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResourceSource *newsrc, int number) { +ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, int number) { assert(newsrc); newsrc->volume_number = number; - newsrc->associated_map = map; if (newsrc->getSourceType() == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); @@ -222,12 +221,11 @@ ResourceSource *ResourceManager::addSource(ResourceSource *map, ResourceSource * return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *map, ResourceSource *newsrc, const Common::FSNode *resFile, int number) { +ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common::FSNode *resFile, int number) { assert(newsrc); newsrc->resourceFile = resFile; newsrc->volume_number = number; - newsrc->associated_map = map; if (newsrc->getSourceType() == kSourceAudioVolume) checkIfAudioVolumeIsCompressed(newsrc); @@ -459,12 +457,12 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, new VolumeResourceSource(name), number); + addSource(new VolumeResourceSource(name, map), number); } #ifdef ENABLE_SCI32 // GK1CD hires content if (Common::File::exists("alt.map") && Common::File::exists("resource.alt")) - addSource(addExternalMap("alt.map", 10), new VolumeResourceSource("resource.alt"), 10); + addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10)), 10); #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme @@ -472,7 +470,7 @@ int ResourceManager::addAppropriateSources() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); - addSource(0, new MacResourceForkResourceSource(filename), atoi(filename.c_str() + 4)); + addSource(new MacResourceForkResourceSource(filename), atoi(filename.c_str() + 4)); } #ifdef ENABLE_SCI32 // Mac SCI32 games have extra folders for patches @@ -484,7 +482,7 @@ int ResourceManager::addAppropriateSources() { // There can also be a "Patches" resource fork with patches if (Common::File::exists("Patches")) - addSource(0, new MacResourceForkResourceSource("Patches"), 100); + addSource(new MacResourceForkResourceSource("Patches"), 100); } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; @@ -504,7 +502,7 @@ int ResourceManager::addAppropriateSources() { int resNumber = atoi(strrchr(resName.c_str(), '.') + 1); if (mapNumber == resNumber) { - addSource(addExternalMap(mapName, mapNumber), new VolumeResourceSource(resName), mapNumber); + addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber)), mapNumber); break; } } @@ -513,7 +511,7 @@ int ResourceManager::addAppropriateSources() { // SCI2.1 resource patches if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) { // We add this resource with a map which surely won't exist - addSource(addExternalMap("resmap.pat", 100), new VolumeResourceSource("ressci.pat"), 100); + addSource(new VolumeResourceSource("ressci.pat", addExternalMap("resmap.pat", 100)), 100); } } #else @@ -523,7 +521,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("."); if (Common::File::exists("message.map")) - addSource(addExternalMap("message.map"), new VolumeResourceSource("resource.msg"), 0); + addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map")), 0); return 1; } @@ -567,7 +565,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { #ifdef ENABLE_SCI32 if (sci21PatchMap && sci21PatchRes) - addSource(sci21PatchMap, new VolumeResourceSource(sci21PatchRes->getName()), sci21PatchRes, 100); + addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap), sci21PatchRes, 100); #endif // Now find all the resource.0?? files @@ -582,7 +580,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { const char *dot = strrchr(filename.c_str(), '.'); int number = atoi(dot + 1); - addSource(map, new VolumeResourceSource(file->getName()), file, number); + addSource(new VolumeResourceSource(file->getName(), map), file, number); } } @@ -597,12 +595,12 @@ int ResourceManager::addInternalSources() { Common::List::iterator itr = resources->begin(); while (itr != resources->end()) { - ResourceSource *src = addSource(NULL, new IntMapResourceSource("MAP"), itr->number); + ResourceSource *src = addSource(new IntMapResourceSource("MAP"), itr->number); if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) - addSource(src, new AudioVolumeResourceSource("RESOURCE.SFX"), 0); + addSource(new AudioVolumeResourceSource("RESOURCE.SFX", src), 0); else if (Common::File::exists("RESOURCE.AUD")) - addSource(src, new AudioVolumeResourceSource("RESOURCE.AUD"), 0); + addSource(new AudioVolumeResourceSource("RESOURCE.AUD", src), 0); ++itr; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index cb43c9e13a..67cc4d3c1f 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -316,15 +316,12 @@ protected: /** * Adds a source to the resource manager's list of sources. - * @param map The map associated with this source * @param source The new source to add * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addSource(ResourceSource *map, ResourceSource *source, - int number); + ResourceSource *addSource(ResourceSource *source, int number); - ResourceSource *addSource(ResourceSource *map, ResourceSource *source, - const Common::FSNode *resFile, int number); + ResourceSource *addSource(ResourceSource *source, const Common::FSNode *resFile, int number); /** * Add an external (i.e., separate file) map resource to the resource manager's list of sources. diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 416e4ea361..36084087fd 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -433,7 +433,7 @@ void ResourceManager::setAudioLanguage(int language) { return; } - _audioMapSCI1 = addSource(NULL, new ExtAudioMapResourceSource(fullname), language); + _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname), language); // Search for audio volumes for this language and add them to the source list Common::ArchiveMemberList files; @@ -443,7 +443,7 @@ void ResourceManager::setAudioLanguage(int language) { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(_audioMapSCI1, new AudioVolumeResourceSource(name), number); + addSource(new AudioVolumeResourceSource(name, _audioMapSCI1), number); } scanNewSources(); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index c3642cda1b..e0d7cdcf87 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -56,7 +56,7 @@ public: bool scanned; const Common::FSNode *resourceFile; int volume_number; - ResourceSource *associated_map; + ResourceSource *associated_map; // TODO: Move to VolumeResourceSource uint32 audioCompressionType; int32 *audioCompressionOffsetMapping; Common::MacResManager *_macResMan; @@ -82,7 +82,10 @@ public: class VolumeResourceSource : public ResourceSource { public: - VolumeResourceSource(const Common::String &name) : ResourceSource(kSourceVolume, name) {} + VolumeResourceSource(const Common::String &name, ResourceSource *map, ResSourceType type = kSourceVolume) + : ResourceSource(type, name) { + associated_map = map; + } }; class ExtMapResourceSource : public ResourceSource { @@ -95,9 +98,11 @@ public: IntMapResourceSource(const Common::String &name) : ResourceSource(kSourceIntMap, name) {} }; -class AudioVolumeResourceSource : public ResourceSource { +class AudioVolumeResourceSource : public VolumeResourceSource { public: - AudioVolumeResourceSource(const Common::String &name) : ResourceSource(kSourceAudioVolume, name) {} + AudioVolumeResourceSource(const Common::String &name, ResourceSource *map) + : VolumeResourceSource(name, map, kSourceAudioVolume) { + } }; class ExtAudioMapResourceSource : public ResourceSource { -- cgit v1.2.3 From 89cf6f7cb1b8336931b46e714b403f9bfe9af128 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:11:56 +0000 Subject: SCI: Change ResourceManager::getVolume() to use new classes * Add new ResourceSource::findVolume() virtual method * Rename ResourceManager::getVolume() to findVolume(), and change it to use the new ResourceSource method * Add some TODO comments pointing to further OOPification possibilities svn-id: r49815 --- engines/sci/resource.cpp | 29 +++++++++++++++++++---------- engines/sci/resource.h | 2 +- engines/sci/resource_audio.cpp | 4 ++-- engines/sci/resource_intern.h | 16 +++++++++++++--- 4 files changed, 35 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 08ca46f881..44b4525cd2 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -214,8 +214,13 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, int number) { assert(newsrc); newsrc->volume_number = number; - if (newsrc->getSourceType() == kSourceAudioVolume) + if (newsrc->getSourceType() == kSourceAudioVolume) { + // TODO: Move this call into the AudioVolumeResourceSource constructor. + // Need to verify if this is safe, though; in particular, whether this + // method may be called before the new AudioVolumeResourceSource has been + // added to the _sources lists. checkIfAudioVolumeIsCompressed(newsrc); + } _sources.push_back(newsrc); return newsrc; @@ -226,8 +231,13 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common: newsrc->resourceFile = resFile; newsrc->volume_number = number; - if (newsrc->getSourceType() == kSourceAudioVolume) + if (newsrc->getSourceType() == kSourceAudioVolume) { + // TODO: Move this call into the AudioVolumeResourceSource constructor. + // Need to verify if this is safe, though; in particular, whether this + // method may be called before the new AudioVolumeResourceSource has been + // added to the _sources lists. checkIfAudioVolumeIsCompressed(newsrc); + } _sources.push_back(newsrc); return newsrc; @@ -240,11 +250,10 @@ ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) { return 0; } -ResourceSource *ResourceManager::getVolume(ResourceSource *map, int volume_nr) { +ResourceSource *ResourceManager::findVolume(ResourceSource *map, int volume_nr) { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { - ResourceSource *src = *it; - if ((src->getSourceType() == kSourceVolume || src->getSourceType() == kSourceAudioVolume) - && src->associated_map == map && src->volume_number == volume_nr) + ResourceSource *src = (*it)->findVolume(map, volume_nr); + if (src) return src; } @@ -908,7 +917,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { // check if 0 or 01 - try to read resources in SCI0 format and see if exists fileStream->seek(0, SEEK_SET); while (fileStream->read(buff, 6) == 6 && !(buff[0] == 0xFF && buff[1] == 0xFF && buff[2] == 0xFF)) { - if (getVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL) + if (findVolume(rsrc, (buff[5] & 0xFC) >> 2) == NULL) return kResVersionSci1Middle; } return kResVersionSci0Sci1Early; @@ -1318,7 +1327,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { // adding a new resource if (_resMap.contains(resId) == false) { res = new Resource; - res->_source = getVolume(map, offset >> bShift); + res->_source = findVolume(map, offset >> bShift); if (!res->_source) { warning("Could not get volume for resource %d, VolumeID %d", id, offset >> bShift); if (_mapVersion != _volVersion) { @@ -1327,7 +1336,7 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { _mapVersion = _volVersion; bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC; bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26; - res->_source = getVolume(map, offset >> bShift); + res->_source = findVolume(map, offset >> bShift); } } res->_fileOffset = offset & (((~bMask) << 24) | 0xFFFFFF); @@ -1411,7 +1420,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers // need to be used in concurrence with the volume specified in the map to get // the actual resource file. - res->_source = getVolume(map, volume_nr + map->volume_number); + res->_source = findVolume(map, volume_nr + map->volume_number); res->_fileOffset = off; } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 67cc4d3c1f..826fbff850 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -312,7 +312,7 @@ protected: */ ResourceSource *addPatchDir(const Common::String &path); - ResourceSource *getVolume(ResourceSource *map, int volume_nr); + ResourceSource *findVolume(ResourceSource *map, int volume_nr); /** * Adds a source to the resource manager's list of sources. diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 36084087fd..7d716f0f20 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -260,7 +260,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { return SCI_ERROR_RESMAP_NOT_FOUND; } - ResourceSource *src = getVolume(map, 0); + ResourceSource *src = findVolume(map, 0); if (!src) return SCI_ERROR_NO_RESOURCE_FILES_FOUND; @@ -380,7 +380,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { offset &= 0x0fffffff; // least significant 28 bits } - ResourceSource *src = getVolume(map, volume_nr); + ResourceSource *src = findVolume(map, volume_nr); if (src) { if (unload) diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index e0d7cdcf87..15fd5c391d 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -57,9 +57,9 @@ public: const Common::FSNode *resourceFile; int volume_number; ResourceSource *associated_map; // TODO: Move to VolumeResourceSource - uint32 audioCompressionType; - int32 *audioCompressionOffsetMapping; - Common::MacResManager *_macResMan; + uint32 audioCompressionType; // TODO: Move to AudioVolumeResourceSource + int32 *audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource + Common::MacResManager *_macResMan; // TODO: Move to MacResourceForkResourceSource protected: ResourceSource(ResSourceType type, const Common::String &name); @@ -68,6 +68,10 @@ public: ResSourceType getSourceType() const { return _sourceType; } const Common::String &getLocationName() const { return _name; } + + virtual ResourceSource *findVolume(ResourceSource *map, int volume_nr) { + return NULL; + }; }; class DirectoryResourceSource : public ResourceSource { @@ -86,6 +90,12 @@ public: : ResourceSource(type, name) { associated_map = map; } + + virtual ResourceSource *findVolume(ResourceSource *map, int volume_nr) { + if (associated_map == map && volume_number == volume_nr) + return this; + return NULL; + }; }; class ExtMapResourceSource : public ResourceSource { -- cgit v1.2.3 From 055ee6ab5b51c0e0fbaa8e6e9e66850ac48504aa Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:12:21 +0000 Subject: SCI: Add virtual method ResourceSource::scanSource svn-id: r49816 --- engines/sci/resource.cpp | 59 +++++++++++++++++++++++-------------------- engines/sci/resource.h | 9 +++++++ engines/sci/resource_intern.h | 16 ++++++++++++ 3 files changed, 56 insertions(+), 28 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 44b4525cd2..74f99ecd03 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -623,38 +623,41 @@ void ResourceManager::scanNewSources() { if (!source->scanned) { source->scanned = true; - switch (source->getSourceType()) { - case kSourceDirectory: - readResourcePatches(source); - - // We can't use getSciVersion() at this point, thus using _volVersion - if (_volVersion >= kResVersionSci11) // SCI1.1+ - readResourcePatchesBase36(source); - - readWaveAudioPatches(); - break; - case kSourceExtMap: - if (_mapVersion < kResVersionSci1Late) - readResourceMapSCI0(source); - else - readResourceMapSCI1(source); - break; - case kSourceExtAudioMap: - readAudioMapSCI1(source); - break; - case kSourceIntMap: - readAudioMapSCI11(source); - break; - case kSourceMacResourceFork: - readMacResourceFork(source); - break; - default: - break; - } + source->scanSource(this); } } } +void DirectoryResourceSource::scanSource(ResourceManager *resMan) { + resMan->readResourcePatches(this); + + // We can't use getSciVersion() at this point, thus using _volVersion + if (resMan->_volVersion >= ResourceManager::kResVersionSci11) // SCI1.1+ + resMan->readResourcePatchesBase36(this); + + resMan->readWaveAudioPatches(); +} + +void ExtMapResourceSource::scanSource(ResourceManager *resMan) { + if (resMan->_mapVersion < ResourceManager::kResVersionSci1Late) + resMan->readResourceMapSCI0(this); + else + resMan->readResourceMapSCI1(this); +} + +void ExtAudioMapResourceSource::scanSource(ResourceManager *resMan) { + resMan->readAudioMapSCI1(this); +} + +void IntMapResourceSource::scanSource(ResourceManager *resMan) { + resMan->readAudioMapSCI11(this); +} + +void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { + resMan->readMacResourceFork(this); +} + + void ResourceManager::freeResourceSources() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) delete *it; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 826fbff850..8720e8eabb 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -194,6 +194,15 @@ protected: typedef Common::HashMap ResourceMap; class ResourceManager { + // FIXME: These 'friend' declarations are meant to be a temporary hack to + // ease transition to the ResourceSource class system. + friend class ResourceSource; + friend class DirectoryResourceSource; + friend class ExtMapResourceSource; + friend class IntMapResourceSource; + friend class ExtAudioMapResourceSource; + friend class MacResourceForkResourceSource; + public: enum ResVersion { kResVersionUnknown, diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 15fd5c391d..fc07572cea 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -72,11 +72,19 @@ public: virtual ResourceSource *findVolume(ResourceSource *map, int volume_nr) { return NULL; }; + + /** + * Scan this source for TODO. + * TODO: The resMan param for now is just a hack. + */ + virtual void scanSource(ResourceManager *resMan) {} }; class DirectoryResourceSource : public ResourceSource { public: DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {} + + virtual void scanSource(ResourceManager *resMan); }; class PatchResourceSource : public ResourceSource { @@ -101,11 +109,15 @@ public: class ExtMapResourceSource : public ResourceSource { public: ExtMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtMap, name) {} + + virtual void scanSource(ResourceManager *resMan); }; class IntMapResourceSource : public ResourceSource { public: IntMapResourceSource(const Common::String &name) : ResourceSource(kSourceIntMap, name) {} + + virtual void scanSource(ResourceManager *resMan); }; class AudioVolumeResourceSource : public VolumeResourceSource { @@ -118,6 +130,8 @@ public: class ExtAudioMapResourceSource : public ResourceSource { public: ExtAudioMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtAudioMap, name) {} + + virtual void scanSource(ResourceManager *resMan); }; class WaveResourceSource : public ResourceSource { @@ -128,6 +142,8 @@ public: class MacResourceForkResourceSource : public ResourceSource { public: MacResourceForkResourceSource(const Common::String &name) : ResourceSource(kSourceMacResourceFork, name) {} + + virtual void scanSource(ResourceManager *resMan); }; } // End of namespace Sci -- cgit v1.2.3 From d15e09fdc27a2a65857ab0d7fa42c923470021ae Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:12:44 +0000 Subject: SCI: Merge MacResourceForkResourceSource::scanSource and ResourceManager::readMacResourceFork svn-id: r49817 --- engines/sci/resource.cpp | 28 +++++++++++----------------- engines/sci/resource.h | 13 +++++-------- engines/sci/resource_intern.h | 3 +++ 3 files changed, 19 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 74f99ecd03..4f6b557ea4 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -653,10 +653,6 @@ void IntMapResourceSource::scanSource(ResourceManager *resMan) { resMan->readAudioMapSCI11(this); } -void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { - resMan->readMacResourceFork(this); -} - void ResourceManager::freeResourceSources() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) @@ -1465,12 +1461,12 @@ static uint32 resTypeToMacTag(ResourceType type) { return 0; } -int ResourceManager::readMacResourceFork(ResourceSource *source) { - assert(source->_macResMan); - if (!source->_macResMan->open(source->getLocationName().c_str())) - error("%s is not a valid Mac resource fork", source->getLocationName().c_str()); +void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { + assert(_macResMan); + if (!_macResMan->open(getLocationName().c_str())) + error("%s is not a valid Mac resource fork", getLocationName().c_str()); - Common::MacResTagArray tagArray = source->_macResMan->getResTagArray(); + Common::MacResTagArray tagArray = _macResMan->getResTagArray(); for (uint32 i = 0; i < tagArray.size(); i++) { ResourceType type = kResourceTypeInvalid; @@ -1485,11 +1481,11 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { if (type == kResourceTypeInvalid) continue; - Common::MacResIDArray idArray = source->_macResMan->getResIDArray(tagArray[i]); + Common::MacResIDArray idArray = _macResMan->getResIDArray(tagArray[i]); for (uint32 j = 0; j < idArray.size(); j++) { // Get the size of the file - Common::SeekableReadStream *stream = source->_macResMan->getResource(tagArray[i], idArray[j]); + Common::SeekableReadStream *stream = _macResMan->getResource(tagArray[i], idArray[j]); // Some IBIS resources have a size of 0, so we skip them if (!stream) @@ -1503,22 +1499,20 @@ int ResourceManager::readMacResourceFork(ResourceSource *source) { Resource *newrsc = NULL; // Prepare destination, if neccessary. Resource forks may contain patches. - if (!_resMap.contains(resId)) { + if (!resMan->_resMap.contains(resId)) { newrsc = new Resource; - _resMap.setVal(resId, newrsc); + resMan->_resMap.setVal(resId, newrsc); } else - newrsc = _resMap.getVal(resId); + newrsc = resMan->_resMap.getVal(resId); // Overwrite everything newrsc->_id = resId; newrsc->_status = kResStatusNoMalloc; - newrsc->_source = source; + newrsc->_source = this; newrsc->size = fileSize; newrsc->_headerSize = 0; } } - - return 0; } void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 8720e8eabb..fa5d757def 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -163,6 +163,11 @@ struct ResourceIdLess : public Common::BinaryFunctiongetName()); - newsrc->resourceFile = mapFile; + newsrc->_resourceFile = mapFile; newsrc->volume_number = volume_nr; _sources.push_back(newsrc); @@ -229,7 +229,7 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, int number) { ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common::FSNode *resFile, int number) { assert(newsrc); - newsrc->resourceFile = resFile; + newsrc->_resourceFile = resFile; newsrc->volume_number = number; if (newsrc->getSourceType() == kSourceAudioVolume) { // TODO: Move this call into the AudioVolumeResourceSource constructor. @@ -307,8 +307,8 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc Common::List::iterator it = _volumeFiles.begin(); Common::File *file; - if (source->resourceFile) - return source->resourceFile->createReadStream(); + if (source->_resourceFile) + return source->_resourceFile->createReadStream(); const char *filename = source->getLocationName().c_str(); @@ -375,7 +375,7 @@ void ResourceManager::loadResource(Resource *res) { case kSourceWave: fileStream->seek(res->_fileOffset, SEEK_SET); loadFromWaveFile(res, fileStream); - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; return; @@ -414,7 +414,7 @@ void ResourceManager::loadResource(Resource *res) { case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 loadFromAudioVolumeSCI1(res, fileStream); - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; return; default: @@ -429,7 +429,7 @@ void ResourceManager::loadResource(Resource *res) { else loadFromAudioVolumeSCI11(res, fileStream); - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; return; @@ -437,7 +437,7 @@ void ResourceManager::loadResource(Resource *res) { fileStream->seek(res->_fileOffset, SEEK_SET); int error = decompress(res, fileStream); - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; if (error) { @@ -892,8 +892,8 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { rsrc = *it; if (rsrc->getSourceType() == kSourceExtMap) { - if (rsrc->resourceFile) { - fileStream = rsrc->resourceFile->createReadStream(); + if (rsrc->_resourceFile) { + fileStream = rsrc->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); file->open(rsrc->getLocationName()); @@ -981,8 +981,8 @@ ResourceManager::ResVersion ResourceManager::detectVolVersion() { rsrc = *it; if (rsrc->getSourceType() == kSourceVolume) { - if (rsrc->resourceFile) { - fileStream = rsrc->resourceFile->createReadStream(); + if (rsrc->_resourceFile) { + fileStream = rsrc->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); file->open(rsrc->getLocationName()); @@ -1085,8 +1085,8 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource else if (checkForType == kResourceTypeSync36) checkForType = kResourceTypeSync; - if (source->resourceFile) { - fileStream = source->resourceFile->createReadStream(); + if (source->_resourceFile) { + fileStream = source->_resourceFile->createReadStream(); } else { Common::File *file = new Common::File(); if (!file->open(source->getLocationName())) { @@ -1292,8 +1292,8 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { uint16 number, id; uint32 offset; - if (map->resourceFile) { - fileStream = map->resourceFile->createReadStream(); + if (map->_resourceFile) { + fileStream = map->_resourceFile->createReadStream(); if (!fileStream) return SCI_ERROR_RESMAP_NOT_FOUND; } else { @@ -1352,8 +1352,8 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { Common::SeekableReadStream *fileStream = 0; Resource *res; - if (map->resourceFile) { - fileStream = map->resourceFile->createReadStream(); + if (map->_resourceFile) { + fileStream = map->_resourceFile->createReadStream(); if (!fileStream) return SCI_ERROR_RESMAP_NOT_FOUND; } else { @@ -1696,12 +1696,12 @@ ResourceCompression ResourceManager::getViewCompression() { ResourceCompression compression; if (readResourceInfo(res, fileStream, szPacked, compression)) { - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; continue; } - if (res->_source->resourceFile) + if (res->_source->_resourceFile) delete fileStream; if (compression != kCompNone) diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 7d716f0f20..d94c7d010a 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -64,7 +64,7 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { *offsetMapping++ = fileStream->size(); } - if (source->resourceFile) + if (source->_resourceFile) delete fileStream; } diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 617977c3dc..c492602187 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -54,7 +54,7 @@ protected: public: bool scanned; - const Common::FSNode *resourceFile; + const Common::FSNode *_resourceFile; int volume_number; ResourceSource *associated_map; // TODO: Move to VolumeResourceSource uint32 audioCompressionType; // TODO: Move to AudioVolumeResourceSource -- cgit v1.2.3 From d4f16962d03f7b1e88ea76560801f2f77a20ebd1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:13:29 +0000 Subject: SCI: Move code from ResourceManager::loadResource to ResourceSource::loadResource svn-id: r49819 --- engines/sci/resource.cpp | 57 +++++++++++++++++++++++++------------------ engines/sci/resource.h | 2 ++ engines/sci/resource_intern.h | 12 ++++++++- 3 files changed, 46 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 3792d5d9c8..ad4daab005 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -176,14 +176,18 @@ ResourceSource::ResourceSource(ResSourceType type, const Common::String &name) associated_map = NULL; audioCompressionType = 0; audioCompressionOffsetMapping = NULL; - - if (_sourceType == kSourceMacResourceFork) - _macResMan = new Common::MacResManager(); - else - _macResMan = NULL; + _macResMan = NULL; } ResourceSource::~ResourceSource() { +} + +MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name) + : ResourceSource(kSourceMacResourceFork, name) { + _macResMan = new Common::MacResManager(); +} + +MacResourceForkResourceSource::~MacResourceForkResourceSource() { delete _macResMan; } @@ -344,17 +348,22 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc static uint32 resTypeToMacTag(ResourceType type); void ResourceManager::loadResource(Resource *res) { - if (res->_source->getSourceType() == kSourcePatch && loadFromPatchFile(res)) + res->_source->loadResource(res, this); +} + +void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + + if (getSourceType() == kSourcePatch && resMan->loadFromPatchFile(res)) return; - if (res->_source->getSourceType() == kSourceMacResourceFork) { - assert(res->_source->_macResMan); - Common::SeekableReadStream *stream = res->_source->_macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); + if (getSourceType() == kSourceMacResourceFork) { + assert(_macResMan); + Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); if (!stream) error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); - int error = decompress(res, stream); + int error = resMan->decompress(res, stream); if (error) { warning("Error %d occured while reading %s from Mac resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -363,27 +372,27 @@ void ResourceManager::loadResource(Resource *res) { return; } - Common::SeekableReadStream *fileStream = getVolumeFile(res->_source); + Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { - warning("Failed to open %s", res->_source->getLocationName().c_str()); + warning("Failed to open %s", getLocationName().c_str()); res->unalloc(); return; } - switch(res->_source->getSourceType()) { + switch(getSourceType()) { case kSourceWave: fileStream->seek(res->_fileOffset, SEEK_SET); - loadFromWaveFile(res, fileStream); - if (res->_source->_resourceFile) + resMan->loadFromWaveFile(res, fileStream); + if (_resourceFile) delete fileStream; return; case kSourceAudioVolume: - if (res->_source->audioCompressionType) { + if (audioCompressionType) { // this file is compressed, so lookup our offset in the offset-translation table and get the new offset // also calculate the compressed size by using the next offset - int32 *mappingTable = res->_source->audioCompressionOffsetMapping; + int32 *mappingTable = audioCompressionOffsetMapping; int32 compressedOffset = 0; do { @@ -413,8 +422,8 @@ void ResourceManager::loadResource(Resource *res) { case kResourceTypeAudio: case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 - loadFromAudioVolumeSCI1(res, fileStream); - if (res->_source->_resourceFile) + resMan->loadFromAudioVolumeSCI1(res, fileStream); + if (_resourceFile) delete fileStream; return; default: @@ -425,19 +434,19 @@ void ResourceManager::loadResource(Resource *res) { fileStream->seek(res->_fileOffset, SEEK_SET); } if (getSciVersion() < SCI_VERSION_1_1) - loadFromAudioVolumeSCI1(res, fileStream); + resMan->loadFromAudioVolumeSCI1(res, fileStream); else - loadFromAudioVolumeSCI11(res, fileStream); + resMan->loadFromAudioVolumeSCI11(res, fileStream); - if (res->_source->_resourceFile) + if (_resourceFile) delete fileStream; return; default: fileStream->seek(res->_fileOffset, SEEK_SET); - int error = decompress(res, fileStream); + int error = resMan->decompress(res, fileStream); - if (res->_source->_resourceFile) + if (_resourceFile) delete fileStream; if (error) { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index fa5d757def..89af97df7e 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -166,6 +166,7 @@ class Resource { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. + friend class ResourceSource; friend class MacResourceForkResourceSource; public: @@ -201,6 +202,7 @@ typedef Common::HashMap_source->loadResource(res, this); } -void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { - if (getSourceType() == kSourcePatch && resMan->loadFromPatchFile(res)) - return; +void PatchResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + bool result = resMan->loadFromPatchFile(res); + if (!result) { + // TODO: We used to fallback to the "default" code here if loadFromPatchFile + // failed, but I am not sure whether that is really appropriate. + // In fact it looks like a bug to me, so I commented this out for now. + //ResourceSource::loadResource(res, resMan); + } +} - if (getSourceType() == kSourceMacResourceFork) { - assert(_macResMan); - Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); +void MacResourceForkResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); - if (!stream) - error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); + if (!stream) + error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); - int error = resMan->decompress(res, stream); - if (error) { - warning("Error %d occured while reading %s from Mac resource file: %s", - error, res->_id.toString().c_str(), sci_error_types[error]); - res->unalloc(); - } - return; + int error = resMan->decompress(res, stream); + if (error) { + warning("Error %d occured while reading %s from Mac resource file: %s", + error, res->_id.toString().c_str(), sci_error_types[error]); + res->unalloc(); } +} +void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { @@ -1471,7 +1476,6 @@ static uint32 resTypeToMacTag(ResourceType type) { } void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { - assert(_macResMan); if (!_macResMan->open(getLocationName().c_str())) error("%s is not a valid Mac resource fork", getLocationName().c_str()); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 89af97df7e..ff848d24b2 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -204,9 +204,12 @@ class ResourceManager { // ease transition to the ResourceSource class system. friend class ResourceSource; friend class DirectoryResourceSource; + friend class PatchResourceSource; friend class ExtMapResourceSource; friend class IntMapResourceSource; + friend class AudioVolumeResourceSource; friend class ExtAudioMapResourceSource; + friend class WaveResourceSource; friend class MacResourceForkResourceSource; public: diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 5c63436b1b..3d51e0ae02 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -59,7 +59,6 @@ public: ResourceSource *associated_map; // TODO: Move to VolumeResourceSource uint32 audioCompressionType; // TODO: Move to AudioVolumeResourceSource int32 *audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource - Common::MacResManager *_macResMan; // TODO: Move to MacResourceForkResourceSource protected: ResourceSource(ResSourceType type, const Common::String &name); @@ -99,6 +98,8 @@ public: class PatchResourceSource : public ResourceSource { public: PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {} + + virtual void loadResource(Resource *res, ResourceManager *resMan); }; class VolumeResourceSource : public ResourceSource { @@ -134,6 +135,8 @@ public: AudioVolumeResourceSource(const Common::String &name, ResourceSource *map) : VolumeResourceSource(name, map, kSourceAudioVolume) { } + + //virtual void loadResource(Resource *res, ResourceManager *resMan); }; class ExtAudioMapResourceSource : public ResourceSource { @@ -146,9 +149,14 @@ public: class WaveResourceSource : public ResourceSource { public: WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} + + //virtual void loadResource(Resource *res, ResourceManager *resMan); }; class MacResourceForkResourceSource : public ResourceSource { +protected: + Common::MacResManager *_macResMan; + public: MacResourceForkResourceSource(const Common::String &name); ~MacResourceForkResourceSource(); @@ -157,6 +165,8 @@ public: * Reads the SCI1.1+ resource file from a Mac resource fork. */ virtual void scanSource(ResourceManager *resMan); + + virtual void loadResource(Resource *res, ResourceManager *resMan); }; } // End of namespace Sci -- cgit v1.2.3 From bb1336ca415311ed28195b2b7ac574e2244c2cc5 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:14:15 +0000 Subject: SCI: Add loadResource impls for WaveResourceSource and AudioVolumeResourceSource svn-id: r49821 --- engines/sci/resource.cpp | 142 +++++++++++++++++++++++------------------- engines/sci/resource.h | 4 +- engines/sci/resource_intern.h | 7 ++- 3 files changed, 85 insertions(+), 68 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 35e0c93d59..45ee9b3d0f 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -376,89 +376,101 @@ void MacResourceForkResourceSource::loadResource(Resource *res, ResourceManager } } -void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { +Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res, ResourceManager *resMan) { Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { warning("Failed to open %s", getLocationName().c_str()); res->unalloc(); - return; } - switch(getSourceType()) { - case kSourceWave: - fileStream->seek(res->_fileOffset, SEEK_SET); - resMan->loadFromWaveFile(res, fileStream); - if (_resourceFile) - delete fileStream; + return fileStream; +} + +void WaveResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); + if (!fileStream) return; - case kSourceAudioVolume: - if (audioCompressionType) { - // this file is compressed, so lookup our offset in the offset-translation table and get the new offset - // also calculate the compressed size by using the next offset - int32 *mappingTable = audioCompressionOffsetMapping; - int32 compressedOffset = 0; - - do { - if (*mappingTable == res->_fileOffset) { - mappingTable++; - compressedOffset = *mappingTable; - // Go to next compressed offset and use that to calculate size of compressed sample - switch (res->_id.type) { - case kResourceTypeSync: - case kResourceTypeSync36: - // we should already have a (valid) size - break; - default: - mappingTable += 2; - res->size = *mappingTable - compressedOffset; - } + fileStream->seek(res->_fileOffset, SEEK_SET); + resMan->loadFromWaveFile(res, fileStream); + if (_resourceFile) + delete fileStream; +} + +void AudioVolumeResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); + if (!fileStream) + return; + + if (audioCompressionType) { + // this file is compressed, so lookup our offset in the offset-translation table and get the new offset + // also calculate the compressed size by using the next offset + int32 *mappingTable = audioCompressionOffsetMapping; + int32 compressedOffset = 0; + + do { + if (*mappingTable == res->_fileOffset) { + mappingTable++; + compressedOffset = *mappingTable; + // Go to next compressed offset and use that to calculate size of compressed sample + switch (res->_id.type) { + case kResourceTypeSync: + case kResourceTypeSync36: + // we should already have a (valid) size break; + default: + mappingTable += 2; + res->size = *mappingTable - compressedOffset; } - mappingTable += 2; - } while (*mappingTable); - - if (!compressedOffset) - error("could not translate offset to compressed offset in audio volume"); - fileStream->seek(compressedOffset, SEEK_SET); - - switch (res->_id.type) { - case kResourceTypeAudio: - case kResourceTypeAudio36: - // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 - resMan->loadFromAudioVolumeSCI1(res, fileStream); - if (_resourceFile) - delete fileStream; - return; - default: break; } - } else { - // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource - fileStream->seek(res->_fileOffset, SEEK_SET); - } - if (getSciVersion() < SCI_VERSION_1_1) + mappingTable += 2; + } while (*mappingTable); + + if (!compressedOffset) + error("could not translate offset to compressed offset in audio volume"); + fileStream->seek(compressedOffset, SEEK_SET); + + switch (res->_id.type) { + case kResourceTypeAudio: + case kResourceTypeAudio36: + // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 resMan->loadFromAudioVolumeSCI1(res, fileStream); - else - resMan->loadFromAudioVolumeSCI11(res, fileStream); + if (_resourceFile) + delete fileStream; + return; + default: + break; + } + } else { + // original file, directly seek to given offset and get SCI1/SCI1.1 audio resource + fileStream->seek(res->_fileOffset, SEEK_SET); + } + if (getSciVersion() < SCI_VERSION_1_1) + resMan->loadFromAudioVolumeSCI1(res, fileStream); + else + resMan->loadFromAudioVolumeSCI11(res, fileStream); - if (_resourceFile) - delete fileStream; + if (_resourceFile) + delete fileStream; +} + +void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { + Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); + if (!fileStream) return; - default: - fileStream->seek(res->_fileOffset, SEEK_SET); - int error = resMan->decompress(res, fileStream); + fileStream->seek(res->_fileOffset, SEEK_SET); + int error = resMan->decompress(res, fileStream); - if (_resourceFile) - delete fileStream; + if (_resourceFile) + delete fileStream; - if (error) { - warning("Error %d occured while reading %s from resource file: %s", - error, res->_id.toString().c_str(), sci_error_types[error]); - res->unalloc(); - } + if (error) { + warning("Error %d occured while reading %s from resource file: %s", + error, res->_id.toString().c_str(), sci_error_types[error]); + res->unalloc(); } } @@ -1541,7 +1553,7 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 } int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, - uint32&szPacked, ResourceCompression &compression) { + uint32 &szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes // SCI1.1 volume format: {bResType wResNumber wPacked wUnpacked wCompression} = 9 bytes diff --git a/engines/sci/resource.h b/engines/sci/resource.h index ff848d24b2..6d37455f52 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -167,6 +167,8 @@ class Resource { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. friend class ResourceSource; + friend class WaveResourceSource; + friend class AudioVolumeResourceSource; friend class MacResourceForkResourceSource; public: @@ -393,7 +395,7 @@ protected: bool loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file); void freeOldResources(); int decompress(Resource *res, Common::SeekableReadStream *file); - int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32&szPacked, ResourceCompression &compression); + int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0); void removeAudioResource(ResourceId resId); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 3d51e0ae02..560e99ac80 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -68,6 +68,9 @@ public: ResSourceType getSourceType() const { return _sourceType; } const Common::String &getLocationName() const { return _name; } + // Auxiliary method, used by loadResource implementations. + Common::SeekableReadStream *getVolumeFile(Resource *res, ResourceManager *resMan); + /** * TODO: Document this */ @@ -136,7 +139,7 @@ public: : VolumeResourceSource(name, map, kSourceAudioVolume) { } - //virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res, ResourceManager *resMan); }; class ExtAudioMapResourceSource : public ResourceSource { @@ -150,7 +153,7 @@ class WaveResourceSource : public ResourceSource { public: WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} - //virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res, ResourceManager *resMan); }; class MacResourceForkResourceSource : public ResourceSource { -- cgit v1.2.3 From 07b896802b3d56748c0e33877a325978db0513ff Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:14:39 +0000 Subject: SCI: Pass volume number to ResourceSource subclass constructors; make ResourceSource::volume_number const svn-id: r49822 --- engines/sci/resource.cpp | 46 ++++++++++++++++++------------------------ engines/sci/resource.h | 4 ++-- engines/sci/resource_audio.cpp | 8 ++++++-- engines/sci/resource_intern.h | 32 ++++++++++++++++------------- 4 files changed, 46 insertions(+), 44 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 45ee9b3d0f..69bce4f5d5 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -168,11 +168,10 @@ uint32 Resource::getAudioCompressionType() { } -ResourceSource::ResourceSource(ResSourceType type, const Common::String &name) - : _sourceType(type), _name(name) { +ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum) + : _sourceType(type), _name(name), volume_number(volNum) { scanned = false; _resourceFile = 0; - volume_number = 0; associated_map = NULL; audioCompressionType = 0; audioCompressionOffsetMapping = NULL; @@ -181,8 +180,8 @@ ResourceSource::ResourceSource(ResSourceType type, const Common::String &name) ResourceSource::~ResourceSource() { } -MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name) - : ResourceSource(kSourceMacResourceFork, name) { +MacResourceForkResourceSource::MacResourceForkResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceMacResourceFork, name, volNum) { _macResMan = new Common::MacResManager(); assert(_macResMan); } @@ -196,28 +195,24 @@ MacResourceForkResourceSource::~MacResourceForkResourceSource() { // Resource source list management ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, int volume_nr) { - ResourceSource *newsrc = new ExtMapResourceSource(filename); - - newsrc->volume_number = volume_nr; + ResourceSource *newsrc = new ExtMapResourceSource(filename, volume_nr); _sources.push_back(newsrc); return newsrc; } ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName()); + ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr); newsrc->_resourceFile = mapFile; - newsrc->volume_number = volume_nr; _sources.push_back(newsrc); return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, int number) { +ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) { assert(newsrc); - newsrc->volume_number = number; if (newsrc->getSourceType() == kSourceAudioVolume) { // TODO: Move this call into the AudioVolumeResourceSource constructor. // Need to verify if this is safe, though; in particular, whether this @@ -230,11 +225,10 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, int number) { return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common::FSNode *resFile, int number) { +ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common::FSNode *resFile) { assert(newsrc); newsrc->_resourceFile = resFile; - newsrc->volume_number = number; if (newsrc->getSourceType() == kSourceAudioVolume) { // TODO: Move this call into the AudioVolumeResourceSource constructor. // Need to verify if this is safe, though; in particular, whether this @@ -492,12 +486,12 @@ int ResourceManager::addAppropriateSources() { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(new VolumeResourceSource(name, map), number); + addSource(new VolumeResourceSource(name, map, number)); } #ifdef ENABLE_SCI32 // GK1CD hires content if (Common::File::exists("alt.map") && Common::File::exists("resource.alt")) - addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10)), 10); + addSource(new VolumeResourceSource("resource.alt", addExternalMap("alt.map", 10), 10)); #endif } else if (Common::File::exists("Data1")) { // Mac SCI1.1+ file naming scheme @@ -505,7 +499,7 @@ int ResourceManager::addAppropriateSources() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { Common::String filename = (*x)->getName(); - addSource(new MacResourceForkResourceSource(filename), atoi(filename.c_str() + 4)); + addSource(new MacResourceForkResourceSource(filename, atoi(filename.c_str() + 4))); } #ifdef ENABLE_SCI32 // Mac SCI32 games have extra folders for patches @@ -517,7 +511,7 @@ int ResourceManager::addAppropriateSources() { // There can also be a "Patches" resource fork with patches if (Common::File::exists("Patches")) - addSource(new MacResourceForkResourceSource("Patches"), 100); + addSource(new MacResourceForkResourceSource("Patches", 100)); } else { // SCI2.1-SCI3 file naming scheme Common::ArchiveMemberList mapFiles; @@ -537,7 +531,7 @@ int ResourceManager::addAppropriateSources() { int resNumber = atoi(strrchr(resName.c_str(), '.') + 1); if (mapNumber == resNumber) { - addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber)), mapNumber); + addSource(new VolumeResourceSource(resName, addExternalMap(mapName, mapNumber), mapNumber)); break; } } @@ -546,7 +540,7 @@ int ResourceManager::addAppropriateSources() { // SCI2.1 resource patches if (Common::File::exists("resmap.pat") && Common::File::exists("ressci.pat")) { // We add this resource with a map which surely won't exist - addSource(new VolumeResourceSource("ressci.pat", addExternalMap("resmap.pat", 100)), 100); + addSource(new VolumeResourceSource("ressci.pat", addExternalMap("resmap.pat", 100), 100)); } } #else @@ -556,7 +550,7 @@ int ResourceManager::addAppropriateSources() { addPatchDir("."); if (Common::File::exists("message.map")) - addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map")), 0); + addSource(new VolumeResourceSource("resource.msg", addExternalMap("message.map"), 0)); return 1; } @@ -600,7 +594,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { #ifdef ENABLE_SCI32 if (sci21PatchMap && sci21PatchRes) - addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap), sci21PatchRes, 100); + addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100), sci21PatchRes); #endif // Now find all the resource.0?? files @@ -615,7 +609,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { const char *dot = strrchr(filename.c_str(), '.'); int number = atoi(dot + 1); - addSource(new VolumeResourceSource(file->getName(), map), file, number); + addSource(new VolumeResourceSource(file->getName(), map, number), file); } } @@ -630,12 +624,12 @@ int ResourceManager::addInternalSources() { Common::List::iterator itr = resources->begin(); while (itr != resources->end()) { - ResourceSource *src = addSource(new IntMapResourceSource("MAP"), itr->number); + ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->number)); if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) - addSource(new AudioVolumeResourceSource("RESOURCE.SFX", src), 0); + addSource(new AudioVolumeResourceSource("RESOURCE.SFX", src, 0)); else if (Common::File::exists("RESOURCE.AUD")) - addSource(new AudioVolumeResourceSource("RESOURCE.AUD", src), 0); + addSource(new AudioVolumeResourceSource("RESOURCE.AUD", src, 0)); ++itr; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 6d37455f52..bddcbffae7 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -339,9 +339,9 @@ protected: * @param source The new source to add * @return A pointer to the added source structure, or NULL if an error occurred. */ - ResourceSource *addSource(ResourceSource *source, int number); + ResourceSource *addSource(ResourceSource *source); - ResourceSource *addSource(ResourceSource *source, const Common::FSNode *resFile, int number); + ResourceSource *addSource(ResourceSource *source, const Common::FSNode *resFile); /** * Add an external (i.e., separate file) map resource to the resource manager's list of sources. diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index d94c7d010a..cbd713c906 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -33,6 +33,10 @@ namespace Sci { +AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum) + : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { +} + void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { Common::SeekableReadStream *fileStream = getVolumeFile(source); @@ -433,7 +437,7 @@ void ResourceManager::setAudioLanguage(int language) { return; } - _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname), language); + _audioMapSCI1 = addSource(new ExtAudioMapResourceSource(fullname, language)); // Search for audio volumes for this language and add them to the source list Common::ArchiveMemberList files; @@ -443,7 +447,7 @@ void ResourceManager::setAudioLanguage(int language) { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(new AudioVolumeResourceSource(name, _audioMapSCI1), number); + addSource(new AudioVolumeResourceSource(name, _audioMapSCI1, number)); } scanNewSources(); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 560e99ac80..52f47aca8b 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -55,13 +55,13 @@ protected: public: bool scanned; const Common::FSNode *_resourceFile; - int volume_number; + const int volume_number; ResourceSource *associated_map; // TODO: Move to VolumeResourceSource uint32 audioCompressionType; // TODO: Move to AudioVolumeResourceSource int32 *audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource protected: - ResourceSource(ResSourceType type, const Common::String &name); + ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0); public: virtual ~ResourceSource(); @@ -74,7 +74,7 @@ public: /** * TODO: Document this */ - virtual ResourceSource *findVolume(ResourceSource *map, int volume_nr) { + virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { return NULL; }; @@ -107,13 +107,13 @@ public: class VolumeResourceSource : public ResourceSource { public: - VolumeResourceSource(const Common::String &name, ResourceSource *map, ResSourceType type = kSourceVolume) - : ResourceSource(type, name) { + VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume) + : ResourceSource(type, name, volNum) { associated_map = map; } - virtual ResourceSource *findVolume(ResourceSource *map, int volume_nr) { - if (associated_map == map && volume_number == volume_nr) + virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { + if (associated_map == map && volume_number == volNum) return this; return NULL; }; @@ -121,30 +121,34 @@ public: class ExtMapResourceSource : public ResourceSource { public: - ExtMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtMap, name) {} + ExtMapResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceExtMap, name, volNum) { + } virtual void scanSource(ResourceManager *resMan); }; class IntMapResourceSource : public ResourceSource { public: - IntMapResourceSource(const Common::String &name) : ResourceSource(kSourceIntMap, name) {} + IntMapResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceIntMap, name, volNum) { + } virtual void scanSource(ResourceManager *resMan); }; class AudioVolumeResourceSource : public VolumeResourceSource { public: - AudioVolumeResourceSource(const Common::String &name, ResourceSource *map) - : VolumeResourceSource(name, map, kSourceAudioVolume) { - } + AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum); virtual void loadResource(Resource *res, ResourceManager *resMan); }; class ExtAudioMapResourceSource : public ResourceSource { public: - ExtAudioMapResourceSource(const Common::String &name) : ResourceSource(kSourceExtAudioMap, name) {} + ExtAudioMapResourceSource(const Common::String &name, int volNum) + : ResourceSource(kSourceExtAudioMap, name, volNum) { + } virtual void scanSource(ResourceManager *resMan); }; @@ -161,7 +165,7 @@ protected: Common::MacResManager *_macResMan; public: - MacResourceForkResourceSource(const Common::String &name); + MacResourceForkResourceSource(const Common::String &name, int volNum); ~MacResourceForkResourceSource(); /** -- cgit v1.2.3 From 4020500640481e0a8089fd82ad94d2c286f0e024 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:15:05 +0000 Subject: SCI: Rename ResourceSource members to follow _camelCase convention svn-id: r49823 --- engines/sci/resource.cpp | 22 +++++++++++----------- engines/sci/resource.h | 2 +- engines/sci/resource_audio.cpp | 20 ++++++++++---------- engines/sci/resource_intern.h | 14 +++++++------- 4 files changed, 29 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 69bce4f5d5..1614700886 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -164,17 +164,17 @@ void Resource::writeToStream(Common::WriteStream *stream) const { } uint32 Resource::getAudioCompressionType() { - return _source->audioCompressionType; + return _source->_audioCompressionType; } ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum) - : _sourceType(type), _name(name), volume_number(volNum) { - scanned = false; + : _sourceType(type), _name(name), _volumeNumber(volNum) { + _scanned = false; _resourceFile = 0; - associated_map = NULL; - audioCompressionType = 0; - audioCompressionOffsetMapping = NULL; + _associatedMap = NULL; + _audioCompressionType = 0; + _audioCompressionOffsetMapping = NULL; } ResourceSource::~ResourceSource() { @@ -397,10 +397,10 @@ void AudioVolumeResourceSource::loadResource(Resource *res, ResourceManager *res if (!fileStream) return; - if (audioCompressionType) { + if (_audioCompressionType) { // this file is compressed, so lookup our offset in the offset-translation table and get the new offset // also calculate the compressed size by using the next offset - int32 *mappingTable = audioCompressionOffsetMapping; + int32 *mappingTable = _audioCompressionOffsetMapping; int32 compressedOffset = 0; do { @@ -641,8 +641,8 @@ void ResourceManager::scanNewSources() { for (Common::List::iterator it = _sources.begin(); it != _sources.end(); ++it) { ResourceSource *source = *it; - if (!source->scanned) { - source->scanned = true; + if (!source->_scanned) { + source->_scanned = true; source->scanSource(this); } } @@ -1439,7 +1439,7 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers // need to be used in concurrence with the volume specified in the map to get // the actual resource file. - res->_source = findVolume(map, volume_nr + map->volume_number); + res->_source = findVolume(map, volume_nr + map->_volumeNumber); res->_fileOffset = off; } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index bddcbffae7..e753dc1686 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -362,7 +362,7 @@ protected: ResourceSource *addInternalMap(const Common::String &name, int resNr); /** - * Checks, if an audio volume got compressed by our tool. If that's the case, it will set audioCompressionType + * Checks, if an audio volume got compressed by our tool. If that's the case, it will set _audioCompressionType * and read in the offset translation table for later usage. */ void checkIfAudioVolumeIsCompressed(ResourceSource *source); diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index cbd713c906..25e73242ef 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -52,13 +52,13 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { case MKID_BE('OGG '): case MKID_BE('FLAC'): // Detected a compressed audio volume - source->audioCompressionType = compressionType; + source->_audioCompressionType = compressionType; // Now read the whole offset mapping table for later usage int32 recordCount = fileStream->readUint32LE(); if (!recordCount) error("compressed audio volume doesn't contain any entries!"); int32 *offsetMapping = new int32[(recordCount + 1) * 2]; - source->audioCompressionOffsetMapping = offsetMapping; + source->_audioCompressionOffsetMapping = offsetMapping; for (int recordNo = 0; recordNo < recordCount; recordNo++) { *offsetMapping++ = fileStream->readUint32LE(); *offsetMapping++ = fileStream->readUint32LE(); @@ -257,10 +257,10 @@ void ResourceManager::removeAudioResource(ResourceId resId) { int ResourceManager::readAudioMapSCI11(ResourceSource *map) { bool isEarly = true; uint32 offset = 0; - Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->volume_number), false); + Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false); if (!mapRes) { - warning("Failed to open %i.MAP", map->volume_number); + warning("Failed to open %i.MAP", map->_volumeNumber); return SCI_ERROR_RESMAP_NOT_FOUND; } @@ -271,7 +271,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { byte *ptr = mapRes->data; - if (map->volume_number == 65535) { + if (map->_volumeNumber == 65535) { // Heuristic to detect late SCI1.1 map format if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) isEarly = false; @@ -324,7 +324,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { ptr += 2; if (syncSize > 0) - addResource(ResourceId(kResourceTypeSync36, map->volume_number, n & 0xffffff3f), src, offset, syncSize); + addResource(ResourceId(kResourceTypeSync36, map->_volumeNumber, n & 0xffffff3f), src, offset, syncSize); } if (n & 0x40) { @@ -334,7 +334,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { ptr += 2; } - addResource(ResourceId(kResourceTypeAudio36, map->volume_number, n & 0xffffff3f), src, offset + syncSize); + addResource(ResourceId(kResourceTypeAudio36, map->_volumeNumber, n & 0xffffff3f), src, offset + syncSize); } } @@ -401,7 +401,7 @@ int ResourceManager::readAudioMapSCI1(ResourceSource *map, bool unload) { void ResourceManager::setAudioLanguage(int language) { if (_audioMapSCI1) { - if (_audioMapSCI1->volume_number == language) { + if (_audioMapSCI1->_volumeNumber == language) { // This language is already loaded return; } @@ -413,7 +413,7 @@ void ResourceManager::setAudioLanguage(int language) { Common::List::iterator it = _sources.begin(); while (it != _sources.end()) { ResourceSource *src = *it; - if (src->associated_map == _audioMapSCI1) { + if (src->_associatedMap == _audioMapSCI1) { it = _sources.erase(it); delete src; } else { @@ -454,7 +454,7 @@ void ResourceManager::setAudioLanguage(int language) { } int ResourceManager::getAudioLanguage() const { - return (_audioMapSCI1 ? _audioMapSCI1->volume_number : 0); + return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0); } SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 52f47aca8b..5a5129c125 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -53,12 +53,12 @@ protected: const Common::String _name; public: - bool scanned; + bool _scanned; const Common::FSNode *_resourceFile; - const int volume_number; - ResourceSource *associated_map; // TODO: Move to VolumeResourceSource - uint32 audioCompressionType; // TODO: Move to AudioVolumeResourceSource - int32 *audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource + const int _volumeNumber; + ResourceSource *_associatedMap; // TODO: Move to VolumeResourceSource + uint32 _audioCompressionType; // TODO: Move to AudioVolumeResourceSource + int32 *_audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource protected: ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0); @@ -109,11 +109,11 @@ class VolumeResourceSource : public ResourceSource { public: VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume) : ResourceSource(type, name, volNum) { - associated_map = map; + _associatedMap = map; } virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { - if (associated_map == map && volume_number == volNum) + if (_associatedMap == map && _volumeNumber == volNum) return this; return NULL; }; -- cgit v1.2.3 From 713e61acba05c49ec4bc896fa2e873c3265000a7 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:15:27 +0000 Subject: SCI: Doxygen fixes svn-id: r49824 --- engines/sci/resource.h | 77 +++++++++++++++++++++++++++----------------------- 1 file changed, 41 insertions(+), 36 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.h b/engines/sci/resource.h index e753dc1686..3d5b874977 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -234,36 +234,39 @@ public: /** * Looks up a resource's data. - * @param id: The resource type to look for - * @param lock: non-zero iff the resource should be locked - * @return (Resource *): The resource, or NULL if it doesn't exist + * @param id The resource type to look for + * @param lock non-zero iff the resource should be locked + * @return The resource, or NULL if it doesn't exist * @note Locked resources are guaranteed not to have their contents freed until * they are unlocked explicitly (by unlockResource). */ Resource *findResource(ResourceId id, bool lock); - /* Unlocks a previously locked resource - ** (Resource *) res: The resource to free - ** Returns : () - */ + /** + * Unlocks a previously locked resource. + * @param res The resource to free + */ void unlockResource(Resource *res); - /* Tests whether a resource exists - ** (ResourceId) id: Id of the resource to check - ** Returns : (Resource *) non-NULL if the resource exists, NULL otherwise - ** This function may often be much faster than finding the resource - ** and should be preferred for simple tests. - ** The resource object returned is, indeed, the resource in question, but - ** it should be used with care, as it may be unallocated. - ** Use scir_find_resource() if you want to use the data contained in the resource. - */ + /** + * Tests whether a resource exists. + * + * This function may often be much faster than finding the resource + * and should be preferred for simple tests. + * The resource object returned is, indeed, the resource in question, but + * it should be used with care, as it may be unallocated. + * Use scir_find_resource() if you want to use the data contained in the resource. + * + * @param id Id of the resource to check + * @return non-NULL if the resource exists, NULL otherwise + */ Resource *testResource(ResourceId id); /** * Returns a list of all resources of the specified type. - * @param type: The resource type to look for - * @param mapNumber: For audio36 and sync36, limit search to this map - * @return: The resource list + * @param type The resource type to look for + * @param mapNumber For audio36 and sync36, limit search to this map + * @return The resource list */ Common::List *listResources(ResourceType type, int mapNumber = -1); @@ -280,7 +283,7 @@ public: * Adds the appropriate GM patch from the Sierra MIDI utility as 4.pat, without * requiring the user to rename the file to 4.pat. Thus, the original Sierra * archive can be extracted in the extras directory, and the GM patches can be - * applied per game, if applicable + * applied per game, if applicable. */ void addNewGMPatch(const Common::String &gameId); @@ -289,13 +292,13 @@ public: bool detectFontExtended(); /** - * Finds the internal Sierra ID of the current game from script 0 + * Finds the internal Sierra ID of the current game from script 0. */ Common::String findSierraGameId(); /** - * Finds the location of the game object from script 0 - * @param addSci11ScriptOffset: Adjust the return value for SCI1.1 and newer + * Finds the location of the game object from script 0. + * @param addSci11ScriptOffset Adjust the return value for SCI1.1 and newer * games. Needs to be false when the heap is accessed directly inside * findSierraGameId(). */ @@ -337,14 +340,15 @@ protected: /** * Adds a source to the resource manager's list of sources. * @param source The new source to add - * @return A pointer to the added source structure, or NULL if an error occurred. + * @return A pointer to the added source structure, or NULL if an error occurred. */ ResourceSource *addSource(ResourceSource *source); ResourceSource *addSource(ResourceSource *source, const Common::FSNode *resFile); /** - * Add an external (i.e., separate file) map resource to the resource manager's list of sources. + * Add an external (i.e., separate file) map resource to the resource + * manager's list of sources. * @param file_name The name of the volume to add * @param volume_nr The volume number the map starts at, 0 for getResMan() returns a valid value much sooner, allowing me to simplify some code. Also added a note about potentially replacing Common::FSList usage by Common::Archive (and FSNode by Archive/ArchiveMember ?). This might be a way to unify the addAppropriateSources variants again. svn-id: r49825 --- engines/sci/detection.cpp | 7 ++++++- engines/sci/resource.cpp | 7 ------- engines/sci/resource.h | 18 ++++++++++-------- engines/sci/sci.cpp | 21 +++++++++++++++++---- 4 files changed, 33 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 7163c879b1..3b153d3dd1 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -428,7 +428,12 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl return 0; } - ResourceManager *resMan = new ResourceManager(fslist); + ResourceManager *resMan = new ResourceManager(); + assert(resMan); + resMan->addAppropriateSources(fslist); + resMan->init(); + // TODO: Add error handling. + ViewType gameViews = resMan->getViewType(); // Have we identified the game views? If not, stop here diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 1614700886..a1e7a5c85c 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -682,13 +682,6 @@ void ResourceManager::freeResourceSources() { } ResourceManager::ResourceManager() { - addAppropriateSources(); - init(); -} - -ResourceManager::ResourceManager(const Common::FSList &fslist) { - addAppropriateSources(fslist); - init(); } void ResourceManager::init() { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 3d5b874977..36d75fb56f 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -229,9 +229,17 @@ public: * Creates a new SCI resource manager. */ ResourceManager(); - ResourceManager(const Common::FSList &fslist); ~ResourceManager(); + + /** + * Initializes the resource manager. + */ + void init(); + + int addAppropriateSources(); + int addAppropriateSources(const Common::FSList &fslist); // TODO: Switch from FSList to Common::Archive? + /** * Looks up a resource's data. * @param id The resource type to look for @@ -324,11 +332,6 @@ protected: ResVersion _volVersion; ///< resource.0xx version ResVersion _mapVersion; ///< resource.map version - /** - * Initializes the resource manager - */ - void init(); - /** * Add a path to the resource manager's list of sources. * @return a pointer to the added source structure, or NULL if an error occurred. @@ -379,8 +382,7 @@ protected: * @return One of SCI_ERROR_*. */ void scanNewSources(); - int addAppropriateSources(); - int addAppropriateSources(const Common::FSList &fslist); + int addInternalSources(); void freeResourceSources(); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index e8847f380b..2680da9d39 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -66,11 +66,20 @@ class GfxDriver; SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) : Engine(syst), _gameDescription(desc), _system(syst) { - _console = NULL; assert(g_sci == 0); g_sci = this; + + _gfxMacIconBar = 0; + + _audio = 0; _features = 0; + _resMan = 0; + _gamestate = 0; + _kernel = 0; + _vocabulary = 0; + _eventMan = 0; + _console = 0; // Set up the engine specific debug levels DebugMan.addDebugChannel(kDebugLevelError, "Error", "Script error debugging"); @@ -98,9 +107,6 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); - _gamestate = 0; - _gfxMacIconBar = 0; - const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.addSubDirectoryMatching(gameDataDir, "actors"); // KQ6 hi-res portraits @@ -138,11 +144,18 @@ Common::Error SciEngine::run() { ConfMan.registerDefault("enable_fb01", "false"); _resMan = new ResourceManager(); + assert(_resMan); + _resMan->addAppropriateSources(); + _resMan->init(); + // TODO: Add error handling. Check return values of addAppropriateSources + // and init. We first have to *add* sensible return values, though ;). +/* if (!_resMan) { warning("No resources found, aborting"); return Common::kNoGameDataFoundError; } +*/ // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(getGameID()); -- cgit v1.2.3 From 348953c067bc9e70702b64f130cbbe4cbc742223 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:16:17 +0000 Subject: SCI: Make ResourceSource::_resourceFile const svn-id: r49826 --- engines/sci/resource.cpp | 29 +++++------------------------ engines/sci/resource.h | 2 -- engines/sci/resource_intern.h | 13 +++++++++---- 3 files changed, 14 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index a1e7a5c85c..108cfa5f63 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -168,10 +168,9 @@ uint32 Resource::getAudioCompressionType() { } -ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum) - : _sourceType(type), _name(name), _volumeNumber(volNum) { +ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum, const Common::FSNode *resFile) + : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) { _scanned = false; - _resourceFile = 0; _associatedMap = NULL; _audioCompressionType = 0; _audioCompressionOffsetMapping = NULL; @@ -202,9 +201,7 @@ ResourceSource *ResourceManager::addExternalMap(const Common::String &filename, } ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, int volume_nr) { - ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr); - - newsrc->_resourceFile = mapFile; + ResourceSource *newsrc = new ExtMapResourceSource(mapFile->getName(), volume_nr, mapFile); _sources.push_back(newsrc); return newsrc; @@ -225,22 +222,6 @@ ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) { return newsrc; } -ResourceSource *ResourceManager::addSource(ResourceSource *newsrc, const Common::FSNode *resFile) { - assert(newsrc); - - newsrc->_resourceFile = resFile; - if (newsrc->getSourceType() == kSourceAudioVolume) { - // TODO: Move this call into the AudioVolumeResourceSource constructor. - // Need to verify if this is safe, though; in particular, whether this - // method may be called before the new AudioVolumeResourceSource has been - // added to the _sources lists. - checkIfAudioVolumeIsCompressed(newsrc); - } - - _sources.push_back(newsrc); - return newsrc; -} - ResourceSource *ResourceManager::addPatchDir(const Common::String &dirname) { ResourceSource *newsrc = new DirectoryResourceSource(dirname); @@ -594,7 +575,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { #ifdef ENABLE_SCI32 if (sci21PatchMap && sci21PatchRes) - addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100), sci21PatchRes); + addSource(new VolumeResourceSource(sci21PatchRes->getName(), sci21PatchMap, 100, sci21PatchRes)); #endif // Now find all the resource.0?? files @@ -609,7 +590,7 @@ int ResourceManager::addAppropriateSources(const Common::FSList &fslist) { const char *dot = strrchr(filename.c_str(), '.'); int number = atoi(dot + 1); - addSource(new VolumeResourceSource(file->getName(), map, number), file); + addSource(new VolumeResourceSource(file->getName(), map, number, file)); } } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 36d75fb56f..de40f73306 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -347,8 +347,6 @@ protected: */ ResourceSource *addSource(ResourceSource *source); - ResourceSource *addSource(ResourceSource *source, const Common::FSNode *resFile); - /** * Add an external (i.e., separate file) map resource to the resource * manager's list of sources. diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 5a5129c125..f2853951fa 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -54,14 +54,14 @@ protected: public: bool _scanned; - const Common::FSNode *_resourceFile; + const Common::FSNode * const _resourceFile; const int _volumeNumber; ResourceSource *_associatedMap; // TODO: Move to VolumeResourceSource uint32 _audioCompressionType; // TODO: Move to AudioVolumeResourceSource int32 *_audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource protected: - ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0); + ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0); public: virtual ~ResourceSource(); @@ -112,6 +112,11 @@ public: _associatedMap = map; } + VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, const Common::FSNode *resFile) + : ResourceSource(kSourceVolume, name, volNum, resFile) { + _associatedMap = map; + } + virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { if (_associatedMap == map && _volumeNumber == volNum) return this; @@ -121,8 +126,8 @@ public: class ExtMapResourceSource : public ResourceSource { public: - ExtMapResourceSource(const Common::String &name, int volNum) - : ResourceSource(kSourceExtMap, name, volNum) { + ExtMapResourceSource(const Common::String &name, int volNum, const Common::FSNode *resFile = 0) + : ResourceSource(kSourceExtMap, name, volNum, resFile) { } virtual void scanSource(ResourceManager *resMan); -- cgit v1.2.3 From 88663c9186e5a4282f5553ad401b340db51164c2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:16:42 +0000 Subject: SCI: Merge ResourceManager::checkIfAudioVolumeIsCompressed into AudioVolumeResourceSource constructor svn-id: r49827 --- engines/sci/resource.cpp | 8 -------- engines/sci/resource.h | 7 ------- engines/sci/resource_audio.cpp | 20 +++++++++++++------- 3 files changed, 13 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 108cfa5f63..fcff177262 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -210,14 +210,6 @@ ResourceSource *ResourceManager::addExternalMap(const Common::FSNode *mapFile, i ResourceSource *ResourceManager::addSource(ResourceSource *newsrc) { assert(newsrc); - if (newsrc->getSourceType() == kSourceAudioVolume) { - // TODO: Move this call into the AudioVolumeResourceSource constructor. - // Need to verify if this is safe, though; in particular, whether this - // method may be called before the new AudioVolumeResourceSource has been - // added to the _sources lists. - checkIfAudioVolumeIsCompressed(newsrc); - } - _sources.push_back(newsrc); return newsrc; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index de40f73306..0d76a4e4a9 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -366,13 +366,6 @@ protected: */ ResourceSource *addInternalMap(const Common::String &name, int resNr); - /** - * Checks if an audio volume got compressed by our tool. If that is the - * case, set _audioCompressionType and read in the offset translation - * table for later usage. - */ - void checkIfAudioVolumeIsCompressed(ResourceSource *source); - /** * Scans newly registered resource sources for resources, earliest addition first. * @param detected_version Pointer to the detected version number, diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 25e73242ef..4f38fe15d1 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -35,13 +35,19 @@ namespace Sci { AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum) : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { -} -void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { - Common::SeekableReadStream *fileStream = getVolumeFile(source); + ResourceManager *resMan = g_sci->getResMan(); + + /* + * Check if this audio volume got compressed by our tool. If that is the + * case, set _audioCompressionType and read in the offset translation + * table for later usage. + */ + + Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { - warning("Failed to open %s", source->getLocationName().c_str()); + warning("Failed to open %s", getLocationName().c_str()); return; } @@ -52,13 +58,13 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { case MKID_BE('OGG '): case MKID_BE('FLAC'): // Detected a compressed audio volume - source->_audioCompressionType = compressionType; + _audioCompressionType = compressionType; // Now read the whole offset mapping table for later usage int32 recordCount = fileStream->readUint32LE(); if (!recordCount) error("compressed audio volume doesn't contain any entries!"); int32 *offsetMapping = new int32[(recordCount + 1) * 2]; - source->_audioCompressionOffsetMapping = offsetMapping; + _audioCompressionOffsetMapping = offsetMapping; for (int recordNo = 0; recordNo < recordCount; recordNo++) { *offsetMapping++ = fileStream->readUint32LE(); *offsetMapping++ = fileStream->readUint32LE(); @@ -68,7 +74,7 @@ void ResourceManager::checkIfAudioVolumeIsCompressed(ResourceSource *source) { *offsetMapping++ = fileStream->size(); } - if (source->_resourceFile) + if (_resourceFile) delete fileStream; } -- cgit v1.2.3 From 6248daccfc636533ad294df7739b00c0f011f2e3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:17:05 +0000 Subject: SCI: Get rid of ugly resMan params to ResourceSource methods We might want to add a ResourceSource::_resMan member, but for now I am not adding one on purpose; many more things might still move between ResourceSource and ResourceManager, so we should wait till the refactoring is complete. svn-id: r49828 --- engines/sci/resource.cpp | 45 +++++++++++++++++++++++++++---------------- engines/sci/resource_intern.h | 26 ++++++++++++------------- 2 files changed, 40 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index fcff177262..7d6835a336 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -315,21 +315,23 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc static uint32 resTypeToMacTag(ResourceType type); void ResourceManager::loadResource(Resource *res) { - res->_source->loadResource(res, this); + res->_source->loadResource(res); } -void PatchResourceSource::loadResource(Resource *res, ResourceManager *resMan) { +void PatchResourceSource::loadResource(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); bool result = resMan->loadFromPatchFile(res); if (!result) { // TODO: We used to fallback to the "default" code here if loadFromPatchFile // failed, but I am not sure whether that is really appropriate. // In fact it looks like a bug to me, so I commented this out for now. - //ResourceSource::loadResource(res, resMan); + //ResourceSource::loadResource(res); } } -void MacResourceForkResourceSource::loadResource(Resource *res, ResourceManager *resMan) { +void MacResourceForkResourceSource::loadResource(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); if (!stream) @@ -343,7 +345,8 @@ void MacResourceForkResourceSource::loadResource(Resource *res, ResourceManager } } -Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res, ResourceManager *resMan) { +Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { @@ -354,8 +357,9 @@ Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res, Resourc return fileStream; } -void WaveResourceSource::loadResource(Resource *res, ResourceManager *resMan) { - Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); +void WaveResourceSource::loadResource(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); + Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; @@ -365,8 +369,9 @@ void WaveResourceSource::loadResource(Resource *res, ResourceManager *resMan) { delete fileStream; } -void AudioVolumeResourceSource::loadResource(Resource *res, ResourceManager *resMan) { - Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); +void AudioVolumeResourceSource::loadResource(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); + Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; @@ -423,8 +428,9 @@ void AudioVolumeResourceSource::loadResource(Resource *res, ResourceManager *res delete fileStream; } -void ResourceSource::loadResource(Resource *res, ResourceManager *resMan) { - Common::SeekableReadStream *fileStream = getVolumeFile(res, resMan); +void ResourceSource::loadResource(Resource *res) { + ResourceManager *resMan = g_sci->getResMan(); + Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; @@ -616,12 +622,13 @@ void ResourceManager::scanNewSources() { if (!source->_scanned) { source->_scanned = true; - source->scanSource(this); + source->scanSource(); } } } -void DirectoryResourceSource::scanSource(ResourceManager *resMan) { +void DirectoryResourceSource::scanSource() { + ResourceManager *resMan = g_sci->getResMan(); resMan->readResourcePatches(this); // We can't use getSciVersion() at this point, thus using _volVersion @@ -631,18 +638,21 @@ void DirectoryResourceSource::scanSource(ResourceManager *resMan) { resMan->readWaveAudioPatches(); } -void ExtMapResourceSource::scanSource(ResourceManager *resMan) { +void ExtMapResourceSource::scanSource() { + ResourceManager *resMan = g_sci->getResMan(); if (resMan->_mapVersion < ResourceManager::kResVersionSci1Late) resMan->readResourceMapSCI0(this); else resMan->readResourceMapSCI1(this); } -void ExtAudioMapResourceSource::scanSource(ResourceManager *resMan) { +void ExtAudioMapResourceSource::scanSource() { + ResourceManager *resMan = g_sci->getResMan(); resMan->readAudioMapSCI1(this); } -void IntMapResourceSource::scanSource(ResourceManager *resMan) { +void IntMapResourceSource::scanSource() { + ResourceManager *resMan = g_sci->getResMan(); resMan->readAudioMapSCI11(this); } @@ -1447,7 +1457,8 @@ static uint32 resTypeToMacTag(ResourceType type) { return 0; } -void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { +void MacResourceForkResourceSource::scanSource() { + ResourceManager *resMan = g_sci->getResMan(); if (!_macResMan->open(getLocationName().c_str())) error("%s is not a valid Mac resource fork", getLocationName().c_str()); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index f2853951fa..ce5e3ac0e6 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -69,7 +69,7 @@ public: const Common::String &getLocationName() const { return _name; } // Auxiliary method, used by loadResource implementations. - Common::SeekableReadStream *getVolumeFile(Resource *res, ResourceManager *resMan); + Common::SeekableReadStream *getVolumeFile(Resource *res); /** * TODO: Document this @@ -80,29 +80,27 @@ public: /** * Scan this source for TODO. - * TODO: The resMan param for now is just a hack. */ - virtual void scanSource(ResourceManager *resMan) {} + virtual void scanSource() {} /** * Load a resource. - * TODO: The resMan param for now is just a hack. */ - virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res); }; class DirectoryResourceSource : public ResourceSource { public: DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {} - virtual void scanSource(ResourceManager *resMan); + virtual void scanSource(); }; class PatchResourceSource : public ResourceSource { public: PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {} - virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res); }; class VolumeResourceSource : public ResourceSource { @@ -130,7 +128,7 @@ public: : ResourceSource(kSourceExtMap, name, volNum, resFile) { } - virtual void scanSource(ResourceManager *resMan); + virtual void scanSource(); }; class IntMapResourceSource : public ResourceSource { @@ -139,14 +137,14 @@ public: : ResourceSource(kSourceIntMap, name, volNum) { } - virtual void scanSource(ResourceManager *resMan); + virtual void scanSource(); }; class AudioVolumeResourceSource : public VolumeResourceSource { public: AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum); - virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res); }; class ExtAudioMapResourceSource : public ResourceSource { @@ -155,14 +153,14 @@ public: : ResourceSource(kSourceExtAudioMap, name, volNum) { } - virtual void scanSource(ResourceManager *resMan); + virtual void scanSource(); }; class WaveResourceSource : public ResourceSource { public: WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} - virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res); }; class MacResourceForkResourceSource : public ResourceSource { @@ -176,9 +174,9 @@ public: /** * Reads the SCI1.1+ resource file from a Mac resource fork. */ - virtual void scanSource(ResourceManager *resMan); + virtual void scanSource(); - virtual void loadResource(Resource *res, ResourceManager *resMan); + virtual void loadResource(Resource *res); }; } // End of namespace Sci -- cgit v1.2.3 From 1a0201f7e978df307e496a43691b81950eba66b1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:17:25 +0000 Subject: SCI: cleanup svn-id: r49829 --- engines/sci/resource.cpp | 3 ++- engines/sci/resource_audio.cpp | 9 ++------- 2 files changed, 4 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 7d6835a336..df66fe0e38 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -351,7 +351,8 @@ Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res) { if (!fileStream) { warning("Failed to open %s", getLocationName().c_str()); - res->unalloc(); + if (res) + res->unalloc(); } return fileStream; diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 4f38fe15d1..472a9773ae 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -36,20 +36,15 @@ namespace Sci { AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum) : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { - ResourceManager *resMan = g_sci->getResMan(); - /* * Check if this audio volume got compressed by our tool. If that is the * case, set _audioCompressionType and read in the offset translation * table for later usage. */ - Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); - - if (!fileStream) { - warning("Failed to open %s", getLocationName().c_str()); + Common::SeekableReadStream *fileStream = getVolumeFile(0); + if (!fileStream) return; - } fileStream->seek(0, SEEK_SET); uint32 compressionType = fileStream->readUint32BE(); -- cgit v1.2.3 From 6667a7102738cda6e36e928bb7a9b4ca8f128e78 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:17:47 +0000 Subject: SCI: Move _audioCompression(Type|OffsetMapping) to AudioVolumeResourceSource svn-id: r49830 --- engines/sci/resource.cpp | 10 ++++++---- engines/sci/resource.h | 2 +- engines/sci/resource_audio.cpp | 3 +++ engines/sci/resource_intern.h | 11 +++++++++-- 4 files changed, 19 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index df66fe0e38..b37f89ae5b 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -163,8 +163,12 @@ void Resource::writeToStream(Common::WriteStream *stream) const { stream->write(data, size); } -uint32 Resource::getAudioCompressionType() { - return _source->_audioCompressionType; +uint32 Resource::getAudioCompressionType() const { + return _source->getAudioCompressionType(); +} + +uint32 AudioVolumeResourceSource::getAudioCompressionType() const { + return _audioCompressionType; } @@ -172,8 +176,6 @@ ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, i : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) { _scanned = false; _associatedMap = NULL; - _audioCompressionType = 0; - _audioCompressionOffsetMapping = NULL; } ResourceSource::~ResourceSource() { diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 0d76a4e4a9..db8a1c2a47 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -190,7 +190,7 @@ public: * This method is used only by the "dump" debugger command. */ void writeToStream(Common::WriteStream *stream) const; - uint32 getAudioCompressionType(); + uint32 getAudioCompressionType() const; protected: int32 _fileOffset; /**< Offset in file */ diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 472a9773ae..81ea99e17a 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -36,6 +36,9 @@ namespace Sci { AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum) : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { + _audioCompressionType = 0; + _audioCompressionOffsetMapping = NULL; + /* * Check if this audio volume got compressed by our tool. If that is the * case, set _audioCompressionType and read in the offset translation diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index ce5e3ac0e6..c58fc72ff2 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -57,8 +57,6 @@ public: const Common::FSNode * const _resourceFile; const int _volumeNumber; ResourceSource *_associatedMap; // TODO: Move to VolumeResourceSource - uint32 _audioCompressionType; // TODO: Move to AudioVolumeResourceSource - int32 *_audioCompressionOffsetMapping; // TODO: Move to AudioVolumeResourceSource protected: ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0); @@ -87,6 +85,9 @@ public: * Load a resource. */ virtual void loadResource(Resource *res); + + virtual uint32 getAudioCompressionType() const { return 0; } + }; class DirectoryResourceSource : public ResourceSource { @@ -141,10 +142,16 @@ public: }; class AudioVolumeResourceSource : public VolumeResourceSource { +protected: + uint32 _audioCompressionType; + int32 *_audioCompressionOffsetMapping; + public: AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum); virtual void loadResource(Resource *res); + + virtual uint32 getAudioCompressionType() const; }; class ExtAudioMapResourceSource : public ResourceSource { -- cgit v1.2.3 From b9a3a9c12d04ab0886cedc2dec81689d5458d4ca Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:18:07 +0000 Subject: SCI: Move _associatedMap to VolumeResourceSource and make it const svn-id: r49831 --- engines/sci/resource.cpp | 1 - engines/sci/resource_audio.cpp | 2 +- engines/sci/resource_intern.h | 10 +++++----- 3 files changed, 6 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index b37f89ae5b..df33ec6b89 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -175,7 +175,6 @@ uint32 AudioVolumeResourceSource::getAudioCompressionType() const { ResourceSource::ResourceSource(ResSourceType type, const Common::String &name, int volNum, const Common::FSNode *resFile) : _sourceType(type), _name(name), _volumeNumber(volNum), _resourceFile(resFile) { _scanned = false; - _associatedMap = NULL; } ResourceSource::~ResourceSource() { diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 81ea99e17a..4df2f6515b 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -417,7 +417,7 @@ void ResourceManager::setAudioLanguage(int language) { Common::List::iterator it = _sources.begin(); while (it != _sources.end()) { ResourceSource *src = *it; - if (src->_associatedMap == _audioMapSCI1) { + if (src->findVolume(_audioMapSCI1, src->_volumeNumber)) { it = _sources.erase(it); delete src; } else { diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index c58fc72ff2..209f3720b1 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -56,7 +56,6 @@ public: bool _scanned; const Common::FSNode * const _resourceFile; const int _volumeNumber; - ResourceSource *_associatedMap; // TODO: Move to VolumeResourceSource protected: ResourceSource(ResSourceType type, const Common::String &name, int volNum = 0, const Common::FSNode *resFile = 0); @@ -105,15 +104,16 @@ public: }; class VolumeResourceSource : public ResourceSource { +protected: + ResourceSource * const _associatedMap; + public: VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, ResSourceType type = kSourceVolume) - : ResourceSource(type, name, volNum) { - _associatedMap = map; + : ResourceSource(type, name, volNum), _associatedMap(map) { } VolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum, const Common::FSNode *resFile) - : ResourceSource(kSourceVolume, name, volNum, resFile) { - _associatedMap = map; + : ResourceSource(kSourceVolume, name, volNum, resFile), _associatedMap(map) { } virtual ResourceSource *findVolume(ResourceSource *map, int volNum) { -- cgit v1.2.3 From 63d9cfb3bf0eb252838ad30946fa8cf51921124b Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:18:31 +0000 Subject: SCI: Add ResourceManager::updateResource(); change some code to use addResource() svn-id: r49832 --- engines/sci/resource.cpp | 72 ++++++++++++++++++------------------------ engines/sci/resource.h | 1 + engines/sci/resource_audio.cpp | 19 ++--------- engines/sci/resource_intern.h | 6 ++-- 4 files changed, 38 insertions(+), 60 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index df33ec6b89..a57ae04847 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1134,20 +1134,12 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource return; } - // Prepare destination, if neccessary - if (_resMap.contains(resId) == false) { - newrsc = new Resource; - _resMap.setVal(resId, newrsc); - } else - newrsc = _resMap.getVal(resId); - // Overwrite everything, because we're patching - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = source; - newrsc->size = fsize - patchDataOffset - 2; + newrsc = updateResource(resId, source, fsize - patchDataOffset - 2); newrsc->_headerSize = patchDataOffset; newrsc->_fileOffset = 0; + + debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str()); } @@ -1285,7 +1277,6 @@ void ResourceManager::readResourcePatches(ResourceSource *source) { int ResourceManager::readResourceMapSCI0(ResourceSource *map) { Common::SeekableReadStream *fileStream = 0; - Resource *res; ResourceType type; uint16 number, id; uint32 offset; @@ -1323,9 +1314,8 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { ResourceId resId = ResourceId(type, number); // adding a new resource if (_resMap.contains(resId) == false) { - res = new Resource; - res->_source = findVolume(map, offset >> bShift); - if (!res->_source) { + ResourceSource *source = findVolume(map, offset >> bShift); + if (!source) { warning("Could not get volume for resource %d, VolumeID %d", id, offset >> bShift); if (_mapVersion != _volVersion) { warning("Retrying with the detected volume version instead"); @@ -1333,12 +1323,11 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { _mapVersion = _volVersion; bMask = (_mapVersion == kResVersionSci1Middle) ? 0xF0 : 0xFC; bShift = (_mapVersion == kResVersionSci1Middle) ? 28 : 26; - res->_source = findVolume(map, offset >> bShift); + source = findVolume(map, offset >> bShift); } } - res->_fileOffset = offset & (((~bMask) << 24) | 0xFFFFFF); - res->_id = resId; - _resMap.setVal(resId, res); + + addResource(resId, source, offset & (((~bMask) << 24) | 0xFFFFFF)); } } while (!fileStream->eos()); @@ -1348,7 +1337,6 @@ int ResourceManager::readResourceMapSCI0(ResourceSource *map) { int ResourceManager::readResourceMapSCI1(ResourceSource *map) { Common::SeekableReadStream *fileStream = 0; - Resource *res; if (map->_resourceFile) { fileStream = map->_resourceFile->createReadStream(); @@ -1409,16 +1397,11 @@ int ResourceManager::readResourceMapSCI1(ResourceSource *map) { resId = ResourceId((ResourceType)type, number); // adding new resource only if it does not exist if (_resMap.contains(resId) == false) { - res = new Resource; - _resMap.setVal(resId, res); - res->_id = resId; - // NOTE: We add the map's volume number here to the specified volume number // for SCI2.1 and SCI3 maps that are not resmap.000. The resmap.* files' numbers // need to be used in concurrence with the volume specified in the map to get // the actual resource file. - res->_source = findVolume(map, volume_nr + map->_volumeNumber); - res->_fileOffset = off; + addResource(resId, findVolume(map, volume_nr + map->_volumeNumber), off); } } } @@ -1494,21 +1477,8 @@ void MacResourceForkResourceSource::scanSource() { ResourceId resId = ResourceId(type, idArray[j]); - Resource *newrsc = NULL; - - // Prepare destination, if neccessary. Resource forks may contain patches. - if (!resMan->_resMap.contains(resId)) { - newrsc = new Resource; - resMan->_resMap.setVal(resId, newrsc); - } else - newrsc = resMan->_resMap.getVal(resId); - - // Overwrite everything - newrsc->_id = resId; - newrsc->_status = kResStatusNoMalloc; - newrsc->_source = this; - newrsc->size = fileSize; - newrsc->_headerSize = 0; + // Overwrite Resource instance. Resource forks may contain patches. + resMan->updateResource(resId, this, fileSize); } } } @@ -1525,6 +1495,26 @@ void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 } } +Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, uint32 size) { + // Update a patched resource, whether it exists or not + Resource *res = 0; + + if (_resMap.contains(resId)) { + res = _resMap.getVal(resId); + } else { + res = new Resource; + _resMap.setVal(resId, res); + } + + res->_id = resId; + res->_status = kResStatusNoMalloc; + res->_source = src; + res->_headerSize = 0; + res->size = size; + + return res; +} + int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes diff --git a/engines/sci/resource.h b/engines/sci/resource.h index db8a1c2a47..09d87eb9e3 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -395,6 +395,7 @@ protected: int decompress(Resource *res, Common::SeekableReadStream *file); int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0); + Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size); void removeAudioResource(ResourceId resId); /**--- Resource map decoding functions ---*/ diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 4df2f6515b..26ea96fb6c 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -170,24 +170,11 @@ void ResourceManager::addNewGMPatch(const Common::String &gameId) { void ResourceManager::processWavePatch(ResourceId resourceId, Common::String name) { ResourceSource *resSrc = new WaveResourceSource(name); + Common::File file; + file.open(name); - Resource *newRes = 0; - - if (_resMap.contains(resourceId)) { - newRes = _resMap.getVal(resourceId); - } else { - newRes = new Resource; - _resMap.setVal(resourceId, newRes); - } - - Common::SeekableReadStream *stream = SearchMan.createReadStreamForMember(name); - newRes->size = stream->size(); - delete stream; + updateResource(resourceId, resSrc, name.size()); - newRes->_id = resourceId; - newRes->_status = kResStatusNoMalloc; - newRes->_source = resSrc; - newRes->_headerSize = 0; debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str()); } diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 209f3720b1..042c5428d8 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -170,6 +170,9 @@ public: virtual void loadResource(Resource *res); }; +/** + * Reads SCI1.1+ resources from a Mac resource fork. + */ class MacResourceForkResourceSource : public ResourceSource { protected: Common::MacResManager *_macResMan; @@ -178,9 +181,6 @@ public: MacResourceForkResourceSource(const Common::String &name, int volNum); ~MacResourceForkResourceSource(); - /** - * Reads the SCI1.1+ resource file from a Mac resource fork. - */ virtual void scanSource(); virtual void loadResource(Resource *res); -- cgit v1.2.3 From 335e17af012590a68ae16ed60eff6fda221a1dce Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:18:57 +0000 Subject: SCI: Move several methods from ResourceManager to Resource svn-id: r49833 --- engines/sci/resource.cpp | 25 ++++++++++++------------- engines/sci/resource.h | 11 ++++++----- engines/sci/resource_audio.cpp | 16 +++++++++++----- 3 files changed, 29 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index a57ae04847..370a135a69 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -234,7 +234,9 @@ ResourceSource *ResourceManager::findVolume(ResourceSource *map, int volume_nr) // Resource manager constructors and operations -bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadPatch(Common::SeekableReadStream *file) { + Resource *res = this; + // We assume that the resource type matches res->type // We also assume that the current file position is right at the actual data (behind resourceid/headersize byte) @@ -262,17 +264,17 @@ bool ResourceManager::loadPatch(Resource *res, Common::SeekableReadStream *file) return true; } -bool ResourceManager::loadFromPatchFile(Resource *res) { +bool Resource::loadFromPatchFile() { Common::File file; - const Common::String &filename = res->_source->getLocationName(); + const Common::String &filename = _source->getLocationName(); if (file.open(filename) == false) { warning("Failed to open patch file %s", filename.c_str()); - res->unalloc(); + unalloc(); return false; } // Skip resourceid and header size byte file.seek(2, SEEK_SET); - return loadPatch(res, &file); + return loadPatch(&file); } Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *source) { @@ -321,8 +323,7 @@ void ResourceManager::loadResource(Resource *res) { void PatchResourceSource::loadResource(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); - bool result = resMan->loadFromPatchFile(res); + bool result = res->loadFromPatchFile(); if (!result) { // TODO: We used to fallback to the "default" code here if loadFromPatchFile // failed, but I am not sure whether that is really appropriate. @@ -360,19 +361,17 @@ Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res) { } void WaveResourceSource::loadResource(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; fileStream->seek(res->_fileOffset, SEEK_SET); - resMan->loadFromWaveFile(res, fileStream); + res->loadFromWaveFile(fileStream); if (_resourceFile) delete fileStream; } void AudioVolumeResourceSource::loadResource(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; @@ -410,7 +409,7 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { case kResourceTypeAudio: case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 - resMan->loadFromAudioVolumeSCI1(res, fileStream); + res->loadFromAudioVolumeSCI1(fileStream); if (_resourceFile) delete fileStream; return; @@ -422,9 +421,9 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { fileStream->seek(res->_fileOffset, SEEK_SET); } if (getSciVersion() < SCI_VERSION_1_1) - resMan->loadFromAudioVolumeSCI1(res, fileStream); + res->loadFromAudioVolumeSCI1(fileStream); else - resMan->loadFromAudioVolumeSCI11(res, fileStream); + res->loadFromAudioVolumeSCI11(fileStream); if (_resourceFile) delete fileStream; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 09d87eb9e3..85e03d3a4c 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -192,6 +192,12 @@ public: void writeToStream(Common::WriteStream *stream) const; uint32 getAudioCompressionType() const; + bool loadPatch(Common::SeekableReadStream *file); + bool loadFromPatchFile(); + bool loadFromWaveFile(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file); + protected: int32 _fileOffset; /**< Offset in file */ ResourceStatus _status; @@ -386,11 +392,6 @@ protected: Common::SeekableReadStream *getVolumeFile(ResourceSource *source); void loadResource(Resource *res); - bool loadPatch(Resource *res, Common::SeekableReadStream *file); - bool loadFromPatchFile(Resource *res); - bool loadFromWaveFile(Resource *res, Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file); void freeOldResources(); int decompress(Resource *res, Common::SeekableReadStream *file); int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 26ea96fb6c..1b90cdfb02 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -76,7 +76,9 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, delete fileStream; } -bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) { + Resource *res = this; + res->data = new byte[res->size]; uint32 really_read = file->read(res->data, res->size); @@ -87,14 +89,16 @@ bool ResourceManager::loadFromWaveFile(Resource *res, Common::SeekableReadStream return true; } -bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { + Resource *res = this; + // Check for WAVE files here uint32 riffTag = file->readUint32BE(); if (riffTag == MKID_BE('RIFF')) { res->_headerSize = 0; res->size = file->readUint32LE(); file->seek(-8, SEEK_CUR); - return loadFromWaveFile(res, file); + return loadFromWaveFile(file); } file->seek(-4, SEEK_CUR); @@ -122,10 +126,12 @@ bool ResourceManager::loadFromAudioVolumeSCI11(Resource *res, Common::SeekableRe file->seek(-11, SEEK_CUR); } - return loadPatch(res, file); + return loadPatch(file); } -bool ResourceManager::loadFromAudioVolumeSCI1(Resource *res, Common::SeekableReadStream *file) { +bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) { + Resource *res = this; + res->data = new byte[res->size]; if (res->data == NULL) { -- cgit v1.2.3 From 4392cdaee19b626058144b0fc309c1a6ea09cd79 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:19:14 +0000 Subject: SCI: cleanup svn-id: r49834 --- engines/sci/resource.cpp | 5 +++-- engines/sci/resource_audio.cpp | 50 +++++++++++++++++++----------------------- 2 files changed, 25 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 370a135a69..2833a00c76 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -333,12 +333,12 @@ void PatchResourceSource::loadResource(Resource *res) { } void MacResourceForkResourceSource::loadResource(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); if (!stream) error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); + ResourceManager *resMan = g_sci->getResMan(); int error = resMan->decompress(res, stream); if (error) { warning("Error %d occured while reading %s from Mac resource file: %s", @@ -430,12 +430,13 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { } void ResourceSource::loadResource(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); Common::SeekableReadStream *fileStream = getVolumeFile(res); if (!fileStream) return; fileStream->seek(res->_fileOffset, SEEK_SET); + + ResourceManager *resMan = g_sci->getResMan(); int error = resMan->decompress(res, fileStream); if (_resourceFile) diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 1b90cdfb02..7daaa0f979 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -77,51 +77,47 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, } bool Resource::loadFromWaveFile(Common::SeekableReadStream *file) { - Resource *res = this; + data = new byte[size]; - res->data = new byte[res->size]; + uint32 really_read = file->read(data, size); + if (really_read != size) + error("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size); - uint32 really_read = file->read(res->data, res->size); - if (really_read != res->size) - error("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); - - res->_status = kResStatusAllocated; + _status = kResStatusAllocated; return true; } bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { - Resource *res = this; - // Check for WAVE files here uint32 riffTag = file->readUint32BE(); if (riffTag == MKID_BE('RIFF')) { - res->_headerSize = 0; - res->size = file->readUint32LE(); + _headerSize = 0; + size = file->readUint32LE(); file->seek(-8, SEEK_CUR); return loadFromWaveFile(file); } file->seek(-4, SEEK_CUR); ResourceType type = (ResourceType)(file->readByte() & 0x7f); - if (((res->_id.type == kResourceTypeAudio || res->_id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) - || ((res->_id.type == kResourceTypeSync || res->_id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { - warning("Resource type mismatch loading %s", res->_id.toString().c_str()); - res->unalloc(); + if (((_id.type == kResourceTypeAudio || _id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) + || ((_id.type == kResourceTypeSync || _id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { + warning("Resource type mismatch loading %s", _id.toString().c_str()); + unalloc(); return false; } - res->_headerSize = file->readByte(); + _headerSize = file->readByte(); if (type == kResourceTypeAudio) { - if (res->_headerSize != 11 && res->_headerSize != 12) { + if (_headerSize != 11 && _headerSize != 12) { warning("Unsupported audio header"); - res->unalloc(); + unalloc(); return false; } // Load sample size file->seek(7, SEEK_CUR); - res->size = file->readUint32LE(); + size = file->readUint32LE(); // Adjust offset to point at the header data again file->seek(-11, SEEK_CUR); } @@ -130,19 +126,17 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { } bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) { - Resource *res = this; - - res->data = new byte[res->size]; + data = new byte[size]; - if (res->data == NULL) { - error("Can't allocate %d bytes needed for loading %s", res->size, res->_id.toString().c_str()); + if (data == NULL) { + error("Can't allocate %d bytes needed for loading %s", size, _id.toString().c_str()); } - unsigned int really_read = file->read(res->data, res->size); - if (really_read != res->size) - warning("Read %d bytes from %s but expected %d", really_read, res->_id.toString().c_str(), res->size); + unsigned int really_read = file->read(data, size); + if (really_read != size) + warning("Read %d bytes from %s but expected %d", really_read, _id.toString().c_str(), size); - res->_status = kResStatusAllocated; + _status = kResStatusAllocated; return true; } -- cgit v1.2.3 From 583a966d8c91250284ebe3fd84fce4e0ed12ae13 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:19:39 +0000 Subject: SCI: Move decompress & readResourceInfo to Resource; more cleanup svn-id: r49835 --- engines/sci/resource.cpp | 51 +++++++++++++++++++++--------------------- engines/sci/resource.h | 42 +++++++++++++++++----------------- engines/sci/resource_audio.cpp | 4 ++-- 3 files changed, 49 insertions(+), 48 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 2833a00c76..ee32458748 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -338,8 +338,7 @@ void MacResourceForkResourceSource::loadResource(Resource *res) { if (!stream) error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); - ResourceManager *resMan = g_sci->getResMan(); - int error = resMan->decompress(res, stream); + int error = res->decompress(stream); if (error) { warning("Error %d occured while reading %s from Mac resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -436,8 +435,7 @@ void ResourceSource::loadResource(Resource *res) { fileStream->seek(res->_fileOffset, SEEK_SET); - ResourceManager *resMan = g_sci->getResMan(); - int error = resMan->decompress(res, fileStream); + int error = res->decompress(fileStream); if (_resourceFile) delete fileStream; @@ -631,18 +629,18 @@ void ResourceManager::scanNewSources() { void DirectoryResourceSource::scanSource() { ResourceManager *resMan = g_sci->getResMan(); - resMan->readResourcePatches(this); + resMan->readResourcePatches(); // We can't use getSciVersion() at this point, thus using _volVersion - if (resMan->_volVersion >= ResourceManager::kResVersionSci11) // SCI1.1+ - resMan->readResourcePatchesBase36(this); + if (resMan->_volVersion >= kResVersionSci11) // SCI1.1+ + resMan->readResourcePatchesBase36(); resMan->readWaveAudioPatches(); } void ExtMapResourceSource::scanSource() { ResourceManager *resMan = g_sci->getResMan(); - if (resMan->_mapVersion < ResourceManager::kResVersionSci1Late) + if (resMan->_mapVersion < kResVersionSci1Late) resMan->readResourceMapSCI0(this); else resMan->readResourceMapSCI1(this); @@ -881,7 +879,7 @@ const char *ResourceManager::versionDescription(ResVersion version) const { return "Version not valid"; } -ResourceManager::ResVersion ResourceManager::detectMapVersion() { +ResVersion ResourceManager::detectMapVersion() { Common::SeekableReadStream *fileStream = 0; byte buff[6]; ResourceSource *rsrc= 0; @@ -971,7 +969,7 @@ ResourceManager::ResVersion ResourceManager::detectMapVersion() { return kResVersionUnknown; } -ResourceManager::ResVersion ResourceManager::detectVolVersion() { +ResVersion ResourceManager::detectVolVersion() { Common::SeekableReadStream *fileStream = 0; ResourceSource *rsrc; @@ -1143,7 +1141,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource debugC(1, kDebugLevelResMan, "Patching %s - OK", source->getLocationName().c_str()); } -void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { +void ResourceManager::readResourcePatchesBase36() { // The base36 encoded audio36 and sync36 resources use a different naming scheme, because they // cannot be described with a single resource number, but are a result of a // tuple. Please don't be confused with the normal audio patches @@ -1227,7 +1225,7 @@ void ResourceManager::readResourcePatchesBase36(ResourceSource *source) { } } -void ResourceManager::readResourcePatches(ResourceSource *source) { +void ResourceManager::readResourcePatches() { // Note: since some SCI1 games(KQ5 floppy, SQ4) might use SCI0 naming scheme for patch files // this function tries to read patch file with any supported naming scheme, // regardless of s_sciVersion value @@ -1515,7 +1513,7 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, return res; } -int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream *file, +int Resource::readResourceInfo(Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes @@ -1525,7 +1523,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream uint32 wCompression, szUnpacked; ResourceType type; - switch (_volVersion) { + ResourceManager *resMan = g_sci->getResMan(); + switch (resMan->_volVersion) { case kResVersionSci0Sci1Early: case kResVersionSci1Middle: w = file->readUint16LE(); @@ -1552,8 +1551,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream case kResVersionSci11Mac: // Doesn't store this data in the resource. Fortunately, // we already have this data. - type = res->_id.type; - number = res->_id.number; + type = _id.type; + number = _id.number; szPacked = file->size(); szUnpacked = file->size(); wCompression = 0; @@ -1575,8 +1574,8 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream if ((file->eos() || file->err())) return SCI_ERROR_IO_ERROR; - res->_id = ResourceId(type, number); - res->size = szUnpacked; + _id = ResourceId(type, number); + size = szUnpacked; // checking compression method switch (wCompression) { @@ -1612,13 +1611,13 @@ int ResourceManager::readResourceInfo(Resource *res, Common::SeekableReadStream return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0; } -int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) { +int Resource::decompress(Common::SeekableReadStream *file) { int error; uint32 szPacked = 0; ResourceCompression compression = kCompUnknown; // fill resource info - error = readResourceInfo(res, file, szPacked, compression); + error = readResourceInfo(file, szPacked, compression); if (error) return error; @@ -1646,15 +1645,15 @@ int ResourceManager::decompress(Resource *res, Common::SeekableReadStream *file) break; #endif default: - warning("Resource %s: Compression method %d not supported", res->_id.toString().c_str(), compression); + warning("Resource %s: Compression method %d not supported", _id.toString().c_str(), compression); return SCI_ERROR_UNKNOWN_COMPRESSION; } - res->data = new byte[res->size]; - res->_status = kResStatusAllocated; - error = res->data ? dec->unpack(file, res->data, szPacked, res->size) : SCI_ERROR_RESOURCE_TOO_BIG; + data = new byte[size]; + _status = kResStatusAllocated; + error = data ? dec->unpack(file, data, szPacked, size) : SCI_ERROR_RESOURCE_TOO_BIG; if (error) - res->unalloc(); + unalloc(); delete dec; return error; @@ -1683,7 +1682,7 @@ ResourceCompression ResourceManager::getViewCompression() { uint32 szPacked; ResourceCompression compression; - if (readResourceInfo(res, fileStream, szPacked, compression)) { + if (res->readResourceInfo(fileStream, szPacked, compression)) { if (res->_source->_resourceFile) delete fileStream; continue; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 85e03d3a4c..53cf2ddb47 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -167,6 +167,7 @@ class Resource { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. friend class ResourceSource; + friend class PatchResourceSource; friend class WaveResourceSource; friend class AudioVolumeResourceSource; friend class MacResourceForkResourceSource; @@ -192,24 +193,37 @@ public: void writeToStream(Common::WriteStream *stream) const; uint32 getAudioCompressionType() const; - bool loadPatch(Common::SeekableReadStream *file); - bool loadFromPatchFile(); - bool loadFromWaveFile(Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file); - bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file); - protected: int32 _fileOffset; /**< Offset in file */ ResourceStatus _status; uint16 _lockers; /**< Number of places where this resource was locked */ ResourceSource *_source; + + bool loadPatch(Common::SeekableReadStream *file); + bool loadFromPatchFile(); + bool loadFromWaveFile(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file); + bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file); + int decompress(Common::SeekableReadStream *file); + int readResourceInfo(Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); }; typedef Common::HashMap ResourceMap; +enum ResVersion { + kResVersionUnknown, + kResVersionSci0Sci1Early, + kResVersionSci1Middle, + kResVersionSci1Late, + kResVersionSci11, + kResVersionSci11Mac, + kResVersionSci32 +}; + class ResourceManager { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. + friend class Resource; // For _volVersion friend class ResourceSource; friend class DirectoryResourceSource; friend class PatchResourceSource; @@ -221,16 +235,6 @@ class ResourceManager { friend class MacResourceForkResourceSource; public: - enum ResVersion { - kResVersionUnknown, - kResVersionSci0Sci1Early, - kResVersionSci1Middle, - kResVersionSci1Late, - kResVersionSci11, - kResVersionSci11Mac, - kResVersionSci32 - }; - /** * Creates a new SCI resource manager. */ @@ -393,8 +397,6 @@ protected: Common::SeekableReadStream *getVolumeFile(ResourceSource *source); void loadResource(Resource *res); void freeOldResources(); - int decompress(Resource *res, Common::SeekableReadStream *file); - int readResourceInfo(Resource *res, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); void addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size = 0); Resource *updateResource(ResourceId resId, ResourceSource *src, uint32 size); void removeAudioResource(ResourceId resId); @@ -437,8 +439,8 @@ protected: /** * Reads patch files from a local directory. */ - void readResourcePatches(ResourceSource *source); - void readResourcePatchesBase36(ResourceSource *source); + void readResourcePatches(); + void readResourcePatchesBase36(); void processPatch(ResourceSource *source, ResourceType resourceType, uint16 resourceNr, uint32 tuple = 0); /** diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 7daaa0f979..eba14d4d5e 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -319,8 +319,8 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { } if (n & 0x40) { - // This seems to define the size of raw lipsync data (at least in kq6), may also just be general appended - // data + // This seems to define the size of raw lipsync data (at least + // in kq6), may also just be general appended data. syncSize += READ_LE_UINT16(ptr); ptr += 2; } -- cgit v1.2.3 From 79c9be5d96ca58a20afa61b4b26e28839dfb925e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:20:03 +0000 Subject: Reduce header dependencies svn-id: r49836 --- engines/sci/graphics/portrait.cpp | 1 + engines/sci/resource.cpp | 1 + engines/sci/resource.h | 7 ++++++- engines/sci/resource_audio.cpp | 1 + 4 files changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 1b4e4bde77..b912bf552e 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -23,6 +23,7 @@ * */ +#include "common/archive.h" #include "common/util.h" #include "common/stack.h" #include "graphics/primitives.h" diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index ee32458748..fb601c7f82 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -26,6 +26,7 @@ // Resource library #include "common/file.h" +#include "common/fs.h" #include "common/macresman.h" #include "sci/resource.h" diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 53cf2ddb47..0fd256633f 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -26,8 +26,9 @@ #ifndef SCI_RESOURCE_H #define SCI_RESOURCE_H -#include "common/fs.h" #include "common/str.h" +#include "common/list.h" +#include "common/hashmap.h" #include "sci/graphics/helpers.h" // for ViewType #include "sci/decompressor.h" @@ -35,6 +36,10 @@ namespace Common { class File; +class FSList; +class FSNode; +class WriteStream; +class SeekableReadStream; } namespace Sci { diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index eba14d4d5e..9cd3f32561 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -25,6 +25,7 @@ // Resource library +#include "common/archive.h" #include "common/file.h" #include "sci/resource.h" -- cgit v1.2.3 From 96f1e293009a7fe1291ed0f7c1255f9010b75098 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:20:24 +0000 Subject: cleanup svn-id: r49837 --- engines/sci/resource.h | 10 +--------- 1 file changed, 1 insertion(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 0fd256633f..4b391cf6cd 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -365,7 +365,7 @@ protected: /** * Add an external (i.e., separate file) map resource to the resource * manager's list of sources. - * @param file_name The name of the volume to add + * @param filename The name of the volume to add * @param volume_nr The volume number the map starts at, 0 for _segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); g_sci->_gfxCompare = _compare; _transitions = new GfxTransitions(this, _screen, _palette, g_sci->getResMan()->isVGA()); - _paint16 = new GfxPaint16(g_sci->getResMan(), _s->_segMan, g_sci->getKernel(), this, _cache, _ports, _coordAdjuster, _screen, _palette, _transitions); + _paint16 = new GfxPaint16(g_sci->getResMan(), _s->_segMan, g_sci->getKernel(), this, _cache, _ports, _coordAdjuster, _screen, _palette, _transitions, _audio); g_sci->_gfxPaint = _paint16; g_sci->_gfxPaint16 = _paint16; _animate = new GfxAnimate(_s, _cache, _ports, _paint16, _screen, _palette, _cursor, _transitions); diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index eb3fea969a..10eae3c618 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -48,8 +48,8 @@ namespace Sci { -GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions) - : _resMan(resMan), _segMan(segMan), _kernel(kernel), _gui(gui), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions) { +GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) + : _resMan(resMan), _segMan(segMan), _kernel(kernel), _gui(gui), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio) { } GfxPaint16::~GfxPaint16() { @@ -587,7 +587,7 @@ reg_t GfxPaint16::kernelPortraitLoad(Common::String resourceName) { } void GfxPaint16::kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { - Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), this, _screen, _palette, _audio, resourceName); + Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _gui, _screen, _palette, _audio, resourceName); // TODO: cache portraits // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates // on kDrawCel, yeah this whole stuff makes sense) diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 7a1a3bd7eb..3b2ffd6fc2 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -45,7 +45,7 @@ class GfxView; */ class GfxPaint16 : public GfxPaint { public: - GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions); + GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); ~GfxPaint16(); void init(GfxAnimate *animate, GfxText16 *text16); @@ -99,6 +99,7 @@ private: ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; + AudioPlayer *_audio; SciGui *_gui; GfxAnimate *_animate; GfxCache *_cache; -- cgit v1.2.3 From 68eeef8f1aa560954297291887f26bad6591aa15 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:21:29 +0000 Subject: SCI: Add ResourceManager::getVolVersion() svn-id: r49840 --- engines/sci/resource.cpp | 2 +- engines/sci/resource.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index fb601c7f82..80b3108988 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1525,7 +1525,7 @@ int Resource::readResourceInfo(Common::SeekableReadStream *file, ResourceType type; ResourceManager *resMan = g_sci->getResMan(); - switch (resMan->_volVersion) { + switch (resMan->getVolVersion()) { case kResVersionSci0Sci1Early: case kResVersionSci1Middle: w = file->readUint16LE(); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 4b391cf6cd..d2dff8f58d 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -228,7 +228,6 @@ enum ResVersion { class ResourceManager { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. - friend class Resource; // For _volVersion friend class ResourceSource; friend class DirectoryResourceSource; friend class PatchResourceSource; @@ -301,6 +300,7 @@ public: ViewType getViewType() const { return _viewType; } const char *getMapVersionDesc() const { return versionDescription(_mapVersion); } const char *getVolVersionDesc() const { return versionDescription(_volVersion); } + ResVersion getVolVersion() const { return _volVersion; } /** * Adds the appropriate GM patch from the Sierra MIDI utility as 4.pat, without -- cgit v1.2.3 From 2b24a1a2adcd112a6f3d878c9172ec570a6077d9 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:31:16 +0000 Subject: SCI: OOpify class ResourceId svn-id: r49841 --- engines/sci/console.cpp | 32 ++++++++++---------- engines/sci/engine/kscripts.cpp | 4 +-- engines/sci/resource.cpp | 22 +++++++------- engines/sci/resource.h | 67 +++++++++++++++++++++++------------------ engines/sci/resource_audio.cpp | 4 +-- 5 files changed, 69 insertions(+), 60 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 1c6f4461a8..4c8d588fa0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -824,7 +824,7 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { } Common::List *resources = _engine->getResMan()->listResources(kResourceTypeScript); - sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::sort(resources->begin(), resources->end()); Common::List::iterator itr = resources->begin(); DebugPrintf("%d SCI1.1-SCI2.1 scripts found, performing sanity checks...\n", resources->size()); @@ -833,15 +833,15 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { while (itr != resources->end()) { script = _engine->getResMan()->findResource(*itr, false); if (!script) - DebugPrintf("Error: script %d couldn't be loaded\n", itr->number); + DebugPrintf("Error: script %d couldn't be loaded\n", itr->getNumber()); - heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->number), false); + heap = _engine->getResMan()->findResource(ResourceId(kResourceTypeHeap, itr->getNumber()), false); if (!heap) - DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->number); + DebugPrintf("Error: script %d doesn't have a corresponding heap\n", itr->getNumber()); if (script && heap && (script->size + heap->size > 65535)) DebugPrintf("Error: script and heap %d together are larger than 64KB (%d bytes)\n", - itr->number, script->size + heap->size); + itr->getNumber(), script->size + heap->size); ++itr; } @@ -864,7 +864,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { parser->setMidiDriver(player); Common::List *resources = _engine->getResMan()->listResources(kResourceTypeSound); - sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::sort(resources->begin(), resources->end()); Common::List::iterator itr = resources->begin(); int instruments[128]; bool instrumentsSongs[128][1000]; @@ -885,12 +885,12 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { SoundResource *sound; while (itr != resources->end()) { - if (songNumber >= 0 && itr->number != songNumber) { + if (songNumber >= 0 && itr->getNumber() != songNumber) { ++itr; continue; } - sound = new SoundResource(itr->number, _engine->getResMan(), doSoundVersion); + sound = new SoundResource(itr->getNumber(), _engine->getResMan(), doSoundVersion); int channelFilterMask = sound->getChannelFilterMask(player->getPlayId(), player->hasRhythmChannel()); SoundResource::Track *track = sound->getTrackByType(player->getPlayId()); if (track->digitalChannelNr != -1) { @@ -907,7 +907,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { bool endOfTrack = false; bool firstOneShown = false; - DebugPrintf("Song %d: ", itr->number); + DebugPrintf("Song %d: ", itr->getNumber()); do { while (*channelData == 0xF8) @@ -937,7 +937,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { DebugPrintf(" %d", instrument); instruments[instrument]++; - instrumentsSongs[instrument][itr->number] = true; + instrumentsSongs[instrument][itr->getNumber()] = true; } break; case 0xD: @@ -1035,19 +1035,19 @@ bool Console::cmdList(int argc, const char **argv) { } Common::List *resources = _engine->getResMan()->listResources(res, number); - sort(resources->begin(), resources->end(), ResourceIdLess()); + Common::sort(resources->begin(), resources->end()); Common::List::iterator itr = resources->begin(); int cnt = 0; while (itr != resources->end()) { if (number == -1) { - DebugPrintf("%8i", itr->number); + DebugPrintf("%8i", itr->getNumber()); if (++cnt % 10 == 0) DebugPrintf("\n"); - } - else if (number == (int)itr->number) { - DebugPrintf("(%3i, %3i, %3i, %3i) ", (itr->tuple >> 24) & 0xff, (itr->tuple >> 16) & 0xff, - (itr->tuple >> 8) & 0xff, itr->tuple & 0xff); + } else if (number == (int)itr->getNumber()) { + const uint32 tuple = itr->getTuple(); + DebugPrintf("(%3i, %3i, %3i, %3i) ", (tuple >> 24) & 0xff, (tuple >> 16) & 0xff, + (tuple >> 8) & 0xff, tuple & 0xff); if (++cnt % 4 == 0) DebugPrintf("\n"); } diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index c6d73556ba..a8cf92b2a6 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -61,8 +61,8 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { if (which) g_sci->getResMan()->unlockResource(which); else { - if (id.type == kResourceTypeInvalid) - warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.number, type); + if (id.getType() == kResourceTypeInvalid) + warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type); else warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); } diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 80b3108988..00da600b26 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -157,7 +157,7 @@ void Resource::unalloc() { } void Resource::writeToStream(Common::WriteStream *stream) const { - stream->writeByte(_id.type | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file + stream->writeByte(getType() | 0x80); // 0x80 is required by old sierra sci, otherwise it wont accept the patch file stream->writeByte(_headerSize); if (_headerSize > 0) stream->write(_header, _headerSize); @@ -334,10 +334,10 @@ void PatchResourceSource::loadResource(Resource *res) { } void MacResourceForkResourceSource::loadResource(Resource *res) { - Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->_id.type), res->_id.number); + Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->_id.getNumber()); if (!stream) - error("Could not get Mac resource fork resource: %d %d", res->_id.type, res->_id.number); + error("Could not get Mac resource fork resource: %d %d", res->getType(), res->_id.getNumber()); int error = res->decompress(stream); if (error) { @@ -387,7 +387,7 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { mappingTable++; compressedOffset = *mappingTable; // Go to next compressed offset and use that to calculate size of compressed sample - switch (res->_id.type) { + switch (res->getType()) { case kResourceTypeSync: case kResourceTypeSync36: // we should already have a (valid) size @@ -405,7 +405,7 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { error("could not translate offset to compressed offset in audio volume"); fileStream->seek(compressedOffset, SEEK_SET); - switch (res->_id.type) { + switch (res->getType()) { case kResourceTypeAudio: case kResourceTypeAudio36: // Directly read the stream, compressed audio wont have resource type id and header size for SCI1.1 @@ -604,9 +604,9 @@ int ResourceManager::addInternalSources() { Common::List::iterator itr = resources->begin(); while (itr != resources->end()) { - ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->number)); + ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber())); - if ((itr->number == 65535) && Common::File::exists("RESOURCE.SFX")) + if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX")) addSource(new AudioVolumeResourceSource("RESOURCE.SFX", src, 0)); else if (Common::File::exists("RESOURCE.AUD")) addSource(new AudioVolumeResourceSource("RESOURCE.AUD", src, 0)); @@ -799,7 +799,7 @@ Common::List *ResourceManager::listResources(ResourceType type, int ResourceMap::iterator itr = _resMap.begin(); while (itr != _resMap.end()) { - if ((itr->_value->_id.type == type) && ((mapNumber == -1) || (itr->_value->_id.number == mapNumber))) + if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->_id.getNumber() == mapNumber))) resources->push_back(itr->_value->_id); ++itr; } @@ -1220,7 +1220,7 @@ void ResourceManager::readResourcePatchesBase36() { } psrcPatch = new PatchResourceSource(name); - processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.tuple); + processPatch(psrcPatch, (ResourceType)i, resourceNr, resource36.getTuple()); } } } @@ -1552,8 +1552,8 @@ int Resource::readResourceInfo(Common::SeekableReadStream *file, case kResVersionSci11Mac: // Doesn't store this data in the resource. Fortunately, // we already have this data. - type = _id.type; - number = _id.number; + type = getType(); + number = _id.getNumber(); szPacked = file->size(); szUnpacked = file->size(); wCompression = 0; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index d2dff8f58d..e030db4bc4 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -114,57 +114,64 @@ class ResourceManager; class ResourceSource; class ResourceId { -public: - ResourceType type; - uint16 number; - uint32 tuple; // Only used for audio36 and sync36 + static inline ResourceType fixupType(ResourceType type) { + if (type < kResourceTypeMacPict || type > kResourceTypeInvalid) + return kResourceTypeInvalid; + return type; + } - ResourceId() : type(kResourceTypeInvalid), number(0), tuple(0) { } + ResourceType _type; + uint16 _number; + uint32 _tuple; // Only used for audio36 and sync36 + +public: + ResourceId() : _type(kResourceTypeInvalid), _number(0), _tuple(0) { } ResourceId(ResourceType type_, uint16 number_, uint32 tuple_ = 0) - : type(type_), number(number_), tuple(tuple_) { - if (type < kResourceTypeMacPict || type > kResourceTypeInvalid) - type = kResourceTypeInvalid; + : _type(fixupType(type_)), _number(number_), _tuple(tuple_) { } ResourceId(ResourceType type_, uint16 number_, byte noun, byte verb, byte cond, byte seq) - : type(type_), number(number_) { - tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq; - - if ((type < kResourceTypeView) || (type > kResourceTypeInvalid)) - type = kResourceTypeInvalid; + : _type(fixupType(type_)), _number(number_) { + _tuple = (noun << 24) | (verb << 16) | (cond << 8) | seq; } - Common::String toString() { + Common::String toString() const { char buf[32]; - snprintf(buf, 32, "%s.%i", getResourceTypeName(type), number); + snprintf(buf, 32, "%s.%i", getResourceTypeName(_type), _number); Common::String retStr = buf; - if (tuple != 0) { - snprintf(buf, 32, "(%i, %i, %i, %i)", tuple >> 24, (tuple >> 16) & 0xff, (tuple >> 8) & 0xff, tuple & 0xff); + if (_tuple != 0) { + snprintf(buf, 32, "(%i, %i, %i, %i)", _tuple >> 24, (_tuple >> 16) & 0xff, (_tuple >> 8) & 0xff, _tuple & 0xff); retStr += buf; } return retStr; } -}; -struct ResourceIdHash : public Common::UnaryFunction { - uint operator()(ResourceId val) const { return ((uint)((val.type << 16) | val.number)) ^ val.tuple; } -}; + inline ResourceType getType() const { return _type; } + inline uint16 getNumber() const { return _number; } + inline uint32 getTuple() const { return _tuple; } -struct ResourceIdEqualTo : public Common::BinaryFunction { - bool operator()(const ResourceId &x, const ResourceId &y) const { return (x.type == y.type) && (x.number == y.number) && (x.tuple == y.tuple); } -}; + inline uint hash() const { + return ((uint)((_type << 16) | _number)) ^ _tuple; + } + + bool operator==(const ResourceId &other) const { + return (_type == other._type) && (_number == other._number) && (_tuple == other._tuple); + } -struct ResourceIdLess : public Common::BinaryFunction { - bool operator()(const ResourceId &x, const ResourceId &y) const { - return (x.type < y.type) || ((x.type == y.type) && (x.number < y.number)) - || ((x.type == y.type) && (x.number == y.number) && (x.tuple < y.tuple)); + bool operator<(const ResourceId &other) const { + return (_type < other._type) || ((_type == other._type) && (_number < other._number)) + || ((_type == other._type) && (_number == other._number) && (_tuple < other._tuple)); } }; +struct ResourceIdHash : public Common::UnaryFunction { + uint operator()(ResourceId val) const { return val.hash(); } +}; + /** Class for storing resources in memory */ class Resource { friend class ResourceManager; @@ -191,6 +198,8 @@ public: byte *_header; uint32 _headerSize; + inline ResourceType getType() const { return _id.getType(); } + /** * Write the resource to the specified stream. * This method is used only by the "dump" debugger command. @@ -213,7 +222,7 @@ protected: int readResourceInfo(Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); }; -typedef Common::HashMap ResourceMap; +typedef Common::HashMap ResourceMap; enum ResVersion { kResVersionUnknown, diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 9cd3f32561..7a0d9bac6e 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -100,8 +100,8 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { file->seek(-4, SEEK_CUR); ResourceType type = (ResourceType)(file->readByte() & 0x7f); - if (((_id.type == kResourceTypeAudio || _id.type == kResourceTypeAudio36) && (type != kResourceTypeAudio)) - || ((_id.type == kResourceTypeSync || _id.type == kResourceTypeSync36) && (type != kResourceTypeSync))) { + if (((getType() == kResourceTypeAudio || getType() == kResourceTypeAudio36) && (type != kResourceTypeAudio)) + || ((getType() == kResourceTypeSync || getType() == kResourceTypeSync36) && (type != kResourceTypeSync))) { warning("Resource type mismatch loading %s", _id.toString().c_str()); unalloc(); return false; -- cgit v1.2.3 From 7a5ce0eddd01d29d14543679aef8892e08829a63 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:31:37 +0000 Subject: SCI: Make Resource::_id protected svn-id: r49842 --- engines/sci/resource.cpp | 8 +++----- engines/sci/resource.h | 16 ++++++++-------- 2 files changed, 11 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 00da600b26..e23d8fd080 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -133,7 +133,7 @@ const char *getResourceTypeName(ResourceType restype) { } //-- Resource main functions -- -Resource::Resource() { +Resource::Resource(ResourceId id) : _id(id) { data = NULL; size = 0; _fileOffset = 0; @@ -1485,9 +1485,8 @@ void MacResourceForkResourceSource::scanSource() { void ResourceManager::addResource(ResourceId resId, ResourceSource *src, uint32 offset, uint32 size) { // Adding new resource only if it does not exist if (_resMap.contains(resId) == false) { - Resource *res = new Resource; + Resource *res = new Resource(resId); _resMap.setVal(resId, res); - res->_id = resId; res->_source = src; res->_fileOffset = offset; res->size = size; @@ -1501,11 +1500,10 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, if (_resMap.contains(resId)) { res = _resMap.getVal(resId); } else { - res = new Resource; + res = new Resource(resId); _resMap.setVal(resId, res); } - res->_id = resId; res->_status = kResStatusNoMalloc; res->_source = src; res->_headerSize = 0; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index e030db4bc4..43408b0ffe 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -184,20 +184,19 @@ class Resource { friend class AudioVolumeResourceSource; friend class MacResourceForkResourceSource; +// NOTE : Currently most member variables lack the underscore prefix and have +// public visibility to let the rest of the engine compile without changes. public: - Resource(); - ~Resource(); - void unalloc(); - -// NOTE : Currently all member data has the same name and public visibility -// to let the rest of the engine compile without changes -public: - ResourceId _id; byte *data; uint32 size; byte *_header; uint32 _headerSize; +public: + Resource(ResourceId id); + ~Resource(); + void unalloc(); + inline ResourceType getType() const { return _id.getType(); } /** @@ -208,6 +207,7 @@ public: uint32 getAudioCompressionType() const; protected: + ResourceId _id; // TODO: _id could almost be made const, only readResourceInfo() modifies it... int32 _fileOffset; /**< Offset in file */ ResourceStatus _status; uint16 _lockers; /**< Number of places where this resource was locked */ -- cgit v1.2.3 From 651e2760a3b2de0c542ccbbf1bf3caa319cc0349 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:33:20 +0000 Subject: Fix spelling, cleanup svn-id: r49843 --- engines/agi/keyboard.cpp | 2 +- engines/agos/icons.cpp | 2 +- engines/agos/vga_s2.cpp | 2 +- engines/saga/saga.cpp | 2 +- engines/sci/engine/kevent.cpp | 4 ++-- engines/sci/engine/seg_manager.h | 2 +- engines/sci/resource.cpp | 6 +++--- engines/sci/sci.h | 2 +- engines/scumm/verbs.h | 2 +- 9 files changed, 12 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/agi/keyboard.cpp b/engines/agi/keyboard.cpp index f99d5728be..62bcd5d8d8 100644 --- a/engines/agi/keyboard.cpp +++ b/engines/agi/keyboard.cpp @@ -121,7 +121,7 @@ int AgiEngine::handleController(int key) { if (_game.controllers[i].keycode == key) { debugC(3, kDebugLevelInput, "event %d: key press", _game.controllers[i].controller); _game.controllerOccured[_game.controllers[i].controller] = true; - report("event AC:%i occured\n", _game.controllers[i].controller); + report("event AC:%i occurred\n", _game.controllers[i].controller); return true; } } diff --git a/engines/agos/icons.cpp b/engines/agos/icons.cpp index fdc5d1707e..08a3d4e2f0 100644 --- a/engines/agos/icons.cpp +++ b/engines/agos/icons.cpp @@ -448,7 +448,7 @@ void AGOSEngine_Feeble::drawIconArray(uint num, Item *itemRef, int line, int cla setupIconHitArea(window, k++, xp, yp, itemRef); } else { /* - * Just remember the overflow has occured + * Just remember the overflow has occurred */ window->iconPtr->iconArray[icount].item = NULL; /* END MARKINGS */ _iOverflow = 1; diff --git a/engines/agos/vga_s2.cpp b/engines/agos/vga_s2.cpp index 4eb739e974..db3a7c18f3 100644 --- a/engines/agos/vga_s2.cpp +++ b/engines/agos/vga_s2.cpp @@ -138,7 +138,7 @@ void AGOSEngine::vc69_playSeq() { // This is a "play track". The original // design stored the track to play if one was // already in progress, so that the next time a - // "fill MIDI stream" event occured, the MIDI + // "fill MIDI stream" event occurred, the MIDI // player would find the change and switch // tracks. We use a different architecture that // allows for an immediate response here, but diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index 446ab86228..d1ab3bc9d7 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -419,7 +419,7 @@ void SagaEngine::loadStrings(StringsTable &stringsTable, const byte *stringsPoin offset = scriptS.readUint16(); // In some rooms in IHNM, string offsets can be greater than the maximum value than a 16-bit integer can hold // We detect this by checking the previous offset, and if it was bigger than the current one, an overflow - // occured (since the string offsets are sequential), so we're adding the missing part of the number + // occurred (since the string offsets are sequential), so we're adding the missing part of the number // Fixes bug #1895205 - "IHNM: end game text/caption error" if (prevOffset > offset) offset += 65536; diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index d6cb4ebd8e..da014cd917 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -129,9 +129,9 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { if ((s->r_acc.offset) && (g_debugState.stopOnEvent)) { g_debugState.stopOnEvent = false; - // A SCI event occured, and we have been asked to stop, so open the debug console + // A SCI event occurred, and we have been asked to stop, so open the debug console Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("SCI event occured: "); + con->DebugPrintf("SCI event occurred: "); switch (curEvent.type) { case SCI_EVENT_QUIT: con->DebugPrintf("quit event\n"); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index ec89e42f9c..990836992c 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -407,7 +407,7 @@ public: * Determines the name of an object * @param[in] pos Location (segment, offset) of the object * @return A name for that object, or a string describing an error - * that occured while looking it up. The string is stored + * that occurred while looking it up. The string is stored * in a static buffer and need not be freed (neither may * it be modified). */ diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index e23d8fd080..cf253619e6 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -341,7 +341,7 @@ void MacResourceForkResourceSource::loadResource(Resource *res) { int error = res->decompress(stream); if (error) { - warning("Error %d occured while reading %s from Mac resource file: %s", + warning("Error %d occurred while reading %s from Mac resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); res->unalloc(); } @@ -442,7 +442,7 @@ void ResourceSource::loadResource(Resource *res) { delete fileStream; if (error) { - warning("Error %d occured while reading %s from resource file: %s", + warning("Error %d occurred while reading %s from resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); res->unalloc(); } @@ -817,7 +817,7 @@ Resource *ResourceManager::findResource(ResourceId id, bool lock) { loadResource(retval); else if (retval->_status == kResStatusEnqueued) removeFromLRU(retval); - // Unless an error occured, the resource is now either + // Unless an error occurred, the resource is now either // locked or allocated, but never queued or freed. freeOldResources(); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index eb2b82fdce..c2f3f17732 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -222,7 +222,7 @@ private: * This function must be run before script_run() is executed. Graphics data * is initialized iff s->gfx_state != NULL. * @param[in] s The state to operate on - * @return true on success, false if an error occured. + * @return true on success, false if an error occurred. */ bool initGame(); diff --git a/engines/scumm/verbs.h b/engines/scumm/verbs.h index 96a49a7ced..83e924edac 100644 --- a/engines/scumm/verbs.h +++ b/engines/scumm/verbs.h @@ -31,7 +31,7 @@ namespace Scumm { /** - * The area in which some click (or key press) occured and which is passed + * The area in which some click (or key press) occurred and which is passed * to the input script. */ enum ClickArea { -- cgit v1.2.3 From d570e10b77887fa163f17de512b14fc824f45f33 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:33:54 +0000 Subject: Modify makeAIFFStream to match the other sound decoder factories svn-id: r49844 --- engines/sci/sound/audio.cpp | 11 ++++++----- engines/sword1/music.cpp | 2 +- 2 files changed, 7 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index b0b9a73e00..8dfbc18976 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -260,9 +260,11 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 // Compressed audio made by our tool byte *compressedData = (byte *)malloc(audioRes->size); assert(compressedData); - // We copy over the compressed data in our own buffer. If we don't do this resourcemanager may free the data - // later. All other compression-types already decompress completely into an additional buffer here. - // MP3/OGG/FLAC decompression works on-the-fly instead. + // We copy over the compressed data in our own buffer. We have to do + // this, because ResourceManager may free the original data late. + // All other compression types already decompress completely into an + // additional buffer here. MP3/OGG/FLAC decompression works on-the-fly + // instead. memcpy(compressedData, audioRes->data, audioRes->size); Common::MemoryReadStream *compressedStream = new Common::MemoryReadStream(compressedData, audioRes->size, DisposeAfterUse::YES); @@ -319,8 +321,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 *sampleLen = (waveFlags & Audio::FLAG_16BITS ? waveSize >> 1 : waveSize) * 60 / waveRate; waveStream->seek(0, SEEK_SET); - audioStream = Audio::makeAIFFStream(*waveStream); - delete waveStream; // makeAIFFStream doesn't handle this for us + audioStream = Audio::makeAIFFStream(waveStream, DisposeAfterUse::YES); } else if (audioRes->size > 14 && READ_BE_UINT16(audioRes->data) == 1 && READ_BE_UINT16(audioRes->data + 2) == 1 && READ_BE_UINT16(audioRes->data + 4) == 5 && READ_BE_UINT32(audioRes->data + 10) == 0x00018051) { // Mac snd detected diff --git a/engines/sword1/music.cpp b/engines/sword1/music.cpp index 91c943472c..23cc30e4b1 100644 --- a/engines/sword1/music.cpp +++ b/engines/sword1/music.cpp @@ -107,7 +107,7 @@ bool MusicHandle::play(const char *fileBase, bool loop) { if (!_audioSource) { sprintf(fileName, "%s.aif", fileBase); if (_file.open(fileName)) - _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(_file), loop ? 0 : 1); + _audioSource = Audio::makeLoopingAudioStream(Audio::makeAIFFStream(&_file, DisposeAfterUse::NO), loop ? 0 : 1); } if (!_audioSource) -- cgit v1.2.3 From e62169c383c987949a5e7aad971691c030eb8a97 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:34:12 +0000 Subject: AGI: Specify bug reference for workaround svn-id: r49845 --- engines/agi/sprite.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/sprite.cpp b/engines/agi/sprite.cpp index d3bd1a6212..25118b69a6 100644 --- a/engines/agi/sprite.cpp +++ b/engines/agi/sprite.cpp @@ -242,7 +242,7 @@ void SpritesMgr::objsRestoreArea(Sprite *s) { pos0 += _WIDTH; } - // WORKAROUND + // WORKAROUND (see ScummVM bug #1945716) // When set.view command is called, current code cannot detect this situation while updating // Thus we force removal of the old sprite if (s->v->viewReplaced) { -- cgit v1.2.3 From f93644325244cc111634e2e8e4f97adb5a3fbe15 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:34:33 +0000 Subject: SCI: Saner and simpler conversion from msecs to ticks svn-id: r49846 --- engines/sci/sound/audio.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 8dfbc18976..ac3ef54c9a 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -353,9 +353,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 } if (audioSeekStream) { - *sampleLen = (audioSeekStream->getLength().msecs() * 10000) / 166666; // we translate msecs to ticks - // Original code - //*sampleLen = (flags & Audio::FLAG_16BITS ? size >> 1 : size) * 60 / _audioRate; + *sampleLen = (audioSeekStream->getLength().msecs() * 60) / 1000; // we translate msecs to ticks audioStream = audioSeekStream; } // We have to make sure that we don't depend on resource manager pointers after this point, because the actual -- cgit v1.2.3 From e4153ffa381542ee14ad268475f679917d177254 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:35:17 +0000 Subject: SCI: Add Resource::getNumber method svn-id: r49848 --- engines/sci/resource.cpp | 8 ++++---- engines/sci/resource.h | 1 + 2 files changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index cf253619e6..24e92060e2 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -334,10 +334,10 @@ void PatchResourceSource::loadResource(Resource *res) { } void MacResourceForkResourceSource::loadResource(Resource *res) { - Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->_id.getNumber()); + Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->getNumber()); if (!stream) - error("Could not get Mac resource fork resource: %d %d", res->getType(), res->_id.getNumber()); + error("Could not get Mac resource fork resource: %d %d", res->getType(), res->getNumber()); int error = res->decompress(stream); if (error) { @@ -799,7 +799,7 @@ Common::List *ResourceManager::listResources(ResourceType type, int ResourceMap::iterator itr = _resMap.begin(); while (itr != _resMap.end()) { - if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->_id.getNumber() == mapNumber))) + if ((itr->_value->getType() == type) && ((mapNumber == -1) || (itr->_value->getNumber() == mapNumber))) resources->push_back(itr->_value->_id); ++itr; } @@ -1551,7 +1551,7 @@ int Resource::readResourceInfo(Common::SeekableReadStream *file, // Doesn't store this data in the resource. Fortunately, // we already have this data. type = getType(); - number = _id.getNumber(); + number = getNumber(); szPacked = file->size(); szUnpacked = file->size(); wCompression = 0; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 43408b0ffe..9d372eaf02 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -198,6 +198,7 @@ public: void unalloc(); inline ResourceType getType() const { return _id.getType(); } + inline uint16 getNumber() const { return _id.getNumber(); } /** * Write the resource to the specified stream. -- cgit v1.2.3 From f387025e9b6a38b9023ffb2a766c168120472202 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:35:39 +0000 Subject: SCI: Add FIXME regarding audio specific code in Resource(Source) svn-id: r49849 --- engines/sci/resource.h | 4 ++++ engines/sci/resource_intern.h | 4 +++- 2 files changed, 7 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 9d372eaf02..9cf7120ed7 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -205,6 +205,10 @@ public: * This method is used only by the "dump" debugger command. */ void writeToStream(Common::WriteStream *stream) const; + + // FIXME: This audio specific method is a hack. After all, why should a + // Resource have audio specific methods? But for now we keep this, as it + // eases transition. uint32 getAudioCompressionType() const; protected: diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 042c5428d8..8cb13bd311 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -85,8 +85,10 @@ public: */ virtual void loadResource(Resource *res); + // FIXME: This audio specific method is a hack. After all, why should a + // ResourceSource or a Resource (which uses this method) have audio + // specific methods? But for now we keep this, as it eases transition. virtual uint32 getAudioCompressionType() const { return 0; } - }; class DirectoryResourceSource : public ResourceSource { -- cgit v1.2.3 From 604f85588965498f7852b579e19a9f6e99d32590 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 12:36:04 +0000 Subject: SCUMM: Fix composeFileHashMap svn-id: r49850 --- engines/scumm/detection.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index c164ac38fd..551e4c70a7 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -395,7 +395,7 @@ static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map d.md5Entry = 0; fileMD5Map[file->getName()] = d; } else { - if (!directoryGlobs) + if (!globs) continue; bool matched = false; @@ -411,7 +411,7 @@ static void composeFileHashMap(const Common::FSList &fslist, DescMap &fileMD5Map Common::FSList files; if (file->getChildren(files, Common::FSNode::kListAll)) { - composeFileHashMap(files, fileMD5Map, depth - 1, directoryGlobs); + composeFileHashMap(files, fileMD5Map, depth - 1, globs); } } } -- cgit v1.2.3 From 891b568fde51c7f1732c86fd34cc40efcd4314ce Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 13:01:07 +0000 Subject: SCI: move textSize and textFonts and textColors inside gfxText16 svn-id: r49851 --- engines/sci/engine/kgraphics.cpp | 14 ++++++----- engines/sci/graphics/gui.cpp | 18 +------------- engines/sci/graphics/gui.h | 4 --- engines/sci/graphics/gui32.cpp | 5 ---- engines/sci/graphics/text16.cpp | 53 +++++++++++++++++++++++----------------- engines/sci/graphics/text16.h | 6 +++-- engines/sci/sci.h | 2 ++ 7 files changed, 46 insertions(+), 56 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index cf6bd41fa9..3e74bb206a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -48,6 +48,7 @@ #include "sci/graphics/paint16.h" #include "sci/graphics/ports.h" #include "sci/graphics/screen.h" +#include "sci/graphics/text16.h" #include "sci/graphics/view.h" namespace Sci { @@ -345,11 +346,12 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16(); #ifdef ENABLE_SCI32 - if (g_sci->_gui32) - g_sci->_gui32->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); - else + if (!g_sci->_gfxText16) { + // TODO: Implement this + textWidth = 0; textHeight = 0; + } else #endif - g_sci->_gui->textSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); + g_sci->_gfxText16->kernelTextSize(g_sci->strSplit(text.c_str(), sep).c_str(), font_nr, maxwidth, &textWidth, &textHeight); debugC(2, kDebugLevelStrings, "GetTextSize '%s' -> %dx%d", text.c_str(), textWidth, textHeight); dest[2] = make_reg(0, textHeight); @@ -1246,12 +1248,12 @@ reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) { // New calls for SCI11. Using those is only needed when using text-codes so that one is able to change // font and/or color multiple times during kDisplay and kDrawControl reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) { - g_sci->_gui->textFonts(argc, argv); + g_sci->_gfxText16->kernelTextFonts(argc, argv); return s->r_acc; } reg_t kTextColors(EngineState *s, int argc, reg_t *argv) { - g_sci->_gui->textColors(argc, argv); + g_sci->_gfxText16->kernelTextColors(argc, argv); return s->r_acc; } diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 468fbed776..847831c909 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -68,6 +68,7 @@ SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCa _animate = new GfxAnimate(_s, _cache, _ports, _paint16, _screen, _palette, _cursor, _transitions); g_sci->_gfxAnimate = _animate; _text16 = new GfxText16(g_sci->getResMan(), _cache, _ports, _paint16, _screen); + g_sci->_gfxText16 = _text16; _controls = new GfxControls(_s->_segMan, _ports, _paint16, _text16, _screen); g_sci->_gfxControls = _controls; _menu = new GfxMenu(g_sci->getEventManager(), _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor); @@ -94,21 +95,4 @@ void SciGui::wait(int16 ticks) { _s->wait(ticks); } -void SciGui::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { - Common::Rect rect(0, 0, *textWidth, *textHeight); - _text16->Size(rect, text, font, maxWidth); - *textWidth = rect.width(); - *textHeight = rect.height(); -} - -// Used SCI1+ for text codes -void SciGui::textFonts(int argc, reg_t *argv) { - _text16->CodeSetFonts(argc, argv); -} - -// Used SCI1+ for text codes -void SciGui::textColors(int argc, reg_t *argv) { - _text16->CodeSetColors(argc, argv); -} - } // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index 73c37de099..edb93e10cb 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -53,10 +53,6 @@ public: virtual void wait(int16 ticks); - virtual void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); - virtual void textFonts(int argc, reg_t *argv); - virtual void textColors(int argc, reg_t *argv); - protected: GfxCursor *_cursor; EngineState *_s; diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp index 10b2b1c4fd..fb2da08ae5 100644 --- a/engines/sci/graphics/gui32.cpp +++ b/engines/sci/graphics/gui32.cpp @@ -69,11 +69,6 @@ SciGui32::~SciGui32() { void SciGui32::init() { } -void SciGui32::textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { - *textWidth = 0; - *textHeight = 0; -} - void SciGui32::drawRobot(GuiResourceId robotId) { Robot *test = new Robot(g_sci->getResMan(), _screen, robotId); test->draw(); diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index 952d13fbbd..c9a7f09973 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -73,28 +73,6 @@ void GfxText16::SetFont(GuiResourceId fontId) { _ports->_curPort->fontHeight = _font->getHeight(); } -void GfxText16::CodeSetFonts(int argc, reg_t *argv) { - int i; - - delete _codeFonts; - _codeFontsCount = argc; - _codeFonts = new GuiResourceId[argc]; - for (i = 0; i < argc; i++) { - _codeFonts[i] = (GuiResourceId)argv[i].toUint16(); - } -} - -void GfxText16::CodeSetColors(int argc, reg_t *argv) { - int i; - - delete _codeColors; - _codeColorsCount = argc; - _codeColors = new uint16[argc]; - for (i = 0; i < argc; i++) { - _codeColors[i] = argv[i].toUint16(); - } -} - void GfxText16::ClearChar(int16 chr) { if (_ports->_curPort->penMode != 1) return; @@ -488,4 +466,35 @@ bool GfxText16::SwitchToFont900OnSjis(const char *text) { return false; } +void GfxText16::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { + Common::Rect rect(0, 0, *textWidth, *textHeight); + Size(rect, text, font, maxWidth); + *textWidth = rect.width(); + *textHeight = rect.height(); +} + +// Used SCI1+ for text codes +void GfxText16::kernelTextFonts(int argc, reg_t *argv) { + int i; + + delete _codeFonts; + _codeFontsCount = argc; + _codeFonts = new GuiResourceId[argc]; + for (i = 0; i < argc; i++) { + _codeFonts[i] = (GuiResourceId)argv[i].toUint16(); + } +} + +// Used SCI1+ for text codes +void GfxText16::kernelTextColors(int argc, reg_t *argv) { + int i; + + delete _codeColors; + _codeColorsCount = argc; + _codeColors = new uint16[argc]; + for (i = 0; i < argc; i++) { + _codeColors[i] = argv[i].toUint16(); + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/text16.h b/engines/sci/graphics/text16.h index 2885fc928b..71b602d116 100644 --- a/engines/sci/graphics/text16.h +++ b/engines/sci/graphics/text16.h @@ -48,8 +48,6 @@ public: GfxFont *GetFont(); void SetFont(GuiResourceId fontId); - void CodeSetFonts(int argc, reg_t *argv); - void CodeSetColors(int argc, reg_t *argv); int16 CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor); void ClearChar(int16 chr); @@ -67,6 +65,10 @@ public: GfxFont *_font; + void kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); + void kernelTextFonts(int argc, reg_t *argv); + void kernelTextColors(int argc, reg_t *argv); + private: void init(); bool SwitchToFont900OnSjis(const char *text); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index c2f3f17732..7cfeec0e09 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -66,6 +66,7 @@ class GfxPaint16; class GfxPalette; class GfxPorts; class GfxScreen; +class GfxText16; class SciGui; class GfxMacIconBar; @@ -205,6 +206,7 @@ public: GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx GfxPorts *_gfxPorts; // Port managment for 16-bit gfx GfxScreen *_gfxScreen; + GfxText16 *_gfxText16; SciGui *_gui; /* Currently active Gui */ GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager -- cgit v1.2.3 From af5346e7ab97190f45be17192deef9a764cd128d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 13:14:23 +0000 Subject: SCI: calling wait() directly and removing it from SciGui svn-id: r49853 --- engines/sci/graphics/gui.cpp | 4 ---- engines/sci/graphics/gui.h | 2 -- engines/sci/graphics/paint16.cpp | 16 ++++------------ engines/sci/graphics/portrait.cpp | 2 +- engines/sci/graphics/transitions.cpp | 4 ++-- 5 files changed, 7 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 847831c909..7febbeba69 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -91,8 +91,4 @@ void SciGui::init(bool usesOldGfxFunctions) { _paint16->init(_animate, _text16); } -void SciGui::wait(int16 ticks) { - _s->wait(ticks); -} - } // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index edb93e10cb..c3954286b3 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -51,8 +51,6 @@ public: virtual void init(bool usesOldGfxFunctions); - virtual void wait(int16 ticks); - protected: GfxCursor *_cursor; EngineState *_s; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 10eae3c618..103da594e6 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -562,22 +562,14 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) { if (directions & SCI_SHAKE_DIRECTION_VERTICAL) _screen->setVerticalShakePos(10); // TODO: horizontal shakes + g_system->updateScreen(); + g_sci->getEngineState()->wait(3); - if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { - g_system->updateScreen(); - g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); - } - - _gui->wait(3); if (directions & SCI_SHAKE_DIRECTION_VERTICAL) _screen->setVerticalShakePos(0); - if (g_system->getMillis() - g_sci->getEngineState()->_screenUpdateTime >= 1000 / 60) { - g_system->updateScreen(); - g_sci->getEngineState()->_screenUpdateTime = g_system->getMillis(); - } - - _gui->wait(3); + g_system->updateScreen(); + g_sci->getEngineState()->wait(3); } } diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index b912bf552e..a85d9a3b06 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -182,7 +182,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Wait till syncTime passed, then show specific animation bitmap do { - _gui->wait(1); + g_sci->getEngineState()->wait(1); curEvent = _event->get(SCI_EVENT_ANY); if (curEvent.type == SCI_EVENT_MOUSE_PRESS || (curEvent.type == SCI_EVENT_KEYBOARD && curEvent.data == SCI_KEY_ESC) || diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index f73525caaf..0bb1a87fc2 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -291,7 +291,7 @@ void GfxTransitions::fadeOut() { workPalette[colorNr * 4 + 2] = oldPalette[colorNr * 4 + 2] * stepNr / 100; } g_system->setPalette(workPalette + 4, 1, 254); - _gui->wait(2); + g_sci->getEngineState()->wait(2); } } @@ -301,7 +301,7 @@ void GfxTransitions::fadeIn() { for (stepNr = 0; stepNr <= 100; stepNr += 10) { _palette->kernelSetIntensity(1, 255, stepNr, true); - _gui->wait(2); + g_sci->getEngineState()->wait(2); } } -- cgit v1.2.3 From ba2de6dfa4f160d04474b76d8d5f7a24634196e1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 13:34:40 +0000 Subject: SCI: putting SciGui::init into SciEngine, removing it from SciGui(32) svn-id: r49854 --- engines/sci/engine/savegame.cpp | 10 +--------- engines/sci/graphics/gui.cpp | 5 ----- engines/sci/graphics/gui.h | 2 -- engines/sci/graphics/gui32.cpp | 3 --- engines/sci/graphics/gui32.h | 4 ---- engines/sci/graphics/ports.cpp | 3 +-- engines/sci/graphics/ports.h | 3 +-- engines/sci/sci.cpp | 19 +++++++++++-------- engines/sci/sci.h | 3 +++ 9 files changed, 17 insertions(+), 35 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 02fdde5622..97872253cb 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -983,15 +983,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // Message state: s->_msgState = new MessageState(s->_segMan); -#ifdef ENABLE_SCI32 - if (g_sci->_gui32) { - g_sci->_gui32->init(); - } else { -#endif - g_sci->_gui->init(g_sci->_features->usesOldGfxFunctions()); -#ifdef ENABLE_SCI32 - } -#endif + g_sci->initGraphics(); s->abortScriptProcessing = kAbortLoadGame; s->shrinkStackToBase(); diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp index 7febbeba69..a450870079 100644 --- a/engines/sci/graphics/gui.cpp +++ b/engines/sci/graphics/gui.cpp @@ -86,9 +86,4 @@ SciGui::~SciGui() { delete _coordAdjuster; } -void SciGui::init(bool usesOldGfxFunctions) { - _ports->init(usesOldGfxFunctions, this, _paint16, _text16); - _paint16->init(_animate, _text16); -} - } // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h index c3954286b3..26028e0cc5 100644 --- a/engines/sci/graphics/gui.h +++ b/engines/sci/graphics/gui.h @@ -49,8 +49,6 @@ public: SciGui(EngineState *s, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio); virtual ~SciGui(); - virtual void init(bool usesOldGfxFunctions); - protected: GfxCursor *_cursor; EngineState *_s; diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp index fb2da08ae5..c953ed7f70 100644 --- a/engines/sci/graphics/gui32.cpp +++ b/engines/sci/graphics/gui32.cpp @@ -66,9 +66,6 @@ SciGui32::~SciGui32() { delete _coordAdjuster; } -void SciGui32::init() { -} - void SciGui32::drawRobot(GuiResourceId robotId) { Robot *test = new Robot(g_sci->getResMan(), _screen, robotId); test->draw(); diff --git a/engines/sci/graphics/gui32.h b/engines/sci/graphics/gui32.h index 2c73272566..2be37d0aaf 100644 --- a/engines/sci/graphics/gui32.h +++ b/engines/sci/graphics/gui32.h @@ -44,10 +44,6 @@ public: SciGui32(SegManager *segMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor); ~SciGui32(); - void init(); - - void textSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight); - void drawRobot(GuiResourceId robotId); protected: diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index d230c1eb9f..b8d38910d1 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -54,11 +54,10 @@ GfxPorts::~GfxPorts() { delete _menuPort; } -void GfxPorts::init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16) { +void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) { int16 offTop = 10; _usesOldGfxFunctions = usesOldGfxFunctions; - _gui = gui; _paint16 = paint16; _text16 = text16; diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h index c8ce6b3470..818f92f44f 100644 --- a/engines/sci/graphics/ports.h +++ b/engines/sci/graphics/ports.h @@ -45,7 +45,7 @@ public: GfxPorts(SegManager *segMan, GfxScreen *screen); ~GfxPorts(); - void init(bool usesOldGfxFunctions, SciGui *gui, GfxPaint16 *paint16, GfxText16 *text16); + void init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16); void kernelSetActive(uint16 portId); Common::Rect kernelGetPicWindow(int16 &picTop, int16 &picLeft); @@ -102,7 +102,6 @@ private: typedef Common::List PortList; SegManager *_segMan; - SciGui *_gui; GfxPaint16 *_paint16; GfxScreen *_screen; GfxText16 *_text16; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 2680da9d39..7dba21b800 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -47,6 +47,7 @@ #include "sci/graphics/gui.h" #include "sci/graphics/maciconbar.h" #include "sci/graphics/menu.h" +#include "sci/graphics/paint16.h" #include "sci/graphics/ports.h" #include "sci/graphics/palette.h" #include "sci/graphics/cursor.h" @@ -254,14 +255,7 @@ Common::Error SciEngine::run() { syncSoundSettings(); -#ifdef ENABLE_SCI32 - if (_gui32) - _gui32->init(); - else -#endif - _gui->init(_features->usesOldGfxFunctions()); - // Set default (EGA, amiga or resource 999) palette - _gfxPalette->setDefault(); + initGraphics(); debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); @@ -353,6 +347,15 @@ bool SciEngine::initGame() { return true; } +void SciEngine::initGraphics() { + if (_gfxPorts) { + _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16); + _gfxPaint16->init(_gfxAnimate, _gfxText16); + } + // Set default (EGA, amiga or resource 999) palette + _gfxPalette->setDefault(); +} + #ifdef USE_OLD_MUSIC_FUNCTIONS void SciEngine::initGameSound(int sound_flags, SciVersion soundVersion) { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 7cfeec0e09..6f6a6b5dd1 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -193,6 +193,9 @@ public: Common::String getSciLanguageString(const char *str, kLanguage lang, kLanguage *lang2 = NULL) const; + // Initializes ports and paint16 for non-sci32 games, also sets default palette + void initGraphics(); + public: GfxAnimate *_gfxAnimate; // Animate for 16-bit gfx GfxCache *_gfxCache; -- cgit v1.2.3 From 45fe9a469e0f0281926920614e1ffec88932d7e8 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 15 Jun 2010 13:45:12 +0000 Subject: Fix wave patches. svn-id: r49855 --- engines/sci/resource_audio.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 7a0d9bac6e..fc30047e1c 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -174,7 +174,7 @@ void ResourceManager::processWavePatch(ResourceId resourceId, Common::String nam Common::File file; file.open(name); - updateResource(resourceId, resSrc, name.size()); + updateResource(resourceId, resSrc, file.size()); debugC(1, kDebugLevelResMan, "Patching %s - OK", name.c_str()); } -- cgit v1.2.3 From ddb5a769a2e4f74c1da945914a67e169bc94bafb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 13:52:06 +0000 Subject: SCI: reset _gfxText16 for sci32, fixes gk1 svn-id: r49856 --- engines/sci/sci.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 7dba21b800..692928f12c 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -227,6 +227,7 @@ Common::Error SciEngine::run() { _gfxMenu = 0; _gfxPaint16 = 0; _gfxPorts = 0; + _gfxText16 = 0; _gui = 0; _gui32 = new SciGui32(_gamestate->_segMan, _eventMan, _gfxScreen, _gfxPalette, _gfxCache, _gfxCursor); } else { -- cgit v1.2.3 From ab558b45d252743797bca27d2240bf0e2057863f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 14:55:52 +0000 Subject: Fixed detective Mosely's hotspot in GK1 (day 1) svn-id: r49857 --- engines/sci/engine/kernel32.cpp | 12 +++++++++--- 1 file changed, 9 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 2b00daf34a..8c5cb019b9 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -792,12 +792,18 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { nsRect.top = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsTop)); nsRect.right = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsRight)); nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); - uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + if (nsRect.left < 0 || nsRect.top < 0) { + // If top and left are negative, we need to adjust coordinates by the item's x and y + nsRect.translate(itemX, itemY); + } + + // HACK: nsLeft and nsTop can be invalid, so try and fix them here using x and y + // (e.g. with the inventory screen in GK1 or detective Mosely in his office) + // Not sure why this is happening, but at least this hack fixes most of the issues if (nsRect.left == itemY && nsRect.top == itemX) { - // FIXME: Why is this happening?? - // Swap the values, as they're inversed(eh???) + // Swap the values, as they're inversed (eh???) nsRect.left = itemX; nsRect.top = itemY; } -- cgit v1.2.3 From e94e91222c70537740ce9610cd8eecfa15f93cb0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 15:02:52 +0000 Subject: Fixed comments svn-id: r49858 --- engines/sci/engine/kernel32.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 8c5cb019b9..0a510dabbb 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -796,12 +796,12 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); if (nsRect.left < 0 || nsRect.top < 0) { // If top and left are negative, we need to adjust coordinates by the item's x and y + // (e.g. happens in GK1, day 1, with detective Mosely's hotspot in his office) nsRect.translate(itemX, itemY); } // HACK: nsLeft and nsTop can be invalid, so try and fix them here using x and y - // (e.g. with the inventory screen in GK1 or detective Mosely in his office) - // Not sure why this is happening, but at least this hack fixes most of the issues + // (e.g. with the inventory screen in GK1) if (nsRect.left == itemY && nsRect.top == itemX) { // Swap the values, as they're inversed (eh???) nsRect.left = itemX; -- cgit v1.2.3 From b25aba1d1ed9c867bbb4ff1b6b7ef9ea075b3cd1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 15:44:24 +0000 Subject: SCI: SciGui/SciGui32 gone for good... svn-id: r49860 --- engines/sci/console.cpp | 9 ++-- engines/sci/engine/kernel32.cpp | 2 - engines/sci/engine/kevent.cpp | 2 - engines/sci/engine/kgraphics.cpp | 5 +- engines/sci/engine/kmenu.cpp | 1 - engines/sci/engine/kmisc.cpp | 1 - engines/sci/engine/savegame.cpp | 5 -- engines/sci/graphics/cache.h | 2 - engines/sci/graphics/compare.h | 2 - engines/sci/graphics/frameout.h | 3 ++ engines/sci/graphics/gui.cpp | 89 ------------------------------------ engines/sci/graphics/gui.h | 76 ------------------------------ engines/sci/graphics/gui32.cpp | 75 ------------------------------ engines/sci/graphics/gui32.h | 64 -------------------------- engines/sci/graphics/menu.cpp | 5 +- engines/sci/graphics/menu.h | 3 +- engines/sci/graphics/paint.h | 2 - engines/sci/graphics/paint16.cpp | 6 +-- engines/sci/graphics/paint16.h | 4 +- engines/sci/graphics/paint32.cpp | 7 +++ engines/sci/graphics/paint32.h | 3 +- engines/sci/graphics/portrait.cpp | 5 +- engines/sci/graphics/portrait.h | 3 +- engines/sci/graphics/robot.cpp | 8 ++-- engines/sci/graphics/robot.h | 6 +-- engines/sci/graphics/transitions.cpp | 5 +- engines/sci/graphics/transitions.h | 3 +- engines/sci/module.mk | 2 - engines/sci/sci.cpp | 81 ++++++++++++++++++++++++-------- engines/sci/sci.h | 9 ++-- 30 files changed, 106 insertions(+), 382 deletions(-) delete mode 100644 engines/sci/graphics/gui.cpp delete mode 100644 engines/sci/graphics/gui.h delete mode 100644 engines/sci/graphics/gui32.cpp delete mode 100644 engines/sci/graphics/gui32.h (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 4c8d588fa0..8fc49fa396 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -43,12 +43,11 @@ #include "sci/sound/music.h" #endif #include "sci/sound/drivers/mididriver.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" #include "sci/graphics/paint.h" #include "sci/graphics/paint16.h" +#include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" #include "sci/parser/vocabulary.h" @@ -1299,7 +1298,11 @@ bool Console::cmdDrawRobot(int argc, const char **argv) { uint16 resourceId = atoi(argv[1]); - _engine->_gui32->drawRobot(resourceId); + if (_engine->_gfxPaint32) { + _engine->_gfxPaint32->debugDrawRobot(resourceId); + } else { + DebugPrintf("command not available in non-sci32 games"); + } return true; } #endif diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 0a510dabbb..b42e0c4144 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -30,8 +30,6 @@ #include "sci/engine/segment.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/frameout.h" #include "sci/graphics/screen.h" diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index da014cd917..c5a37dde94 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -31,8 +31,6 @@ #include "sci/console.h" #include "sci/debug.h" // for g_debug_simulated_key #include "sci/event.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/coordadjuster.h" #include "sci/graphics/cursor.h" diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 3e74bb206a..c7126127ca 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -37,8 +37,6 @@ #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/kernel.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/gui32.h" #include "sci/graphics/animate.h" #include "sci/graphics/cache.h" #include "sci/graphics/compare.h" @@ -634,7 +632,8 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); - if (!g_sci->_gui) + // Exit for SCI32 for now + if (!g_sci->_gfxPaint16) return s->r_acc; switch (operation) { diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index a5f2f01297..13937c2f61 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -27,7 +27,6 @@ #include "sci/resource.h" #include "sci/engine/state.h" #include "sci/engine/kernel.h" -#include "sci/graphics/gui.h" #include "sci/graphics/cursor.h" #include "sci/graphics/menu.h" diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index d836ec4a7f..ef6088b6d5 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -31,7 +31,6 @@ #include "sci/engine/state.h" #include "sci/engine/kernel.h" #include "sci/engine/gc.h" -#include "sci/graphics/gui.h" #include "sci/graphics/maciconbar.h" namespace Sci { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 97872253cb..256a1aef03 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -39,7 +39,6 @@ #include "sci/engine/selector.h" #include "sci/engine/vm_types.h" #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS -#include "sci/graphics/gui.h" #include "sci/graphics/ports.h" #include "sci/sound/audio.h" #ifdef USE_OLD_MUSIC_FUNCTIONS @@ -49,10 +48,6 @@ #include "sci/sound/music.h" #endif -#ifdef ENABLE_SCI32 -#include "sci/graphics/gui32.h" -#endif - #include "gui/message.h" namespace Sci { diff --git a/engines/sci/graphics/cache.h b/engines/sci/graphics/cache.h index 16ab1916d4..2e9a345230 100644 --- a/engines/sci/graphics/cache.h +++ b/engines/sci/graphics/cache.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_CACHE_H #define SCI_GRAPHICS_CACHE_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/compare.h b/engines/sci/graphics/compare.h index 348d5ef723..be461cdc5b 100644 --- a/engines/sci/graphics/compare.h +++ b/engines/sci/graphics/compare.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_GFX_H #define SCI_GRAPHICS_GFX_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 36c02af278..8015b9879f 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -44,7 +44,10 @@ struct FrameoutEntry { typedef Common::List FrameoutList; class GfxCache; +class GfxCoordAdjuster32; class GfxPaint32; +class GfxPalette; +class GfxScreen; /** * Frameout class, kFrameout and relevant functions for SCI32 games */ diff --git a/engines/sci/graphics/gui.cpp b/engines/sci/graphics/gui.cpp deleted file mode 100644 index a450870079..0000000000 --- a/engines/sci/graphics/gui.cpp +++ /dev/null @@ -1,89 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/timer.h" -#include "common/util.h" - -#include "sci/sci.h" -#include "sci/debug.h" // for g_debug_sleeptime_factor -#include "sci/event.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/gui.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" -#include "sci/graphics/ports.h" -#include "sci/graphics/paint16.h" -#include "sci/graphics/cache.h" -#include "sci/graphics/compare.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/animate.h" -#include "sci/graphics/controls.h" -#include "sci/graphics/menu.h" -#include "sci/graphics/text16.h" -#include "sci/graphics/transitions.h" -#include "sci/graphics/view.h" -#include "sci/sound/audio.h" - -namespace Sci { - -SciGui::SciGui(EngineState *state, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio) - : _s(state), _screen(screen), _palette(palette), _cache(cache), _cursor(cursor), _ports(ports), _audio(audio) { - - // FIXME/TODO: If SciGui inits all the stuff below, then it should *own* it, - // not SciEngine. Conversely, if we want SciEngine to own this stuff, - // then it should init it! - _coordAdjuster = new GfxCoordAdjuster16(_ports); - g_sci->_gfxCoordAdjuster = _coordAdjuster; - _cursor->init(_coordAdjuster, g_sci->getEventManager()); - _compare = new GfxCompare(_s->_segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); - g_sci->_gfxCompare = _compare; - _transitions = new GfxTransitions(this, _screen, _palette, g_sci->getResMan()->isVGA()); - _paint16 = new GfxPaint16(g_sci->getResMan(), _s->_segMan, g_sci->getKernel(), this, _cache, _ports, _coordAdjuster, _screen, _palette, _transitions, _audio); - g_sci->_gfxPaint = _paint16; - g_sci->_gfxPaint16 = _paint16; - _animate = new GfxAnimate(_s, _cache, _ports, _paint16, _screen, _palette, _cursor, _transitions); - g_sci->_gfxAnimate = _animate; - _text16 = new GfxText16(g_sci->getResMan(), _cache, _ports, _paint16, _screen); - g_sci->_gfxText16 = _text16; - _controls = new GfxControls(_s->_segMan, _ports, _paint16, _text16, _screen); - g_sci->_gfxControls = _controls; - _menu = new GfxMenu(g_sci->getEventManager(), _s->_segMan, this, _ports, _paint16, _text16, _screen, _cursor); - g_sci->_gfxMenu = _menu; -} - -SciGui::~SciGui() { - delete _menu; - delete _controls; - delete _text16; - delete _animate; - delete _paint16; - delete _transitions; - delete _compare; - delete _coordAdjuster; -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/gui.h b/engines/sci/graphics/gui.h deleted file mode 100644 index 26028e0cc5..0000000000 --- a/engines/sci/graphics/gui.h +++ /dev/null @@ -1,76 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_GRAPHICS_GUI_H -#define SCI_GRAPHICS_GUI_H - -#include "sci/graphics/helpers.h" - -namespace Sci { - -class GfxScreen; -class GfxPalette; -class GfxCursor; -class GfxCache; -class GfxCompare; -class GfxCoordAdjuster16; -class GfxPorts; -class GfxPaint16; -class GfxAnimate; -class GfxControls; -class GfxMenu; -class GfxText16; -class GfxTransitions; - -class SciGui { -public: - SciGui(EngineState *s, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor, GfxPorts *ports, AudioPlayer *audio); - virtual ~SciGui(); - -protected: - GfxCursor *_cursor; - EngineState *_s; - GfxScreen *_screen; - GfxPalette *_palette; - GfxCache *_cache; - GfxCoordAdjuster16 *_coordAdjuster; - GfxCompare *_compare; - GfxPorts *_ports; - GfxPaint16 *_paint16; - -private: - AudioPlayer *_audio; - GfxAnimate *_animate; - GfxControls *_controls; - GfxMenu *_menu; - GfxText16 *_text16; - GfxTransitions *_transitions; - - bool _usesOldGfxFunctions; -}; - -} // End of namespace Sci - -#endif diff --git a/engines/sci/graphics/gui32.cpp b/engines/sci/graphics/gui32.cpp deleted file mode 100644 index c953ed7f70..0000000000 --- a/engines/sci/graphics/gui32.cpp +++ /dev/null @@ -1,75 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "common/timer.h" -#include "common/util.h" - -#include "sci/sci.h" -#include "sci/event.h" -#include "sci/engine/state.h" -#include "sci/engine/selector.h" -#include "sci/graphics/gui32.h" -#include "sci/graphics/screen.h" -#include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" -#include "sci/graphics/cache.h" -#include "sci/graphics/compare.h" -#include "sci/graphics/coordadjuster.h" -#include "sci/graphics/frameout.h" -#include "sci/graphics/paint32.h" -#include "sci/graphics/picture.h" -#include "sci/graphics/robot.h" -#include "sci/graphics/view.h" - -namespace Sci { - -SciGui32::SciGui32(SegManager *segMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor) - : _screen(screen), _palette(palette), _cache(cache), _cursor(cursor) { - - _coordAdjuster = new GfxCoordAdjuster32(segMan); - g_sci->_gfxCoordAdjuster = _coordAdjuster; - _cursor->init(_coordAdjuster, event); - _compare = new GfxCompare(segMan, g_sci->getKernel(), _cache, _screen, _coordAdjuster); - g_sci->_gfxCompare = _compare; - _paint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _coordAdjuster, _cache, _screen, _palette); - g_sci->_gfxPaint = _paint32; - _frameout = new GfxFrameout(segMan, g_sci->getResMan(), _coordAdjuster, _cache, _screen, _palette, _paint32); - g_sci->_gfxFrameout = _frameout; -} - -SciGui32::~SciGui32() { - delete _frameout; - delete _paint32; - delete _compare; - delete _coordAdjuster; -} - -void SciGui32::drawRobot(GuiResourceId robotId) { - Robot *test = new Robot(g_sci->getResMan(), _screen, robotId); - test->draw(); - delete test; -} - -} // End of namespace Sci diff --git a/engines/sci/graphics/gui32.h b/engines/sci/graphics/gui32.h deleted file mode 100644 index 2be37d0aaf..0000000000 --- a/engines/sci/graphics/gui32.h +++ /dev/null @@ -1,64 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_GRAPHICS_GUI32_H -#define SCI_GRAPHICS_GUI32_H - -#include "sci/graphics/helpers.h" - -namespace Sci { - -class GfxCursor; -class GfxScreen; -class GfxPalette; -class GfxCache; -class GfxCoordAdjuster32; -class GfxCompare; -class GfxFrameout; -class GfxPaint32; - -class SciGui32 { -public: - SciGui32(SegManager *segMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, GfxCache *cache, GfxCursor *cursor); - ~SciGui32(); - - void drawRobot(GuiResourceId robotId); - -protected: - GfxCursor *_cursor; - GfxScreen *_screen; - GfxPalette *_palette; - GfxCache *_cache; - GfxCoordAdjuster32 *_coordAdjuster; - GfxCompare *_compare; - GfxFrameout *_frameout; - GfxPaint32 *_paint32; - -private: -}; - -} // End of namespace Sci - -#endif diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index ac4f1c0653..5ca4d8176b 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -31,7 +31,6 @@ #include "sci/event.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/gui.h" #include "sci/graphics/ports.h" #include "sci/graphics/paint16.h" #include "sci/graphics/animate.h" @@ -43,8 +42,8 @@ namespace Sci { -GfxMenu::GfxMenu(EventManager *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) - : _event(event), _segMan(segMan), _gui(gui), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) { +GfxMenu::GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor) + : _event(event), _segMan(segMan), _ports(ports), _paint16(paint16), _text16(text16), _screen(screen), _cursor(cursor) { _menuSaveHandle = NULL_REG; _barSaveHandle = NULL_REG; diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h index ec344961de..b72d518977 100644 --- a/engines/sci/graphics/menu.h +++ b/engines/sci/graphics/menu.h @@ -83,7 +83,7 @@ typedef Common::List GuiMenuItemList; */ class GfxMenu { public: - GfxMenu(EventManager *event, SegManager *segMan, SciGui *gui, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); + GfxMenu(EventManager *event, SegManager *segMan, GfxPorts *ports, GfxPaint16 *paint16, GfxText16 *text16, GfxScreen *screen, GfxCursor *cursor); ~GfxMenu(); void reset(); @@ -113,7 +113,6 @@ private: EventManager *_event; SegManager *_segMan; - SciGui *_gui; GfxPorts *_ports; GfxPaint16 *_paint16; GfxText16 *_text16; diff --git a/engines/sci/graphics/paint.h b/engines/sci/graphics/paint.h index f1342d55e5..75a17461d4 100644 --- a/engines/sci/graphics/paint.h +++ b/engines/sci/graphics/paint.h @@ -26,8 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT_H #define SCI_GRAPHICS_PAINT_H -#include "sci/graphics/gui.h" - #include "common/hashmap.h" namespace Sci { diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 103da594e6..a52fd304e2 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -48,8 +48,8 @@ namespace Sci { -GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) - : _resMan(resMan), _segMan(segMan), _kernel(kernel), _gui(gui), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio) { +GfxPaint16::GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio) + : _resMan(resMan), _segMan(segMan), _kernel(kernel), _cache(cache), _ports(ports), _coordAdjuster(coordAdjuster), _screen(screen), _palette(palette), _transitions(transitions), _audio(audio) { } GfxPaint16::~GfxPaint16() { @@ -579,7 +579,7 @@ reg_t GfxPaint16::kernelPortraitLoad(Common::String resourceName) { } void GfxPaint16::kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { - Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _gui, _screen, _palette, _audio, resourceName); + Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _screen, _palette, _audio, resourceName); // TODO: cache portraits // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates // on kDrawCel, yeah this whole stuff makes sense) diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 3b2ffd6fc2..f54b8059c1 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -26,7 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT16_H #define SCI_GRAPHICS_PAINT16_H -#include "sci/graphics/gui.h" #include "sci/graphics/paint.h" #include "common/hashmap.h" @@ -45,7 +44,7 @@ class GfxView; */ class GfxPaint16 : public GfxPaint { public: - GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, SciGui *gui, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); + GfxPaint16(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, GfxCache *cache, GfxPorts *ports, GfxCoordAdjuster *coordAdjuster, GfxScreen *screen, GfxPalette *palette, GfxTransitions *transitions, AudioPlayer *audio); ~GfxPaint16(); void init(GfxAnimate *animate, GfxText16 *text16); @@ -100,7 +99,6 @@ private: SegManager *_segMan; Kernel *_kernel; AudioPlayer *_audio; - SciGui *_gui; GfxAnimate *_animate; GfxCache *_cache; GfxPorts *_ports; diff --git a/engines/sci/graphics/paint32.cpp b/engines/sci/graphics/paint32.cpp index 711efc9816..9b24da413b 100644 --- a/engines/sci/graphics/paint32.cpp +++ b/engines/sci/graphics/paint32.cpp @@ -38,6 +38,7 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" +#include "sci/graphics/robot.h" namespace Sci { @@ -79,4 +80,10 @@ void GfxPaint32::kernelGraphDrawLine(Common::Point startPoint, Common::Point end _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); } +void GfxPaint32::debugDrawRobot(GuiResourceId robotId) { + GfxRobot *test = new GfxRobot(g_sci->getResMan(), _screen, robotId); + test->draw(); + delete test; +} + } // End of namespace Sci diff --git a/engines/sci/graphics/paint32.h b/engines/sci/graphics/paint32.h index f4d6340361..a048d7f307 100644 --- a/engines/sci/graphics/paint32.h +++ b/engines/sci/graphics/paint32.h @@ -26,7 +26,6 @@ #ifndef SCI_GRAPHICS_PAINT32_H #define SCI_GRAPHICS_PAINT32_H -#include "sci/graphics/gui.h" #include "sci/graphics/paint.h" #include "common/hashmap.h" @@ -49,6 +48,8 @@ public: void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle); void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); + void debugDrawRobot(GuiResourceId robotId); + private: ResourceManager *_resMan; SegManager *_segMan; diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index a85d9a3b06..f7d6f4de0a 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -31,7 +31,6 @@ #include "sci/sci.h" #include "sci/event.h" #include "sci/engine/state.h" -#include "sci/graphics/gui.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/portrait.h" @@ -39,8 +38,8 @@ namespace Sci { -Portrait::Portrait(ResourceManager *resMan, EventManager *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) - : _resMan(resMan), _event(event), _gui(gui), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) { +Portrait::Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName) + : _resMan(resMan), _event(event), _screen(screen), _palette(palette), _audio(audio), _resourceName(resourceName) { init(); } diff --git a/engines/sci/graphics/portrait.h b/engines/sci/graphics/portrait.h index 2f23ced913..7da9425c9d 100644 --- a/engines/sci/graphics/portrait.h +++ b/engines/sci/graphics/portrait.h @@ -42,7 +42,7 @@ struct PortraitBitmap { */ class Portrait { public: - Portrait(ResourceManager *resMan, EventManager *event, SciGui *gui, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); + Portrait(ResourceManager *resMan, EventManager *event, GfxScreen *screen, GfxPalette *palette, AudioPlayer *audio, Common::String resourceName); ~Portrait(); void setupAudio(uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq); @@ -57,7 +57,6 @@ private: ResourceManager *_resMan; EventManager *_event; - SciGui *_gui; GfxPalette *_palette; GfxScreen *_screen; AudioPlayer *_audio; diff --git a/engines/sci/graphics/robot.cpp b/engines/sci/graphics/robot.cpp index 2f711eb58a..d926e037f4 100644 --- a/engines/sci/graphics/robot.cpp +++ b/engines/sci/graphics/robot.cpp @@ -31,17 +31,17 @@ namespace Sci { #ifdef ENABLE_SCI32 -Robot::Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) +GfxRobot::GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId) : _resMan(resMan), _screen(screen), _resourceId(resourceId) { assert(resourceId != -1); initData(resourceId); } -Robot::~Robot() { +GfxRobot::~GfxRobot() { _resMan->unlockResource(_resource); } -void Robot::initData(GuiResourceId resourceId) { +void GfxRobot::initData(GuiResourceId resourceId) { _resource = _resMan->findResource(ResourceId(kResourceTypeRobot, resourceId), true); if (!_resource) { error("robot resource %d not found", resourceId); @@ -158,7 +158,7 @@ void Robot::initData(GuiResourceId resourceId) { // TODO: just trying around in here... -void Robot::draw() { +void GfxRobot::draw() { byte *bitmapData = _resourceData + ROBOT_FILE_STARTOFDATA; int x, y; //int frame; diff --git a/engines/sci/graphics/robot.h b/engines/sci/graphics/robot.h index 009b76a91c..80dae95f95 100644 --- a/engines/sci/graphics/robot.h +++ b/engines/sci/graphics/robot.h @@ -31,10 +31,10 @@ namespace Sci { #define ROBOT_FILE_STARTOFDATA 58 #ifdef ENABLE_SCI32 -class Robot { +class GfxRobot { public: - Robot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); - ~Robot(); + GfxRobot(ResourceManager *resMan, GfxScreen *screen, GuiResourceId resourceId); + ~GfxRobot(); void draw(); diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 0bb1a87fc2..9f8d4d1164 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -31,15 +31,14 @@ #include "sci/sci.h" #include "sci/engine/state.h" -#include "sci/graphics/gui.h" #include "sci/graphics/screen.h" #include "sci/graphics/palette.h" #include "sci/graphics/transitions.h" namespace Sci { -GfxTransitions::GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA) - : _gui(gui), _screen(screen), _palette(palette), _isVGA(isVGA) { +GfxTransitions::GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA) + : _screen(screen), _palette(palette), _isVGA(isVGA) { init(); } diff --git a/engines/sci/graphics/transitions.h b/engines/sci/graphics/transitions.h index 9a1a412d5b..788cefabca 100644 --- a/engines/sci/graphics/transitions.h +++ b/engines/sci/graphics/transitions.h @@ -65,7 +65,7 @@ class Screen; */ class GfxTransitions { public: - GfxTransitions(SciGui *gui, GfxScreen *screen, GfxPalette *palette, bool isVGA); + GfxTransitions(GfxScreen *screen, GfxPalette *palette, bool isVGA); ~GfxTransitions(); void setup(int16 number, bool blackoutFlag); @@ -92,7 +92,6 @@ private: void diagonalRollToCenter(bool blackoutFlag); void updateScreenAndWait(int msec); - SciGui *_gui; GfxScreen *_screen; GfxPalette *_palette; diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 4860ac7c2f..792522f153 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -43,7 +43,6 @@ MODULE_OBJS := \ graphics/cursor.o \ graphics/font.o \ graphics/fontsjis.o \ - graphics/gui.o \ graphics/maciconbar.o \ graphics/menu.o \ graphics/paint.o \ @@ -78,7 +77,6 @@ ifdef ENABLE_SCI32 MODULE_OBJS += \ engine/kernel32.o \ graphics/frameout.o \ - graphics/gui32.o \ graphics/paint32.o \ graphics/robot.o \ video/vmd_decoder.o diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 692928f12c..4af6bc7b43 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -44,18 +44,24 @@ #include "sci/sound/audio.h" #include "sci/sound/soundcmd.h" -#include "sci/graphics/gui.h" +#include "sci/graphics/animate.h" +#include "sci/graphics/cache.h" +#include "sci/graphics/compare.h" +#include "sci/graphics/controls.h" +#include "sci/graphics/coordadjuster.h" +#include "sci/graphics/cursor.h" #include "sci/graphics/maciconbar.h" #include "sci/graphics/menu.h" #include "sci/graphics/paint16.h" +#include "sci/graphics/paint32.h" #include "sci/graphics/ports.h" #include "sci/graphics/palette.h" -#include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" -#include "sci/graphics/cache.h" +#include "sci/graphics/text16.h" +#include "sci/graphics/transitions.h" #ifdef ENABLE_SCI32 -#include "sci/graphics/gui32.h" +#include "sci/graphics/frameout.h" #endif namespace Sci { @@ -183,9 +189,29 @@ Common::Error SciEngine::run() { if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) upscaledHires = GFX_SCREEN_UPSCALED_640x400; + // Reset all graphics objects + _gfxAnimate = 0; + _gfxCache = 0; + _gfxCompare = 0; + _gfxControls = 0; + _gfxCoordAdjuster = 0; + _gfxCursor = 0; + _gfxMacIconBar = 0; + _gfxMenu = 0; + _gfxPaint = 0; + _gfxPaint16 = 0; + _gfxPalette = 0; + _gfxPorts = 0; + _gfxScreen = 0; + _gfxText16 = 0; + _gfxTransitions = 0; +#ifdef ENABLE_SCI32 + _gfxFrameout = 0; + _gfxPaint32 = 0; +#endif + // Initialize graphics-related parts - // invokes initGraphics() if (_resMan->detectHires()) _gfxScreen = new GfxScreen(_resMan, 640, 480); else @@ -222,23 +248,30 @@ Common::Error SciEngine::run() { #ifdef ENABLE_SCI32 if (getSciVersion() >= SCI_VERSION_2) { - _gfxAnimate = 0; - _gfxControls = 0; - _gfxMenu = 0; - _gfxPaint16 = 0; - _gfxPorts = 0; - _gfxText16 = 0; - _gui = 0; - _gui32 = new SciGui32(_gamestate->_segMan, _eventMan, _gfxScreen, _gfxPalette, _gfxCache, _gfxCursor); + // SCI32 graphic objects creation + _gfxCoordAdjuster = new GfxCoordAdjuster32(segMan); + _gfxCursor->init(_gfxCoordAdjuster, _eventMan); + _gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); + _gfxPaint = _gfxPaint32; + _gfxFrameout = new GfxFrameout(segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); } else { #endif + // SCI0-SCI1.1 graphic objects creation _gfxPorts = new GfxPorts(segMan, _gfxScreen); - _gui = new SciGui(_gamestate, _gfxScreen, _gfxPalette, _gfxCache, _gfxCursor, _gfxPorts, _audio); -#ifdef ENABLE_SCI32 - _gui32 = 0; - _gfxFrameout = 0; + _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); + _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); + _gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); + _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); + _gfxPaint = _gfxPaint16; + _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); + _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); + _gfxControls = new GfxControls(segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); + _gfxMenu = new GfxMenu(g_sci->getEventManager(), segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); - g_sci->_gfxMenu->reset(); + _gfxMenu->reset(); +#ifdef ENABLE_SCI32 } #endif @@ -272,15 +305,23 @@ Common::Error SciEngine::run() { ConfMan.flushToDisk(); delete _gamestate->_soundCmd; - delete _gui; #ifdef ENABLE_SCI32 - delete _gui32; + delete _gfxFrameout; #endif + delete _gfxMenu; + delete _gfxControls; + delete _gfxText16; + delete _gfxAnimate; + delete _gfxPaint; + delete _gfxTransitions; + delete _gfxCompare; + delete _gfxCoordAdjuster; delete _gfxPorts; delete _gfxCache; delete _gfxPalette; delete _gfxCursor; delete _gfxScreen; + delete _eventMan; delete segMan; delete _gamestate; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 6f6a6b5dd1..7d04840759 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -60,15 +60,16 @@ class GfxCompare; class GfxControls; class GfxCoordAdjuster; class GfxCursor; +class GfxMacIconBar; class GfxMenu; class GfxPaint; class GfxPaint16; +class GfxPaint32; class GfxPalette; class GfxPorts; class GfxScreen; class GfxText16; -class SciGui; -class GfxMacIconBar; +class GfxTransitions; #ifdef ENABLE_SCI32 class SciGui32; @@ -207,14 +208,14 @@ public: GfxPalette *_gfxPalette; GfxPaint *_gfxPaint; GfxPaint16 *_gfxPaint16; // Painting in 16-bit gfx + GfxPaint32 *_gfxPaint32; // Painting in 32-bit gfx GfxPorts *_gfxPorts; // Port managment for 16-bit gfx GfxScreen *_gfxScreen; GfxText16 *_gfxText16; - SciGui *_gui; /* Currently active Gui */ + GfxTransitions *_gfxTransitions; // transitions between screens for 16-bit gfx GfxMacIconBar *_gfxMacIconBar; // Mac Icon Bar manager #ifdef ENABLE_SCI32 - SciGui32 *_gui32; // GUI for SCI32 games GfxFrameout *_gfxFrameout; // kFrameout and the like for 32-bit gfx #endif -- cgit v1.2.3 From 90408a59cca70c9890f7b32bc0788f8c0418bad7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 16:36:09 +0000 Subject: Don't adjust the object's coordinates if the object does not belong to a plane in kIsOnMe(). It's now possible to start the interactive part of the Phantasmagoria 1 demo svn-id: r49862 --- engines/sci/engine/kernel32.cpp | 32 +++++++++++++++++--------------- 1 file changed, 17 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index b42e0c4144..a077f110cf 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -834,22 +834,24 @@ reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { // Get the object's plane reg_t planeObject = readSelector(s->_segMan, targetObject, SELECTOR(plane)); - uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY)); - uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX)); - uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top)); - uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left)); - planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; - planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; - - // Adjust the bounding rectangle of the object by the object's actual X, Y coordinates - uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); - uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY); - itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX); - itemY += planeTop; - itemX += planeLeft; + if (!planeObject.isNull()) { + uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); + uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); + uint16 planeResY = readSelectorValue(s->_segMan, planeObject, SELECTOR(resY)); + uint16 planeResX = readSelectorValue(s->_segMan, planeObject, SELECTOR(resX)); + uint16 planeTop = readSelectorValue(s->_segMan, planeObject, SELECTOR(top)); + uint16 planeLeft = readSelectorValue(s->_segMan, planeObject, SELECTOR(left)); + planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; + planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; + + // Adjust the bounding rectangle of the object by the object's actual X, Y coordinates + itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY); + itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX); + itemY += planeTop; + itemX += planeLeft; - nsRect.translate(itemX, itemY); + nsRect.translate(itemX, itemY); + } //warning("kIsOnMe: (%d, %d) on object %04x:%04x, parameter %d", argv[0].toUint16(), argv[1].toUint16(), PRINT_REG(argv[2]), argv[3].toUint16()); -- cgit v1.2.3 From b8d9cf27737f13937b5950b72d7911cf5281e7c5 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 16:50:10 +0000 Subject: SCI: Pass resman to scanSource() methods svn-id: r49863 --- engines/sci/resource.cpp | 24 +++++++++--------------- engines/sci/resource_intern.h | 12 ++++++------ 2 files changed, 15 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 24e92060e2..e167d50c1a 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -437,15 +437,14 @@ void ResourceSource::loadResource(Resource *res) { fileStream->seek(res->_fileOffset, SEEK_SET); int error = res->decompress(fileStream); - - if (_resourceFile) - delete fileStream; - if (error) { warning("Error %d occurred while reading %s from resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); res->unalloc(); } + + if (_resourceFile) + delete fileStream; } Resource *ResourceManager::testResource(ResourceId id) { @@ -623,13 +622,12 @@ void ResourceManager::scanNewSources() { if (!source->_scanned) { source->_scanned = true; - source->scanSource(); + source->scanSource(this); } } } -void DirectoryResourceSource::scanSource() { - ResourceManager *resMan = g_sci->getResMan(); +void DirectoryResourceSource::scanSource(ResourceManager *resMan) { resMan->readResourcePatches(); // We can't use getSciVersion() at this point, thus using _volVersion @@ -639,21 +637,18 @@ void DirectoryResourceSource::scanSource() { resMan->readWaveAudioPatches(); } -void ExtMapResourceSource::scanSource() { - ResourceManager *resMan = g_sci->getResMan(); +void ExtMapResourceSource::scanSource(ResourceManager *resMan) { if (resMan->_mapVersion < kResVersionSci1Late) resMan->readResourceMapSCI0(this); else resMan->readResourceMapSCI1(this); } -void ExtAudioMapResourceSource::scanSource() { - ResourceManager *resMan = g_sci->getResMan(); +void ExtAudioMapResourceSource::scanSource(ResourceManager *resMan) { resMan->readAudioMapSCI1(this); } -void IntMapResourceSource::scanSource() { - ResourceManager *resMan = g_sci->getResMan(); +void IntMapResourceSource::scanSource(ResourceManager *resMan) { resMan->readAudioMapSCI11(this); } @@ -1441,8 +1436,7 @@ static uint32 resTypeToMacTag(ResourceType type) { return 0; } -void MacResourceForkResourceSource::scanSource() { - ResourceManager *resMan = g_sci->getResMan(); +void MacResourceForkResourceSource::scanSource(ResourceManager *resMan) { if (!_macResMan->open(getLocationName().c_str())) error("%s is not a valid Mac resource fork", getLocationName().c_str()); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 8cb13bd311..7993fc303e 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -78,7 +78,7 @@ public: /** * Scan this source for TODO. */ - virtual void scanSource() {} + virtual void scanSource(ResourceManager *resMan) {} /** * Load a resource. @@ -95,7 +95,7 @@ class DirectoryResourceSource : public ResourceSource { public: DirectoryResourceSource(const Common::String &name) : ResourceSource(kSourceDirectory, name) {} - virtual void scanSource(); + virtual void scanSource(ResourceManager *resMan); }; class PatchResourceSource : public ResourceSource { @@ -131,7 +131,7 @@ public: : ResourceSource(kSourceExtMap, name, volNum, resFile) { } - virtual void scanSource(); + virtual void scanSource(ResourceManager *resMan); }; class IntMapResourceSource : public ResourceSource { @@ -140,7 +140,7 @@ public: : ResourceSource(kSourceIntMap, name, volNum) { } - virtual void scanSource(); + virtual void scanSource(ResourceManager *resMan); }; class AudioVolumeResourceSource : public VolumeResourceSource { @@ -162,7 +162,7 @@ public: : ResourceSource(kSourceExtAudioMap, name, volNum) { } - virtual void scanSource(); + virtual void scanSource(ResourceManager *resMan); }; class WaveResourceSource : public ResourceSource { @@ -183,7 +183,7 @@ public: MacResourceForkResourceSource(const Common::String &name, int volNum); ~MacResourceForkResourceSource(); - virtual void scanSource(); + virtual void scanSource(ResourceManager *resMan); virtual void loadResource(Resource *res); }; -- cgit v1.2.3 From cf38303497e00744fbd7c95bbd711d25cac1c6c4 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 15 Jun 2010 16:56:23 +0000 Subject: Don't disable kPalVary for SCI32, the semantics have remained the same. svn-id: r49865 --- engines/sci/engine/kgraphics.cpp | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c7126127ca..f56c5bb5e1 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -632,10 +632,6 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); - // Exit for SCI32 for now - if (!g_sci->_gfxPaint16) - return s->r_acc; - switch (operation) { case 0: { // Init GuiResourceId paletteId; -- cgit v1.2.3 From 831e626ccd488df9e8c3d534bf129c48e66f18e0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 16:58:03 +0000 Subject: SDL: only change mouse cursor, when mouse is currently within our window, also enable mouse position changing again for SCI svn-id: r49866 --- engines/sci/graphics/cursor.cpp | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 14ab3fcdaf..38e9d389a6 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -219,6 +219,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // TODO: What about the 2000 resources? Inventory items? How to handle? // TODO: What games does this work for? At least it does for KQ6. // TODO: Stop asking rhetorical questions. + // TODO: It was fred all along! Resource *resource = _resMan->findResource(ResourceId(kResourceTypeCursor, 1000 + celNum), false); @@ -258,16 +259,12 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu } void GfxCursor::setPosition(Common::Point pos) { - // This code has been disabled because it's annoying in windowed mode. The engine shouldn't move - // the mouse cursor whenever it wants, it interferes with other programs -#if 0 if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); } else { _screen->adjustToUpscaledCoordinates(pos.y, pos.x); g_system->warpMouse(pos.x, pos.y); } -#endif } Common::Point GfxCursor::getPosition() { @@ -293,9 +290,6 @@ Common::Point GfxCursor::getPosition() { } void GfxCursor::refreshPosition() { - // This code has been disabled because it's annoying in windowed mode. The engine shouldn't move - // the mouse cursor whenever it wants, it interferes with other programs -#if 0 bool clipped = false; Common::Point mousePoint = getPosition(); @@ -318,7 +312,6 @@ void GfxCursor::refreshPosition() { // FIXME: Do this only when mouse is grabbed? if (clipped) setPosition(mousePoint); -#endif } void GfxCursor::kernelSetMoveZone(Common::Rect zone) { -- cgit v1.2.3 From 7c7054dbd1697b95634979f05d4a7b153bb17082 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 15 Jun 2010 17:14:38 +0000 Subject: Remove unnecessary svn:executable properties svn-id: r49870 --- engines/agi/sound_coco3.h | 0 engines/agi/sound_midi.cpp | 0 engines/agi/sound_midi.h | 0 engines/agi/sound_pcjr.cpp | 0 engines/agi/sound_pcjr.h | 0 engines/agi/sound_sarien.h | 0 engines/drascula/console.cpp | 0 engines/drascula/console.h | 0 8 files changed, 0 insertions(+), 0 deletions(-) mode change 100755 => 100644 engines/agi/sound_coco3.h mode change 100755 => 100644 engines/agi/sound_midi.cpp mode change 100755 => 100644 engines/agi/sound_midi.h mode change 100755 => 100644 engines/agi/sound_pcjr.cpp mode change 100755 => 100644 engines/agi/sound_pcjr.h mode change 100755 => 100644 engines/agi/sound_sarien.h mode change 100755 => 100644 engines/drascula/console.cpp mode change 100755 => 100644 engines/drascula/console.h (limited to 'engines') diff --git a/engines/agi/sound_coco3.h b/engines/agi/sound_coco3.h old mode 100755 new mode 100644 diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp old mode 100755 new mode 100644 diff --git a/engines/agi/sound_midi.h b/engines/agi/sound_midi.h old mode 100755 new mode 100644 diff --git a/engines/agi/sound_pcjr.cpp b/engines/agi/sound_pcjr.cpp old mode 100755 new mode 100644 diff --git a/engines/agi/sound_pcjr.h b/engines/agi/sound_pcjr.h old mode 100755 new mode 100644 diff --git a/engines/agi/sound_sarien.h b/engines/agi/sound_sarien.h old mode 100755 new mode 100644 diff --git a/engines/drascula/console.cpp b/engines/drascula/console.cpp old mode 100755 new mode 100644 diff --git a/engines/drascula/console.h b/engines/drascula/console.h old mode 100755 new mode 100644 -- cgit v1.2.3 From c9ba23f2b461c40c1b985faa4091c9363d20163c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 17:41:33 +0000 Subject: SCI: only set mouse position, when cursor is visible (fixes non-stop, but escapeable mouse position setting to 0, 0 in eco quest 1 floppy during intro) svn-id: r49874 --- engines/sci/graphics/cursor.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 38e9d389a6..46bd981b7f 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -259,6 +259,13 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu } void GfxCursor::setPosition(Common::Point pos) { + // Don't set position, when cursor is not visible + // This fixes eco quest 1 (floppy) right at the start, which is setting mouse cursor to 0, 0 all the time during the + // intro. It's escapeable (now) by moving to the left or top, but it's getting on your nerves. + // This could theoretically break some things, although sierra normally sets position only when showing the cursor. + if (!_isVisible) + return; + if (!_upscaledHires) { g_system->warpMouse(pos.x, pos.y); } else { -- cgit v1.2.3 From 93df097f39dda7b1b0d68a94d0f06b01b9b834b4 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Tue, 15 Jun 2010 18:17:51 +0000 Subject: Added the same quit/restart test to print() as we have in so many other places. This makes it easier to quit the game during the text box in the King's Quest 3 into, and probably other places as well. svn-id: r49881 --- engines/agi/text.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/text.cpp b/engines/agi/text.cpp index 36a289c47b..778da0a527 100644 --- a/engines/agi/text.cpp +++ b/engines/agi/text.cpp @@ -489,7 +489,7 @@ int AgiEngine::print(const char *p, int lin, int col, int len) { _game.keypress = 0; break; } - } while (_game.msgBoxTicks > 0); + } while (_game.msgBoxTicks > 0 && !(shouldQuit() || _restartGame)); setvar(vWindowReset, 0); -- cgit v1.2.3 From 9938661ffaa5923069fe5ee9e8f2ecb96a961ff5 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 15 Jun 2010 18:36:05 +0000 Subject: Surface is a struct, not a class svn-id: r49883 --- engines/groovie/script.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/groovie/script.h b/engines/groovie/script.h index 43b7c06a54..cda87a8917 100644 --- a/engines/groovie/script.h +++ b/engines/groovie/script.h @@ -34,7 +34,7 @@ class SeekableReadStream; } namespace Graphics { -class Surface; +struct Surface; } namespace Groovie { -- cgit v1.2.3 From fea248ae2f0c2659d84bd8ec400530a6c5e5bc22 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 15 Jun 2010 20:23:25 +0000 Subject: SCI: make umlauts work in kFrameout for sci32 svn-id: r49890 --- engines/sci/graphics/frameout.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index d794fad39e..f16f1068a9 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -265,14 +265,15 @@ void GfxFrameout::kernelFrameout() { uint16 curX = itemEntry->x; uint16 curY = itemEntry->y; for (uint32 i = 0; i < text.size(); i++) { + unsigned char curChar = text[i]; // TODO: proper text splitting... this is a hack - if ((text[i] == ' ' && i > 0 && text[i - i] == ' ') || text[i] == '\n' || - (curX + font->getCharWidth(text[i]) > _screen->getWidth())) { + if ((curChar == ' ' && i > 0 && text[i - i] == ' ') || curChar == '\n' || + (curX + font->getCharWidth(curChar) > _screen->getWidth())) { curY += font->getHeight(); curX = itemEntry->x; } - font->draw(text[i], curY, curX, foreColor, dimmed); - curX += font->getCharWidth(text[i]); + font->draw(curChar, curY, curX, foreColor, dimmed); + curX += font->getCharWidth(curChar); } delete font; } -- cgit v1.2.3 From 444a6b5976f1f5b41db1db94ae16a8987fff134c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 15 Jun 2010 23:12:34 +0000 Subject: Workaround bug #3003643 (MI1EGA German: Credit text incorrect) svn-id: r49895 --- engines/scumm/script_v5.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/scumm/script_v5.cpp b/engines/scumm/script_v5.cpp index b1545db0f3..5c20e0dfd3 100644 --- a/engines/scumm/script_v5.cpp +++ b/engines/scumm/script_v5.cpp @@ -2594,6 +2594,17 @@ void ScummEngine_v5::decodeParseString() { else strcpy((char *)tmpBuf+16, "^19^"); printString(textSlot, tmpBuf); + } else if (_game.id == GID_MONKEY_EGA && _roomResource == 30 && vm.slot[_currentScript].number == 411 && + strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT")) { + // WORKAROUND for bug #3003643 (MI1EGA German: Credit text incorrect) + // The script contains buggy text. + const char *tmp = strstr((const char *)_scriptPointer, "NCREDIT-NOTE-AMOUNT"); + char tmpBuf[256]; + const int diff = tmp - (const char *)_scriptPointer; + memcpy(tmpBuf, _scriptPointer, diff); + strcpy(tmpBuf + diff, "5000"); + strcpy(tmpBuf + diff + 4, tmp + sizeof("NCREDIT-NOTE-AMOUNT") - 1); + printString(textSlot, (byte *)tmpBuf); } else { printString(textSlot, _scriptPointer); } -- cgit v1.2.3 From e7275161f431d0025a7e2bb47bc2d442670fd155 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Wed, 16 Jun 2010 00:24:16 +0000 Subject: SCI: Avoid using g_sci in resman (as it might not yet be inited) svn-id: r49897 --- engines/sci/resource.cpp | 40 +++++++++++++++++++--------------------- engines/sci/resource.h | 24 ++++++++++++------------ engines/sci/resource_audio.cpp | 6 +++--- engines/sci/resource_intern.h | 14 +++++++------- 4 files changed, 41 insertions(+), 43 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index e167d50c1a..bda854cfd0 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -319,11 +319,11 @@ Common::SeekableReadStream *ResourceManager::getVolumeFile(ResourceSource *sourc static uint32 resTypeToMacTag(ResourceType type); void ResourceManager::loadResource(Resource *res) { - res->_source->loadResource(res); + res->_source->loadResource(this, res); } -void PatchResourceSource::loadResource(Resource *res) { +void PatchResourceSource::loadResource(ResourceManager *resMan, Resource *res) { bool result = res->loadFromPatchFile(); if (!result) { // TODO: We used to fallback to the "default" code here if loadFromPatchFile @@ -333,13 +333,13 @@ void PatchResourceSource::loadResource(Resource *res) { } } -void MacResourceForkResourceSource::loadResource(Resource *res) { +void MacResourceForkResourceSource::loadResource(ResourceManager *resMan, Resource *res) { Common::SeekableReadStream *stream = _macResMan->getResource(resTypeToMacTag(res->getType()), res->getNumber()); if (!stream) error("Could not get Mac resource fork resource: %d %d", res->getType(), res->getNumber()); - int error = res->decompress(stream); + int error = res->decompress(resMan->getVolVersion(), stream); if (error) { warning("Error %d occurred while reading %s from Mac resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -347,8 +347,7 @@ void MacResourceForkResourceSource::loadResource(Resource *res) { } } -Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res) { - ResourceManager *resMan = g_sci->getResMan(); +Common::SeekableReadStream *ResourceSource::getVolumeFile(ResourceManager *resMan, Resource *res) { Common::SeekableReadStream *fileStream = resMan->getVolumeFile(this); if (!fileStream) { @@ -360,8 +359,8 @@ Common::SeekableReadStream *ResourceSource::getVolumeFile(Resource *res) { return fileStream; } -void WaveResourceSource::loadResource(Resource *res) { - Common::SeekableReadStream *fileStream = getVolumeFile(res); +void WaveResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); if (!fileStream) return; @@ -371,8 +370,8 @@ void WaveResourceSource::loadResource(Resource *res) { delete fileStream; } -void AudioVolumeResourceSource::loadResource(Resource *res) { - Common::SeekableReadStream *fileStream = getVolumeFile(res); +void AudioVolumeResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); if (!fileStream) return; @@ -429,14 +428,14 @@ void AudioVolumeResourceSource::loadResource(Resource *res) { delete fileStream; } -void ResourceSource::loadResource(Resource *res) { - Common::SeekableReadStream *fileStream = getVolumeFile(res); +void ResourceSource::loadResource(ResourceManager *resMan, Resource *res) { + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, res); if (!fileStream) return; fileStream->seek(res->_fileOffset, SEEK_SET); - int error = res->decompress(fileStream); + int error = res->decompress(resMan->getVolVersion(), fileStream); if (error) { warning("Error %d occurred while reading %s from resource file: %s", error, res->_id.toString().c_str(), sci_error_types[error]); @@ -606,9 +605,9 @@ int ResourceManager::addInternalSources() { ResourceSource *src = addSource(new IntMapResourceSource("MAP", itr->getNumber())); if ((itr->getNumber() == 65535) && Common::File::exists("RESOURCE.SFX")) - addSource(new AudioVolumeResourceSource("RESOURCE.SFX", src, 0)); + addSource(new AudioVolumeResourceSource(this, "RESOURCE.SFX", src, 0)); else if (Common::File::exists("RESOURCE.AUD")) - addSource(new AudioVolumeResourceSource("RESOURCE.AUD", src, 0)); + addSource(new AudioVolumeResourceSource(this, "RESOURCE.AUD", src, 0)); ++itr; } @@ -1506,7 +1505,7 @@ Resource *ResourceManager::updateResource(ResourceId resId, ResourceSource *src, return res; } -int Resource::readResourceInfo(Common::SeekableReadStream *file, +int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression) { // SCI0 volume format: {wResId wPacked+4 wUnpacked wCompression} = 8 bytes // SCI1 volume format: {bResType wResNumber wPacked+4 wUnpacked wCompression} = 9 bytes @@ -1516,8 +1515,7 @@ int Resource::readResourceInfo(Common::SeekableReadStream *file, uint32 wCompression, szUnpacked; ResourceType type; - ResourceManager *resMan = g_sci->getResMan(); - switch (resMan->getVolVersion()) { + switch (volVersion) { case kResVersionSci0Sci1Early: case kResVersionSci1Middle: w = file->readUint16LE(); @@ -1604,13 +1602,13 @@ int Resource::readResourceInfo(Common::SeekableReadStream *file, return compression == kCompUnknown ? SCI_ERROR_UNKNOWN_COMPRESSION : 0; } -int Resource::decompress(Common::SeekableReadStream *file) { +int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file) { int error; uint32 szPacked = 0; ResourceCompression compression = kCompUnknown; // fill resource info - error = readResourceInfo(file, szPacked, compression); + error = readResourceInfo(volVersion, file, szPacked, compression); if (error) return error; @@ -1675,7 +1673,7 @@ ResourceCompression ResourceManager::getViewCompression() { uint32 szPacked; ResourceCompression compression; - if (res->readResourceInfo(fileStream, szPacked, compression)) { + if (res->readResourceInfo(_volVersion, fileStream, szPacked, compression)) { if (res->_source->_resourceFile) delete fileStream; continue; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 9cf7120ed7..13eb6567ab 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -110,6 +110,16 @@ enum ResourceType { const char *getResourceTypeName(ResourceType restype); +enum ResVersion { + kResVersionUnknown, + kResVersionSci0Sci1Early, + kResVersionSci1Middle, + kResVersionSci1Late, + kResVersionSci11, + kResVersionSci11Mac, + kResVersionSci32 +}; + class ResourceManager; class ResourceSource; @@ -223,22 +233,12 @@ protected: bool loadFromWaveFile(Common::SeekableReadStream *file); bool loadFromAudioVolumeSCI1(Common::SeekableReadStream *file); bool loadFromAudioVolumeSCI11(Common::SeekableReadStream *file); - int decompress(Common::SeekableReadStream *file); - int readResourceInfo(Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); + int decompress(ResVersion volVersion, Common::SeekableReadStream *file); + int readResourceInfo(ResVersion volVersion, Common::SeekableReadStream *file, uint32 &szPacked, ResourceCompression &compression); }; typedef Common::HashMap ResourceMap; -enum ResVersion { - kResVersionUnknown, - kResVersionSci0Sci1Early, - kResVersionSci1Middle, - kResVersionSci1Late, - kResVersionSci11, - kResVersionSci11Mac, - kResVersionSci32 -}; - class ResourceManager { // FIXME: These 'friend' declarations are meant to be a temporary hack to // ease transition to the ResourceSource class system. diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index fc30047e1c..c98b5387be 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -34,7 +34,7 @@ namespace Sci { -AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum) +AudioVolumeResourceSource::AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum) : VolumeResourceSource(name, map, volNum, kSourceAudioVolume) { _audioCompressionType = 0; @@ -46,7 +46,7 @@ AudioVolumeResourceSource::AudioVolumeResourceSource(const Common::String &name, * table for later usage. */ - Common::SeekableReadStream *fileStream = getVolumeFile(0); + Common::SeekableReadStream *fileStream = getVolumeFile(resMan, 0); if (!fileStream) return; @@ -439,7 +439,7 @@ void ResourceManager::setAudioLanguage(int language) { const char *dot = strrchr(name.c_str(), '.'); int number = atoi(dot + 1); - addSource(new AudioVolumeResourceSource(name, _audioMapSCI1, number)); + addSource(new AudioVolumeResourceSource(this, name, _audioMapSCI1, number)); } scanNewSources(); diff --git a/engines/sci/resource_intern.h b/engines/sci/resource_intern.h index 7993fc303e..45421dd722 100644 --- a/engines/sci/resource_intern.h +++ b/engines/sci/resource_intern.h @@ -66,7 +66,7 @@ public: const Common::String &getLocationName() const { return _name; } // Auxiliary method, used by loadResource implementations. - Common::SeekableReadStream *getVolumeFile(Resource *res); + Common::SeekableReadStream *getVolumeFile(ResourceManager *resMan, Resource *res); /** * TODO: Document this @@ -83,7 +83,7 @@ public: /** * Load a resource. */ - virtual void loadResource(Resource *res); + virtual void loadResource(ResourceManager *resMan, Resource *res); // FIXME: This audio specific method is a hack. After all, why should a // ResourceSource or a Resource (which uses this method) have audio @@ -102,7 +102,7 @@ class PatchResourceSource : public ResourceSource { public: PatchResourceSource(const Common::String &name) : ResourceSource(kSourcePatch, name) {} - virtual void loadResource(Resource *res); + virtual void loadResource(ResourceManager *resMan, Resource *res); }; class VolumeResourceSource : public ResourceSource { @@ -149,9 +149,9 @@ protected: int32 *_audioCompressionOffsetMapping; public: - AudioVolumeResourceSource(const Common::String &name, ResourceSource *map, int volNum); + AudioVolumeResourceSource(ResourceManager *resMan, const Common::String &name, ResourceSource *map, int volNum); - virtual void loadResource(Resource *res); + virtual void loadResource(ResourceManager *resMan, Resource *res); virtual uint32 getAudioCompressionType() const; }; @@ -169,7 +169,7 @@ class WaveResourceSource : public ResourceSource { public: WaveResourceSource(const Common::String &name) : ResourceSource(kSourceWave, name) {} - virtual void loadResource(Resource *res); + virtual void loadResource(ResourceManager *resMan, Resource *res); }; /** @@ -185,7 +185,7 @@ public: virtual void scanSource(ResourceManager *resMan); - virtual void loadResource(Resource *res); + virtual void loadResource(ResourceManager *resMan, Resource *res); }; } // End of namespace Sci -- cgit v1.2.3 From af65de6e1aaa197e17f10cd976ea2f5d15f0d7c8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 16 Jun 2010 21:02:58 +0000 Subject: SCI: implement channel remapping for SCI1 svn-id: r49905 --- engines/sci/console.cpp | 3 +- engines/sci/resource.h | 4 -- engines/sci/resource_audio.cpp | 3 -- engines/sci/sound/midiparser_sci.cpp | 76 ++++++++++++++++++++++++------------ engines/sci/sound/midiparser_sci.h | 25 ++++-------- engines/sci/sound/music.cpp | 64 +++++++++++++----------------- engines/sci/sound/music.h | 13 ++---- 7 files changed, 91 insertions(+), 97 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 8fc49fa396..ebe7edecbe 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -859,7 +859,8 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { SciVersion doSoundVersion = _engine->_features->detectDoSoundType(); MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion); - MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion); + MidiParser_SCI *parser; // = new MidiParser_SCI(doSoundVersion); + // FIXME: add SciMusic object parser->setMidiDriver(player); Common::List *resources = _engine->getResMan()->listResources(kResourceTypeSound); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 13eb6567ab..b37f71832d 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -513,7 +513,6 @@ public: Track *getDigitalTrack(); int getChannelFilterMask(int hardwareMask, bool wantsRhythm); byte getInitialVoiceCount(byte channel); - bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); } private: SciVersion _soundVersion; @@ -521,9 +520,6 @@ private: Track *_tracks; Resource *_innerResource; ResourceManager *_resMan; - uint16 _channelsUsed; - - void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); } }; } // End of namespace Sci diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index c98b5387be..72fd8f4594 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -461,8 +461,6 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi byte *dataEnd; Channel *channel, *sampleChannel; - _channelsUsed = 0; - switch (_soundVersion) { case SCI_VERSION_0_EARLY: case SCI_VERSION_0_LATE: @@ -552,7 +550,6 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header channel->number = *(channel->data - 2); - setChannelUsed(channel->number); channel->poly = *(channel->data - 1); channel->time = channel->prev = 0; if (channel->number == 0xFE) { // Digital channel diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index c74a7eae11..8bc9b97926 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -43,9 +43,10 @@ enum SciMidiCommands { // MidiParser_SCI // -MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion) : +MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : MidiParser() { _soundVersion = soundVersion; + _music = music; _mixedData = NULL; // mididata contains delta in 1/60th second // values of ppqn and tempo are found experimentally and may be wrong @@ -59,10 +60,6 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion) : _dataincAdd = false; _dataincToAdd = 0; _resetOnPause = false; - _channelsUsed = 0; - - for (int i = 0; i < 16; i++) - _channelRemap[i] = i; } MidiParser_SCI::~MidiParser_SCI() { @@ -78,6 +75,13 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in if (_pSnd) setVolume(psnd->volume); + for (int i = 0; i < 15; i++) { + _channelUsed[i] = false; + _channelRemap[i] = -1; + } + _channelRemap[9] = 9; // never map channel 9, because that's used for percussion + _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally + if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection midiFilterChannels(channelFilterMask); @@ -128,21 +132,24 @@ void MidiParser_SCI::unloadMusic() { // Center the pitch wheels and hold pedal in preparation for the next piece of music if (_driver && _pSnd) { for (int i = 0; i < 16; ++i) { - if (isChannelUsed(i)) { - _driver->send(0xE0 | i, 0, 0x40); // Reset pitch wheel - _driver->send(0xB0 | i, 0x40, 0); // Reset hold pedal + int16 realChannel = _channelRemap[i]; + if (realChannel != -1) { + _driver->send(0xE0 | realChannel, 0, 0x40); // Reset pitch wheel + _driver->send(0xB0 | realChannel, 0x40, 0); // Reset hold pedal } } } +} - for (int i = 0; i < 16; i++) - _channelRemap[i] = i; +void MidiParser_SCI::sendToDriver(uint32 b) { + // Channel remapping + int16 realChannel = _channelRemap[b & 0xf]; + assert(realChannel != -1); + b = (b & 0xFFFFFFF0) | realChannel; + _driver->send(b); } void MidiParser_SCI::parseNextEvent(EventInfo &info) { - // Monitor which channels are used by this song - setChannelUsed(info.channel()); - // Set signal AFTER waiting for delta, otherwise we would set signal too soon resulting in all sorts of bugs if (_dataincAdd) { _dataincAdd = false; @@ -334,8 +341,9 @@ void MidiParser_SCI::allNotesOff() { // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { - if ((_active_notes[i] & (1 << j)) && isChannelUsed(j)){ - _driver->send(0x80 | j, i, 0); + int16 realChannel = _channelRemap[j]; + if ((_active_notes[i] & (1 << j)) && realChannel != -1){ + _driver->send(0x80 | realChannel, i, 0); } } } @@ -353,8 +361,9 @@ void MidiParser_SCI::allNotesOff() { // support this...). for (i = 0; i < 16; ++i) { - if (isChannelUsed(i)) - _driver->send(0xB0 | i, 0x7b, 0); // All notes off + int16 realChannel = _channelRemap[i]; + if (realChannel != -1) + _driver->send(0xB0 | realChannel, 0x7b, 0); // All notes off } memset(_active_notes, 0, sizeof(_active_notes)); @@ -436,19 +445,23 @@ byte *MidiParser_SCI::midiMixChannels() { default: // MIDI command if (command & 0x80) { par1 = *channel->data++; - - // TODO: Fix remapping - -#if 0 - // Remap channel. Keep the upper 4 bits (command code) and change - // the lower 4 bits (channel) - byte remappedChannel = _channelRemap[par1 & 0xF]; - par1 = (par1 & 0xF0) | (remappedChannel & 0xF); -#endif } else {// running status par1 = command; command = channel->prev; } + + // remember which channel got used for channel remapping + byte midiChannel = command & 0xF; + _channelUsed[midiChannel] = true; +// int16 realChannel = _channelRemap[midiChannel]; +// if (realChannel == -1) { +// // We don't own this channel yet, so ask SciMusic to get it (or a remapped one) +// realChannel = _music->tryToOwnChannel(_pSnd, midiChannel); +// _channelRemap[midiChannel] = realChannel; +// } +// // Map new channel +// command = realChannel | (command & 0xF0); + if (command != global_prev) *outData++ = command; // out command *outData++ = par1;// pout par1 @@ -577,6 +590,17 @@ byte *MidiParser_SCI::midiFilterChannels(int channelMask) { return _mixedData; } +// This will get called right before actual playing and will try to own the used channels +void MidiParser_SCI::tryToOwnChannels() { + for (int curChannel = 0; curChannel < 15; curChannel++) { + if (_channelUsed[curChannel]) { + if (_channelRemap[curChannel] == -1) { + _channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel); + } + } + } +} + void MidiParser_SCI::setVolume(byte volume) { // FIXME: This receives values > 127... throw a warning for now and clip the variable if (volume > MUSIC_VOLUME_MAX) { diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 80401460d2..4888fa06ca 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -53,7 +53,7 @@ namespace Sci { */ class MidiParser_SCI : public MidiParser { public: - MidiParser_SCI(SciVersion soundVersion); + MidiParser_SCI(SciVersion soundVersion, SciMusic *music); ~MidiParser_SCI(); bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion); bool loadMusic(byte *, uint32) { @@ -73,25 +73,19 @@ public: void allNotesOff(); - void remapChannel(byte channel, byte newChannel) { - assert(channel < 0xF); // don't touch special SCI channel 15 - assert(newChannel < 0xF); // don't touch special SCI channel 15 - _channelRemap[channel] = newChannel; - } - - void clearUsedChannels() { _channelsUsed = 0; } - const byte *getMixedData() const { return _mixedData; } -protected: - bool isChannelUsed(byte channel) const { return _channelsUsed & (1 << channel); } - void setChannelUsed(byte channel) { _channelsUsed |= (1 << channel); } + void tryToOwnChannels(); +protected: + void sendToDriver(uint32 b); void parseNextEvent(EventInfo &info); byte *midiMixChannels(); byte *midiFilterChannels(int channelMask); byte midiGetNextChannel(long ticker); + SciMusic *_music; + SciVersion _soundVersion; byte *_mixedData; SoundResource::Track *_track; @@ -105,11 +99,8 @@ protected: int16 _dataincToAdd; bool _resetOnPause; - // A 16-bit mask, containing the channels used - // by the currently parsed song - uint16 _channelsUsed; - - byte _channelRemap[16]; + bool _channelUsed[16]; + int16 _channelRemap[16]; }; } // End of namespace Sci diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 254c70a24f..69e1c180e8 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -43,6 +43,9 @@ SciMusic::SciMusic(SciVersion soundVersion) // Reserve some space in the playlist, to avoid expensive insertion // operations _playList.reserve(10); + + for (int i = 0; i < 16; i++) + _usedChannel[i] = 0; } SciMusic::~SciMusic() { @@ -174,20 +177,6 @@ void SciMusic::sortPlayList() { Common::sort(_playList.begin(), _playList.end(), musicEntryCompare); } -void SciMusic::findUsedChannels() { - // Reset list - for (int k = 0; k < 16; k++) - _usedChannels[k] = false; - - const MusicList::const_iterator end = _playList.end(); - for (MusicList::const_iterator i = _playList.begin(); i != end; ++i) { - for (int channel = 0; channel < 16; channel++) { - if ((*i)->soundRes && (*i)->soundRes->isChannelUsed(channel)) - _usedChannels[channel] = true; - } - } -} - void SciMusic::soundInitSnd(MusicEntry *pSnd) { int channelFilterMask = 0; SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId()); @@ -224,34 +213,13 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { _mutex.lock(); pSnd->soundType = Audio::Mixer::kMusicSoundType; if (pSnd->pMidiParser == NULL) { - pSnd->pMidiParser = new MidiParser_SCI(_soundVersion); + pSnd->pMidiParser = new MidiParser_SCI(_soundVersion, this); pSnd->pMidiParser->setMidiDriver(_pMidiDrv); pSnd->pMidiParser->setTimerRate(_dwTempo); } pSnd->pauseCounter = 0; - // TODO: Fix channel remapping. This doesn't quite work... (e.g. no difference in LSL1VGA) -#if 0 - // Remap channels - findUsedChannels(); - - pSnd->pMidiParser->clearUsedChannels(); - - for (int i = 0; i < 16; i++) { - if (_usedChannels[i] && pSnd->soundRes->isChannelUsed(i)) { - int16 newChannel = getNextUnusedChannel(); - if (newChannel >= 0) { - _usedChannels[newChannel] = true; - debug("Remapping channel %d to %d\n", i, newChannel); - pSnd->pMidiParser->remapChannel(i, newChannel); - } else { - warning("Attempt to remap channel %d, but no unused channels exist", i); - } - } - } -#endif - // Find out what channels to filter for SCI0 channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel()); pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); @@ -263,6 +231,24 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { } } +// This one checks, if requested channel is available -> in that case give caller that channel +// Otherwise look for an unused one +int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { + if (!_usedChannel[bestChannel]) { + // currently unused, so give it to caller directly + _usedChannel[bestChannel] = caller; + return bestChannel; + } + // otherwise look for unused channel + for (int channelNr = 0; channelNr < 15; channelNr++) { + if (!_usedChannel[channelNr]) { + _usedChannel[channelNr] = caller; + return channelNr; + } + } + error("no free channels"); +} + void SciMusic::onTimer() { const MusicList::iterator end = _playList.end(); for (MusicList::iterator i = _playList.begin(); i != end; ++i) @@ -324,6 +310,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { DisposeAfterUse::NO); } } else { + pSnd->pMidiParser->tryToOwnChannels(); _mutex.lock(); if (pSnd->pMidiParser) { pSnd->pMidiParser->setVolume(pSnd->volume); @@ -388,6 +375,11 @@ void SciMusic::soundKill(MusicEntry *pSnd) { _mutex.lock(); uint sz = _playList.size(), i; + // Remove used channels + for (i = 0; i < 15; i++) { + if (_usedChannel[i] == pSnd) + _usedChannel[i] = 0; + } // Remove sound from playlist for (i = 0; i < sz; i++) { if (_playList[i] == pSnd) { diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 83cd59e89b..bbafb808cb 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -196,6 +196,8 @@ public: // where a deadlock can occur Common::Mutex _mutex; + int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel); + protected: void sortPlayList(); @@ -210,20 +212,11 @@ protected: bool _bMultiMidi; private: static void miditimerCallback(void *p); - void findUsedChannels(); - int16 getNextUnusedChannel() const { - for (int i = 0; i < 16; i++) { - if (!_usedChannels[i]) - return i; - } - - return -1; - } MusicList _playList; bool _soundOn; byte _masterVolume; - bool _usedChannels[16]; + MusicEntry *_usedChannel[16]; }; } // End of namespace Sci -- cgit v1.2.3 From 02c3397ddf12e636da0b851f6350b45af1859dcd Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 16 Jun 2010 21:07:26 +0000 Subject: SCI: fix debug command "show_instruments", got broken by r49905 on purpose svn-id: r49906 --- engines/sci/console.cpp | 3 +-- engines/sci/sound/midiparser_sci.cpp | 11 +++-------- 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index ebe7edecbe..3737ccd59e 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -859,8 +859,7 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { SciVersion doSoundVersion = _engine->_features->detectDoSoundType(); MidiPlayer *player = MidiPlayer_Midi_create(doSoundVersion); - MidiParser_SCI *parser; // = new MidiParser_SCI(doSoundVersion); - // FIXME: add SciMusic object + MidiParser_SCI *parser = new MidiParser_SCI(doSoundVersion, 0); parser->setMidiDriver(player); Common::List *resources = _engine->getResMan()->listResources(kResourceTypeSound); diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 8bc9b97926..b76c5d0624 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -453,14 +453,6 @@ byte *MidiParser_SCI::midiMixChannels() { // remember which channel got used for channel remapping byte midiChannel = command & 0xF; _channelUsed[midiChannel] = true; -// int16 realChannel = _channelRemap[midiChannel]; -// if (realChannel == -1) { -// // We don't own this channel yet, so ask SciMusic to get it (or a remapped one) -// realChannel = _music->tryToOwnChannel(_pSnd, midiChannel); -// _channelRemap[midiChannel] = realChannel; -// } -// // Map new channel -// command = realChannel | (command & 0xF0); if (command != global_prev) *outData++ = command; // out command @@ -592,6 +584,9 @@ byte *MidiParser_SCI::midiFilterChannels(int channelMask) { // This will get called right before actual playing and will try to own the used channels void MidiParser_SCI::tryToOwnChannels() { + // We don't have SciMusic in case debug command show_instruments is used + if (!_music) + return; for (int curChannel = 0; curChannel < 15; curChannel++) { if (_channelUsed[curChannel]) { if (_channelRemap[curChannel] == -1) { -- cgit v1.2.3 From 289b668099071c4609a6081cca97c626d61e93eb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 16 Jun 2010 21:23:47 +0000 Subject: SCI: dont seek during init of music but on play, fixes assert when restoring saves caused by r49905 - because channel remapping isn't done at that point svn-id: r49907 --- engines/sci/sound/music.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 69e1c180e8..213d3830c7 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -224,8 +224,6 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel()); pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); - // Fast forward to the last position and perform associated events when loading - pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); _mutex.unlock(); } } @@ -316,6 +314,9 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pMidiParser->setVolume(pSnd->volume); if (pSnd->status == kSoundStopped) pSnd->pMidiParser->jumpToTick(0); + else + // Fast forward to the last position and perform associated events when loading + pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); } _mutex.unlock(); } -- cgit v1.2.3 From 9b6f71d7cf76e529ed8010224442ceef18183fcb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 16 Jun 2010 21:44:33 +0000 Subject: Added handling for the SCI2.1 kPalette(1) call. The graphics in Torin's Passage are shown with the correct colors now svn-id: r49908 --- engines/sci/engine/kgraphics.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index f56c5bb5e1..424d5049e5 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -553,9 +553,11 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 1: // Set resource palette - if (argc==3) { + if (argc == 2 || argc == 3) { GuiResourceId resourceId = argv[1].toUint16(); - bool force = argv[2].toUint16() == 2 ? true : false; + bool force = false; + if (argc == 3) + force = argv[2].toUint16() == 2 ? true : false; g_sci->_gfxPalette->kernelSetFromResource(resourceId, force); } else { warning("kPalette(1) called with %d parameters", argc); -- cgit v1.2.3 From 20d8de27bad1e9e8cd218c258ec863f89219b49c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 16 Jun 2010 21:56:39 +0000 Subject: Implemented the SCI2.1 kMulDiv kernel function. Walking in Torin's Passage is done correctly now, without leaving trails svn-id: r49909 --- engines/sci/engine/kernel.cpp | 1 + engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel32.cpp | 8 ++++++++ 3 files changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d1b6ce72bc..3da34d44e4 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -387,6 +387,7 @@ SciKernelFunction kfunct_mappers[] = { { "List", kList, ".*" }, { "Robot", kRobot, ".*" }, { "IsOnMe", kIsOnMe, "iio.*" }, + { "MulDiv", kMulDiv, "iii" }, #endif diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 10225729d7..b3730cb6df 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -413,6 +413,7 @@ reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv); reg_t kArray(EngineState *s, int argc, reg_t *argv); reg_t kListAt(EngineState *s, int argc, reg_t *argv); reg_t kString(EngineState *s, int argc, reg_t *argv); +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv); // "Screen items" in SCI32 are views reg_t kAddScreenItem(EngineState *s, int argc, reg_t *argv); reg_t kUpdateScreenItem(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index a077f110cf..d35dd38792 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -879,6 +879,14 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { + int16 multiplicant = argv[0].toSint16(); + int16 multiplier = argv[1].toSint16(); + int16 denominator = argv[2].toSint16(); + + return make_reg(0, multiplicant * multiplier / denominator); +} + } // End of namespace Sci #endif // ENABLE_SCI32 -- cgit v1.2.3 From fa0011f51216d926d0922fba7bfb1ed65958dff2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 16 Jun 2010 21:59:21 +0000 Subject: Added a sanity check inside kMulDiv svn-id: r49910 --- engines/sci/engine/kernel32.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index d35dd38792..7067e87c60 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -884,6 +884,12 @@ reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { int16 multiplier = argv[1].toSint16(); int16 denominator = argv[2].toSint16(); + // Sanity check... + if (!denominator) { + warning("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); + return NULL_REG; + } + return make_reg(0, multiplicant * multiplier / denominator); } -- cgit v1.2.3 From 93890a49c1f62791f39e4ee07c2366c8fdb8fb37 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 16 Jun 2010 23:28:20 +0000 Subject: Added back the functionality to skip videos svn-id: r49911 --- engines/sci/console.cpp | 9 ++++++--- engines/sci/engine/kgraphics.cpp | 9 ++++++--- 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 3737ccd59e..6845e7282e 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -244,8 +244,9 @@ void Console::postEnter() { if (videoDecoder && videoDecoder->loadFile(_videoFile)) { uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + bool skipVideo = false; - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { Graphics::Surface *frame = videoDecoder->decodeNextFrame(); if (frame) { @@ -259,8 +260,10 @@ void Console::postEnter() { } Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } g_system->delayMillis(10); } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 424d5049e5..5c84ddfb49 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1160,8 +1160,9 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { if (videoDecoder) { uint16 x = (screenWidth - videoDecoder->getWidth()) / 2; uint16 y = (screenHeight - videoDecoder->getHeight()) / 2; + bool skipVideo = false; - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo()) { + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { Graphics::Surface *frame = videoDecoder->decodeNextFrame(); if (frame) { @@ -1175,8 +1176,10 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) - ; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } g_system->delayMillis(10); } -- cgit v1.2.3 From 18dc295a339cb7cc618ba565f68d05c6eada9782 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 16 Jun 2010 23:30:22 +0000 Subject: Hooked the VMD player in kPlayVMD. The VMD videos in the demo of Phantasmagoria 1 are shown now (e.g. the intro and the chapter beginning) svn-id: r49912 --- engines/sci/engine/kernel.cpp | 1 + engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel32.cpp | 70 +++++++++++++++++++++++++++++++++++++++++ engines/sci/sci.cpp | 7 +++-- 4 files changed, 76 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 3da34d44e4..ef219390a4 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -386,6 +386,7 @@ SciKernelFunction kfunct_mappers[] = { { "Save", kSave, ".*" }, { "List", kList, ".*" }, { "Robot", kRobot, ".*" }, + { "PlayVMD", kPlayVMD, ".*" }, { "IsOnMe", kIsOnMe, "iio.*" }, { "MulDiv", kMulDiv, "iii" }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b3730cb6df..0a4998868d 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -438,6 +438,7 @@ reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); +reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); #endif diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 7067e87c60..9adfdca21c 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -30,8 +30,10 @@ #include "sci/engine/segment.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" +#include "sci/graphics/cursor.h" #include "sci/graphics/frameout.h" #include "sci/graphics/screen.h" +#include "sci/video/vmd_decoder.h" #include "common/system.h" @@ -893,6 +895,74 @@ reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { return make_reg(0, multiplicant * multiplier / denominator); } +reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { + uint16 operation = argv[0].toUint16(); + Graphics::VideoDecoder *videoDecoder = 0; + Common::String fileName; + + Common::String warningMsg; + + switch (operation) { + case 0: // play + fileName = s->_segMan->derefString(argv[1]); + // TODO: argv[2] (usually 0) + videoDecoder = new VMDDecoder(g_system->getMixer()); + + g_sci->_gfxCursor->kernelHide(); + + if (videoDecoder && videoDecoder->loadFile(fileName)) { + uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; + uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + bool skipVideo = false; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } + + // Copy video contents to screen buffer + g_sci->_gfxScreen->kernelSyncWithFramebuffer(); + + delete videoDecoder; + } else + warning("Could not play video %s\n", fileName.c_str()); + + g_sci->_gfxCursor->kernelShow(); + + break; + default: + warningMsg = "PlayVMD - unsupported subop. Params: " + + Common::String::printf("%d", argc) + " ("; + + for (int i = 0; i < argc; i++) { + warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + warningMsg += (i == argc - 1 ? ")" : ", "); + } + + warning("%s", warningMsg.c_str()); + break; + } + + return s->r_acc; +} + } // End of namespace Sci #endif // ENABLE_SCI32 diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 4af6bc7b43..03f54caf31 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -118,11 +118,12 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) SearchMan.addSubDirectoryMatching(gameDataDir, "actors"); // KQ6 hi-res portraits SearchMan.addSubDirectoryMatching(gameDataDir, "aud"); // resource.aud and audio files - SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions - SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions SearchMan.addSubDirectoryMatching(gameDataDir, "wav"); // speech files in WAV format SearchMan.addSubDirectoryMatching(gameDataDir, "sfx"); // music/sound files in WAV format - SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot files + SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions + SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions + SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot movie files + SearchMan.addSubDirectoryMatching(gameDataDir, "vmd"); // vmd movie files // Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD // is for the demo of Phantasmagoria, included in the disk -- cgit v1.2.3 From a7b76c04d9df2c30d541554b9f907f6bcedd307a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 00:07:03 +0000 Subject: Added handling of VMD video files in kResCheck, fixes video playing in GK2 svn-id: r49913 --- engines/sci/engine/kscripts.cpp | 8 ++++++++ engines/sci/resource.h | 1 + engines/sci/sci.cpp | 1 + 3 files changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index a8cf92b2a6..88e765a0ff 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -29,6 +29,8 @@ #include "sci/engine/selector.h" #include "sci/engine/kernel.h" +#include "common/file.h" + namespace Sci { // Loads arbitrary resources of type 'restype' with resource numbers 'resnrs' @@ -93,6 +95,12 @@ reg_t kResCheck(EngineState *s, int argc, reg_t *argv) { Resource *res = NULL; ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); + if (restype == kResourceTypeVMD) { + char fileName[50]; + sprintf(fileName, "%d.vmd", argv[1].toUint16()); + return make_reg(0, Common::File::exists(fileName)); + } + if ((restype == kResourceTypeAudio36) || (restype == kResourceTypeSync36)) { if (argc >= 6) { uint noun = argv[2].toUint16() & 0xff; diff --git a/engines/sci/resource.h b/engines/sci/resource.h index b37f71832d..591273b252 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -98,6 +98,7 @@ enum ResourceType { kResourceTypeUnknown1, // Translation, currently unsupported kResourceTypeUnknown2, kResourceTypeRobot, + kResourceTypeVMD, kResourceTypeInvalid, // Mac-only resources, these resource types are self-defined diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 03f54caf31..1dc02ac7c3 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -123,6 +123,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) SearchMan.addSubDirectoryMatching(gameDataDir, "avi"); // AVI movie files for Windows versions SearchMan.addSubDirectoryMatching(gameDataDir, "seq"); // SEQ movie files for DOS versions SearchMan.addSubDirectoryMatching(gameDataDir, "robot"); // robot movie files + SearchMan.addSubDirectoryMatching(gameDataDir, "movies"); // vmd movie files SearchMan.addSubDirectoryMatching(gameDataDir, "vmd"); // vmd movie files // Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD -- cgit v1.2.3 From 2cba994bb4179cbed1c54921ff825bc4f7735efb Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 00:20:40 +0000 Subject: Only hide/show cursor when playing a VMD if it was visible in the first place. svn-id: r49914 --- engines/sci/engine/kernel32.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 9adfdca21c..dedcf0df5f 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -898,9 +898,8 @@ reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); Graphics::VideoDecoder *videoDecoder = 0; - Common::String fileName; - - Common::String warningMsg; + bool reshowCursor = g_sci->_gfxCursor->isVisible(); + Common::String fileName, warningMsg; switch (operation) { case 0: // play @@ -908,7 +907,8 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // TODO: argv[2] (usually 0) videoDecoder = new VMDDecoder(g_system->getMixer()); - g_sci->_gfxCursor->kernelHide(); + if (reshowCursor) + g_sci->_gfxCursor->kernelHide(); if (videoDecoder && videoDecoder->loadFile(fileName)) { uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; @@ -944,8 +944,8 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { } else warning("Could not play video %s\n", fileName.c_str()); - g_sci->_gfxCursor->kernelShow(); - + if (reshowCursor) + g_sci->_gfxCursor->kernelShow(); break; default: warningMsg = "PlayVMD - unsupported subop. Params: " + -- cgit v1.2.3 From 6ee4bf06ade5fdc6158d55b10cd73b1bf9377941 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 03:53:13 +0000 Subject: Fix a valgrind warning in GfxCursor. Thanks to digitall for finding it. svn-id: r49917 --- engines/sci/graphics/cursor.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 46bd981b7f..2930bb8a46 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -43,11 +43,11 @@ GfxCursor::GfxCursor(ResourceManager *resMan, GfxPalette *palette, GfxScreen *sc : _resMan(resMan), _palette(palette), _screen(screen) { _upscaledHires = _screen->getUpscaledHires(); + _isVisible = true; + // center mouse cursor setPosition(Common::Point(_screen->getWidth() / 2, _screen->getHeight() / 2)); kernelSetMoveZone(Common::Rect(0, 0, _screen->getDisplayWidth(), _screen->getDisplayHeight())); - - _isVisible = true; } GfxCursor::~GfxCursor() { -- cgit v1.2.3 From 39276e82dbebf55e68ecc298cbeef01133fb0bf8 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 03:57:38 +0000 Subject: Fix another valgrind warning, thanks to digitall for spotting. svn-id: r49918 --- engines/sci/sound/midiparser_sci.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index b76c5d0624..189d9b8727 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -60,6 +60,7 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : _dataincAdd = false; _dataincToAdd = 0; _resetOnPause = false; + _pSnd = 0; } MidiParser_SCI::~MidiParser_SCI() { -- cgit v1.2.3 From f10b1a23f807d7889a2776ce80ea8b7a77160eb5 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 17 Jun 2010 05:40:48 +0000 Subject: Fixed a few cppcheck errors. svn-id: r49919 --- engines/groovie/font.cpp | 1 + engines/m4/mads_scene.cpp | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/groovie/font.cpp b/engines/groovie/font.cpp index 6aa6c89d31..dc1d7ae73a 100644 --- a/engines/groovie/font.cpp +++ b/engines/groovie/font.cpp @@ -54,6 +54,7 @@ bool T7GFont::load(Common::SeekableReadStream &stream) { if (stream.eos()) { error("Groovie::T7GFont: Couldn't read the glyph offsets"); + delete[] glyphOffsets; return false; } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 428b92c657..43b39af0db 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -635,7 +635,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su if (sceneNumber > 0) { sceneName = MADSResourceManager::getResourceName(RESPREFIX_RM, sceneNumber, ".DAT"); } else { - strcat(buffer1, "*"); + strcpy(buffer1, "*"); strcat(buffer1, resName); sceneName = buffer1; // TODO: Check whether this needs to be converted to 'HAG form' } -- cgit v1.2.3 From 894ba682cdfb60a268dd4f4cb09d74d5cbb590b0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 07:26:06 +0000 Subject: Moved kMulDiv together with the rest of the math functions, and kPlayVMD together with the rest of the video playing functions svn-id: r49920 --- engines/sci/engine/kernel32.cpp | 84 ---------------------------------------- engines/sci/engine/kgraphics.cpp | 75 +++++++++++++++++++++++++++++++++++ engines/sci/engine/kmath.cpp | 18 +++++++++ 3 files changed, 93 insertions(+), 84 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index dedcf0df5f..a077f110cf 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -30,10 +30,8 @@ #include "sci/engine/segment.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" -#include "sci/graphics/cursor.h" #include "sci/graphics/frameout.h" #include "sci/graphics/screen.h" -#include "sci/video/vmd_decoder.h" #include "common/system.h" @@ -881,88 +879,6 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } -reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { - int16 multiplicant = argv[0].toSint16(); - int16 multiplier = argv[1].toSint16(); - int16 denominator = argv[2].toSint16(); - - // Sanity check... - if (!denominator) { - warning("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); - return NULL_REG; - } - - return make_reg(0, multiplicant * multiplier / denominator); -} - -reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { - uint16 operation = argv[0].toUint16(); - Graphics::VideoDecoder *videoDecoder = 0; - bool reshowCursor = g_sci->_gfxCursor->isVisible(); - Common::String fileName, warningMsg; - - switch (operation) { - case 0: // play - fileName = s->_segMan->derefString(argv[1]); - // TODO: argv[2] (usually 0) - videoDecoder = new VMDDecoder(g_system->getMixer()); - - if (reshowCursor) - g_sci->_gfxCursor->kernelHide(); - - if (videoDecoder && videoDecoder->loadFile(fileName)) { - uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; - uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; - bool skipVideo = false; - - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { - if (videoDecoder->needsUpdate()) { - Graphics::Surface *frame = videoDecoder->decodeNextFrame(); - if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); - - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); - - g_system->updateScreen(); - } - } - - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) { - if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) - skipVideo = true; - } - - g_system->delayMillis(10); - } - - // Copy video contents to screen buffer - g_sci->_gfxScreen->kernelSyncWithFramebuffer(); - - delete videoDecoder; - } else - warning("Could not play video %s\n", fileName.c_str()); - - if (reshowCursor) - g_sci->_gfxCursor->kernelShow(); - break; - default: - warningMsg = "PlayVMD - unsupported subop. Params: " + - Common::String::printf("%d", argc) + " ("; - - for (int i = 0; i < argc; i++) { - warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); - warningMsg += (i == argc - 1 ? ")" : ", "); - } - - warning("%s", warningMsg.c_str()); - break; - } - - return s->r_acc; -} - } // End of namespace Sci #endif // ENABLE_SCI32 diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 5c84ddfb49..84fbbe98eb 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -48,6 +48,9 @@ #include "sci/graphics/screen.h" #include "sci/graphics/text16.h" #include "sci/graphics/view.h" +#ifdef ENABLE_SCI32 +#include "sci/video/vmd_decoder.h" +#endif namespace Sci { @@ -1230,6 +1233,78 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } + +reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { + uint16 operation = argv[0].toUint16(); + Graphics::VideoDecoder *videoDecoder = 0; + bool reshowCursor = g_sci->_gfxCursor->isVisible(); + Common::String fileName, warningMsg; + + switch (operation) { + case 0: // play + fileName = s->_segMan->derefString(argv[1]); + // TODO: argv[2] (usually 0) + if (argv[2] != NULL_REG) + warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x)", PRINT_REG(argv[2])); + + videoDecoder = new VMDDecoder(g_system->getMixer()); + + if (reshowCursor) + g_sci->_gfxCursor->kernelHide(); + + if (videoDecoder && videoDecoder->loadFile(fileName)) { + uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; + uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + bool skipVideo = false; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } + + // Copy video contents to screen buffer + g_sci->_gfxScreen->kernelSyncWithFramebuffer(); + + delete videoDecoder; + } else + warning("Could not play video %s\n", fileName.c_str()); + + if (reshowCursor) + g_sci->_gfxCursor->kernelShow(); + break; + default: + warningMsg = "PlayVMD - unsupported subop. Params: " + + Common::String::printf("%d", argc) + " ("; + + for (int i = 0; i < argc; i++) { + warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + warningMsg += (i == argc - 1 ? ")" : ", "); + } + + warning("%s", warningMsg.c_str()); + break; + } + + return s->r_acc; +} + #endif reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index dbf317860f..6d4b9a2a04 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -153,4 +153,22 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) { return make_reg(0, (int16)(tan(param * PI / 180.0) * scale)); } +#ifdef ENABLE_SCI32 + +reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { + int16 multiplicant = argv[0].toSint16(); + int16 multiplier = argv[1].toSint16(); + int16 denominator = argv[2].toSint16(); + + // Sanity check... + if (!denominator) { + warning("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); + return NULL_REG; + } + + return make_reg(0, multiplicant * multiplier / denominator); +} + +#endif + } // End of namespace Sci -- cgit v1.2.3 From 25496abe1b494e125cc8dd7892e9c95e3da61042 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 07:53:57 +0000 Subject: Added 2x scaling for VMD videos, for bugtesting (temporarily in SCI itself). It's currently not optimized much, but since the VMD decoder code will be revamped, we don't really care about performance at this point svn-id: r49921 --- engines/sci/engine/kgraphics.cpp | 19 ++++++++++++++++--- 1 file changed, 16 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 84fbbe98eb..41aca3ff49 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1253,15 +1253,27 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelHide(); if (videoDecoder && videoDecoder->loadFile(fileName)) { - uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; - uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + //uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; + //uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; + uint16 w = videoDecoder->getWidth() * 2; + uint16 h = videoDecoder->getHeight() * 2; + uint16 x = (g_system->getWidth() - w) / 2; + uint16 y = (g_system->getHeight() - h) / 2; + byte *frameBuf = new byte[w * h]; + bool skipVideo = false; while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { if (videoDecoder->needsUpdate()) { Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + //g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); + // All the VMD videos in SCI2.1 need to be scaled by 2 + // TODO: This isn't optimized much, but since the VMD decoder code will be revamped, we + // don't really care about performance at this point anyway + g_sci->_gfxScreen->scale2x((byte *)frame->pixels, frameBuf, videoDecoder->getWidth(), videoDecoder->getHeight()); + g_system->copyRectToScreen(frameBuf, frame->pitch * 2, x, y, frame->w * 2, frame->h * 2); if (videoDecoder->hasDirtyPalette()) videoDecoder->setSystemPalette(); @@ -1282,6 +1294,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // Copy video contents to screen buffer g_sci->_gfxScreen->kernelSyncWithFramebuffer(); + delete frameBuf; delete videoDecoder; } else warning("Could not play video %s\n", fileName.c_str()); -- cgit v1.2.3 From 705d3c2d85b30368a7b138328cdd99040fe0bf28 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 08:41:04 +0000 Subject: SCI: fixes regressions of r49905 (thx to digitall) - first we now find out what channels are used in sci0 as well, we are doing straight mapping for sci0 though - this fixes music in sci0 games, also fixing crash in sq1vga because of using null pMidiParser svn-id: r49922 --- engines/sci/sound/midiparser_sci.cpp | 4 ++++ engines/sci/sound/music.cpp | 5 ++++- 2 files changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 189d9b8727..bdb907a451 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -545,6 +545,10 @@ byte *MidiParser_SCI::midiFilterChannels(int channelMask) { break; default: // MIDI command + // remember which channel got used for channel remapping + byte midiChannel = command & 0xF; + _channelUsed[midiChannel] = true; + if (lastCommand != command) { *outData++ = command; debugC(4, kDebugLevelSound, "%02X ", command); diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 213d3830c7..a1c6cc0a56 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -232,6 +232,9 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { // This one checks, if requested channel is available -> in that case give caller that channel // Otherwise look for an unused one int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { + // Don't even try this for SCI0 + if (_soundVersion <= SCI_VERSION_0_LATE) + return bestChannel; if (!_usedChannel[bestChannel]) { // currently unused, so give it to caller directly _usedChannel[bestChannel] = caller; @@ -308,9 +311,9 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { DisposeAfterUse::NO); } } else { - pSnd->pMidiParser->tryToOwnChannels(); _mutex.lock(); if (pSnd->pMidiParser) { + pSnd->pMidiParser->tryToOwnChannels(); pSnd->pMidiParser->setVolume(pSnd->volume); if (pSnd->status == kSoundStopped) pSnd->pMidiParser->jumpToTick(0); -- cgit v1.2.3 From 81fe1aa19ee4a9e8ffb7a77fbef8dc40fddbc750 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 08:55:08 +0000 Subject: Added some more information on some of the calls of kPlayVMD svn-id: r49923 --- engines/sci/engine/kgraphics.cpp | 21 ++++++++++++++++++--- 1 file changed, 18 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 41aca3ff49..03989be374 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1241,11 +1241,14 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { Common::String fileName, warningMsg; switch (operation) { - case 0: // play + case 0: // init + // This is actually meant to init the video file, but we play it instead fileName = s->_segMan->derefString(argv[1]); - // TODO: argv[2] (usually 0) + // TODO: argv[2] (usually null). When it exists, it points to an "Event" object, + // that holds no data initially (e.g. in the intro of Phantasmagoria 1 demo). + // Perhaps it's meant for syncing if (argv[2] != NULL_REG) - warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x)", PRINT_REG(argv[2])); + warning("kPlayVMD: third parameter isn't 0 (it's %04x:%04x - %s)", PRINT_REG(argv[2]), s->_segMan->getObjectName(argv[2])); videoDecoder = new VMDDecoder(g_system->getMixer()); @@ -1302,6 +1305,18 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { if (reshowCursor) g_sci->_gfxCursor->kernelShow(); break; + case 1: + // Unknown. Called with 5 extra integer parameterrs + // (e.g. 174, 95, 20, 0, 55, 236) + case 6: + // Play, perhaps? Or stop? This is the last call made, and takes no extra parameters + case 14: + // Takes an additional integer parameter (e.g. 3) + case 16: + // Takes an additional parameter, usually 0 + case 21: + // Looks to be setting the video size and position. Called with 4 extra integer + // parameters (e.g. 86, 41, 235, 106) default: warningMsg = "PlayVMD - unsupported subop. Params: " + Common::String::printf("%d", argc) + " ("; -- cgit v1.2.3 From 3a8e11767d07e836bc001e931c480a3cd63dcd67 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 11:05:39 +0000 Subject: SCI: decreasing channel given to us on cmdSendMidi by one, so mute command now matches the right channel. sierra sci also decreased by one (their channel is 1-based) svn-id: r49924 --- engines/sci/sound/soundcmd.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index e317796aad..6ee23d7fc8 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -232,6 +232,10 @@ reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { uint16 controller = argv[4].toUint16(); uint16 param = argv[5].toUint16(); + if (!channel) + error("invalid channel specified on cmdSendMidi"); + channel--; // channel is given 1-based, we are using 0-based + _midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); } -- cgit v1.2.3 From 423029c027c2013c4d23062b2ce81a807d6c74ec Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 11:54:54 +0000 Subject: SCI: implemented channel muting for sci1, finally fixes lsl5 paino scene with patti svn-id: r49926 --- engines/sci/sound/midiparser_sci.cpp | 23 ++++++++++++++++++++--- engines/sci/sound/midiparser_sci.h | 3 ++- engines/sci/sound/music.cpp | 12 ++++++++++++ engines/sci/sound/music.h | 6 ++---- engines/sci/sound/soundcmd.cpp | 15 +++++++++++---- 5 files changed, 47 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index bdb907a451..1ea990332b 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -79,6 +79,7 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in for (int i = 0; i < 15; i++) { _channelUsed[i] = false; _channelRemap[i] = -1; + _channelMuted[i] = false; } _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally @@ -143,8 +144,22 @@ void MidiParser_SCI::unloadMusic() { } void MidiParser_SCI::sendToDriver(uint32 b) { + byte midiChannel = b & 0xf; + + if ((b & 0xFFF0) == 0x4EB0) { + // this is channel mute only for sci1 + // it's velocity control for sci0 + if (_soundVersion >= SCI_VERSION_1_EARLY) { + _channelMuted[midiChannel] = b & 0xFF0000 ? true : false; + return; // don't send this to driver at all + } + } + + // Is channel muted? if so, don't send command + if (_channelMuted[midiChannel]) + return; // Channel remapping - int16 realChannel = _channelRemap[b & 0xf]; + int16 realChannel = _channelRemap[midiChannel]; assert(realChannel != -1); b = (b & 0xFFFFFFF0) | realChannel; _driver->send(b); @@ -249,7 +264,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { case 0x0A: // pan case 0x0B: // expression case 0x40: // sustain - case 0x4E: // velocity control case 0x79: // reset all case 0x7B: // notes off // These are all handled by the music driver, so ignore them @@ -263,8 +277,11 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { break; } } - if (info.basic.param1 == 7) // channel volume change -scale it + switch (info.basic.param1) { + case 7: // channel volume change -scale it info.basic.param2 = info.basic.param2 * _volume / MUSIC_VOLUME_MAX; + break; + } info.length = 0; break; diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 4888fa06ca..89d1e63d8c 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -76,9 +76,9 @@ public: const byte *getMixedData() const { return _mixedData; } void tryToOwnChannels(); + void sendToDriver(uint32 b); protected: - void sendToDriver(uint32 b); void parseNextEvent(EventInfo &info); byte *midiMixChannels(); byte *midiFilterChannels(int channelMask); @@ -101,6 +101,7 @@ protected: bool _channelUsed[16]; int16 _channelRemap[16]; + bool _channelMuted[16]; }; } // End of namespace Sci diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index a1c6cc0a56..c5fc07bfd7 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -446,6 +446,18 @@ void SciMusic::soundSetMasterVolume(uint16 vol) { _pMidiDrv->setVolume(vol); } +void SciMusic::sendMidiCommand(uint32 cmd) { + Common::StackLock lock(_mutex); + _pMidiDrv->send(cmd); +} + +void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { + if (pSnd->pMidiParser) + pSnd->pMidiParser->sendToDriver(cmd); + else + warning("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); +} + void SciMusic::printPlayList(Console *con) { Common::StackLock lock(_mutex); diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index bbafb808cb..8e68d3df92 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -179,10 +179,8 @@ public: MusicList::iterator getPlayListStart() { return _playList.begin(); } MusicList::iterator getPlayListEnd() { return _playList.end(); } - void sendMidiCommand(uint32 cmd) { - Common::StackLock lock(_mutex); - _pMidiDrv->send(cmd); - } + void sendMidiCommand(uint32 cmd); + void sendMidiCommand(MusicEntry *pSnd, uint32 cmd); void setReverb(byte reverb); diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 6ee23d7fc8..fa215ac302 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -232,9 +232,8 @@ reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { uint16 controller = argv[4].toUint16(); uint16 param = argv[5].toUint16(); - if (!channel) - error("invalid channel specified on cmdSendMidi"); - channel--; // channel is given 1-based, we are using 0-based + if (channel) + channel--; // channel is given 1-based, we are using 0-based _midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); } @@ -901,7 +900,15 @@ void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { //SongHandle handle = FROBNICATE_HANDLE(obj); //_state->sfx_send_midi(handle, value, _midiCmd, _controller, _param); #else - _music->sendMidiCommand(_midiCommand); + MusicEntry *musicSlot = _music->getSlot(obj); + if (!musicSlot) { + // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! + // if so, allow it + //_music->sendMidiCommand(_midiCommand); + warning("cmdSendMidi: Slot not found (%04x:%04x)", PRINT_REG(obj)); + return; + } + _music->sendMidiCommand(musicSlot, _midiCommand); #endif } -- cgit v1.2.3 From cf86b447939a3baea5aa3bd53450f8f56f436740 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 12:13:27 +0000 Subject: M4/MADS: Some slight tweaks to the animation message chunks svn-id: r49927 --- engines/m4/animation.cpp | 18 +++++++++++++----- engines/m4/animation.h | 1 + 2 files changed, 14 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index c39a1f0cd2..6b32bdca17 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -132,9 +132,9 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S for (int i = 0; i < messagesCount; ++i) { AnimMessage rec; + rec.soundId = animStream->readUint16LE(); animStream->read(rec.msg, 70); - rec.pos.x = animStream->readUint16LE(); - rec.pos.y = animStream->readUint16LE(); + animStream->readUint16LE(); animStream->readUint16LE(); rec.rgb1.r = animStream->readByte(); rec.rgb1.g = animStream->readByte(); @@ -142,11 +142,13 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S rec.rgb2.r = animStream->readByte(); rec.rgb2.g = animStream->readByte(); rec.rgb2.b = animStream->readByte(); + animStream->readUint16LE(); + animStream->readUint16LE(); rec.kernelMsgIndex = animStream->readUint16LE(); - animStream->skip(6); + rec.pos.x = animStream->readUint16LE(); + rec.pos.y = animStream->readUint16LE(); rec.startFrame = animStream->readUint16LE(); rec.endFrame = animStream->readUint16LE(); - animStream->readUint16LE(); _messages.push_back(rec); } @@ -201,7 +203,10 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S fontName += "*"; fontName += fontResource; - _font = _vm->_font->getFont(fontName); + if (fontName != "") + _font = _vm->_font->getFont(fontName); + else + warning("Attempted to set a font with an empty name"); } // Load all the sprite sets for the animation @@ -421,6 +426,9 @@ void MadsAnimation::update() { // Add a kernel message to display the given text me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg); + // Play the associated sound, if it exists + if (me.soundId >= 0) + _vm->_sound->playDSRSound(me.soundId, 255, false); ++_messageCtr; } } diff --git a/engines/m4/animation.h b/engines/m4/animation.h index cffcf9f689..89c3cbbfaf 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -39,6 +39,7 @@ class SpriteSlotSubset; class AnimMessage { public: + int16 soundId; char msg[70]; Common::Point pos; RGB8 rgb1, rgb2; -- cgit v1.2.3 From 0e365131ac58b7504e9e16b08a8b3125b6b37027 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 12:29:58 +0000 Subject: Fixed wPlayAudio, and added some documentation on the 3 new kDoAudio subops. Digital sounds in Pharkas work again svn-id: r49928 --- engines/sci/engine/ksound.cpp | 16 +++++++++++++--- engines/sci/sound/audio.cpp | 2 +- 2 files changed, 14 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 8cf9400353..d4af4ade5c 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -174,9 +174,19 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { case kSciAudioCD: debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop"); return kDoCdAudio(s, argc - 1, argv + 1); - // TODO: There are 3 more functions used in Freddy Pharkas (11, 12 and 13) and new within sierra sci - // Details currently unknown - // kDoAudio sits at seg026:038C + + // 3 new subops in Pharkas. kDoAudio in Pharkas sits at seg026:038C + case 11: + warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + break; + case 12: + // Seems to be audio sync, used in Pharkas, silenced warning cause of the spam it produces + //warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + break; + case 13: + // Used in Pharkas whenever a speech sample starts + warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + break; default: warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); } diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index ac3ef54c9a..0e235ee400 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -82,7 +82,7 @@ int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { // sample length and return that. wPlayAudio should *not* actually start the sample. int sampleLen = 0; - Audio::AudioStream *audioStream = getAudioStream(module, tuple, &sampleLen); + Audio::AudioStream *audioStream = getAudioStream(tuple, module, &sampleLen); if (!audioStream) warning("wPlayAudio: unable to create stream for audio tuple %d, module %d", tuple, module); delete audioStream; -- cgit v1.2.3 From 45b23601e77d816415cccd7cd73f487d3a0f485b Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Thu, 17 Jun 2010 13:42:02 +0000 Subject: Add detection of original directory structure for Touche. svn-id: r49929 --- engines/touche/detection.cpp | 9 +++++++-- engines/touche/touche.cpp | 6 ++++++ 2 files changed, 13 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/touche/detection.cpp b/engines/touche/detection.cpp index f336c2e008..35f03fa657 100644 --- a/engines/touche/detection.cpp +++ b/engines/touche/detection.cpp @@ -124,6 +124,11 @@ static const ADFileBasedFallback fileBasedFallback[] = { } // End of namespace Touche +static const char *directoryGlobs[] = { + "database", + 0 +}; + static const ADParams detectionParams = { (const byte *)Touche::gameDescriptions, sizeof(ADGameDescription), @@ -136,9 +141,9 @@ static const ADParams detectionParams = { // Additional GUI options (for every game} Common::GUIO_NONE, // Maximum directory depth - 1, + 2, // List of directory globs - 0 + directoryGlobs }; class ToucheMetaEngine : public AdvancedMetaEngine { diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 187e685d06..2dc8b76b4f 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -28,6 +28,8 @@ #include "common/debug-channels.h" #include "common/events.h" #include "common/EventRecorder.h" +#include "common/file.h" +#include "common/fs.h" #include "common/system.h" #include "engines/util.h" @@ -70,6 +72,10 @@ ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) _menuRedrawCounter = 0; memset(_paletteBuffer, 0, sizeof(_paletteBuffer)); + const Common::FSNode gameDataDir(ConfMan.get("path")); + + SearchMan.addSubDirectoryMatching(gameDataDir, "database"); + DebugMan.addDebugChannel(kDebugEngine, "Engine", "Engine debug level"); DebugMan.addDebugChannel(kDebugGraphics, "Graphics", "Graphics debug level"); DebugMan.addDebugChannel(kDebugResource, "Resource", "Resource debug level"); -- cgit v1.2.3 From 36d92b4566ba15d381f56870ccf9898ca0383138 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 14:05:05 +0000 Subject: Fixed kLoad and kUnload (the resource type was incorrect) svn-id: r49931 --- engines/sci/engine/kscripts.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 88e765a0ff..7e33f17f5f 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -36,7 +36,7 @@ namespace Sci { // Loads arbitrary resources of type 'restype' with resource numbers 'resnrs' // This implementation ignores all resource numbers except the first one. reg_t kLoad(EngineState *s, int argc, reg_t *argv) { - int restype = argv[0].toUint16(); + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); int resnr = argv[1].toUint16(); // Request to dynamically allocate hunk memory for later use @@ -76,7 +76,7 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { // Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { if (argc >= 2) { - int restype = argv[0].toUint16(); + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); reg_t resnr = argv[1]; if (restype == kResourceTypeMemory) -- cgit v1.2.3 From 4e7b98db0cd978af5913ca3604fc72f4d4f7d7d9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 14:06:12 +0000 Subject: Removed a now obsolete FIXME (spotted by Fingolfin) svn-id: r49932 --- engines/sci/engine/seg_manager.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 96670b5aeb..310e600133 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -535,9 +535,6 @@ Node *SegManager::lookupNode(reg_t addr) { return NULL; // Non-error null if (getSegmentType(addr.segment) != SEG_TYPE_NODES) { - // FIXME: This occurs right at the beginning of SQ4, when walking north from the first screen. It doesn't - // seem to have any apparent ill-effects, though, so it's been changed to non-fatal, for now - //error("%s, L%d: Attempt to use non-node %04x:%04x as list node", __FILE__, __LINE__, PRINT_REG(addr)); warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); return NULL; } -- cgit v1.2.3 From f403d0f806d56dbe2017374792e0697e6d46bc1f Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 15:02:18 +0000 Subject: Don't translate both x and y of the rect in kOnMe if only one of the variables is negative. Fixes the GKEgo hotspot outside of the Madame Cazanoux's house. svn-id: r49933 --- engines/sci/engine/kernel32.cpp | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index a077f110cf..fb90cfb147 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -792,11 +792,15 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { nsRect.bottom = readSelectorValue(s->_segMan, targetObject, SELECTOR(nsBottom)); uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - if (nsRect.left < 0 || nsRect.top < 0) { - // If top and left are negative, we need to adjust coordinates by the item's x and y - // (e.g. happens in GK1, day 1, with detective Mosely's hotspot in his office) - nsRect.translate(itemX, itemY); - } + + // If top and left are negative, we need to adjust coordinates by the item's x and y + // (e.g. happens in GK1, day 1, with detective Mosely's hotspot in his office) + + if (nsRect.left < 0) + nsRect.translate(itemX, 0); + + if (nsRect.top < 0) + nsRect.translate(0, itemY); // HACK: nsLeft and nsTop can be invalid, so try and fix them here using x and y // (e.g. with the inventory screen in GK1) -- cgit v1.2.3 From 1bbb9d7bd29020566c36d7812c6de236a25c025e Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Thu, 17 Jun 2010 15:46:01 +0000 Subject: Fixed cppcheck warning. svn-id: r49935 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 03989be374..8b2501ff62 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1297,7 +1297,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // Copy video contents to screen buffer g_sci->_gfxScreen->kernelSyncWithFramebuffer(); - delete frameBuf; + delete[] frameBuf; delete videoDecoder; } else warning("Could not play video %s\n", fileName.c_str()); -- cgit v1.2.3 From 00ac852dc861877857bbb4065a6cd1f78f04b023 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 16:06:01 +0000 Subject: SCI: implement workaround for laura bow 2 demo, because that interpreter uses the old real palette merging from sci1 - some views contain a palette that has all colors marked as being used, which would overwrite sysPalette with blacks svn-id: r49936 --- engines/sci/graphics/palette.cpp | 12 ++++++++++++ engines/sci/graphics/palette.h | 1 + 2 files changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index d28fb2ada1..f10446098f 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -57,6 +57,15 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _sysPalette.colors[255].b = 255; _sysPaletteChanged = false; + _alwaysForceRealMerge = false; + + // Pseudo-WORKAROUND + // Laura Bow 2 is an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 + // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging + // If we use the copying over, we will get issues because some views have marked all colors as being used + // and those will overwrite the current palette in that case + if (!strcmp(g_sci->getGameID(), "laurabow2") && (g_sci->isDemo())) + _alwaysForceRealMerge = true; } GfxPalette::~GfxPalette() { @@ -211,6 +220,9 @@ bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealM int i,j; bool paletteChanged = false; + // for Laura Bow 2 demo + forceRealMerge |= _alwaysForceRealMerge; + if ((!forceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes for (i = 1; i < 255; i++) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index d84436d708..fead340090 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -77,6 +77,7 @@ private: uint32 _palVaryEnd; bool _sysPaletteChanged; + bool _alwaysForceRealMerge; Common::Array _schedules; }; -- cgit v1.2.3 From 7bb48adda7e9e04fb1b8a6ccce38b29a143ba835 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 16:09:06 +0000 Subject: SCI: slightly change comment from r49936 svn-id: r49937 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index f10446098f..608c2339f5 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -60,7 +60,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _alwaysForceRealMerge = false; // Pseudo-WORKAROUND - // Laura Bow 2 is an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 + // Laura Bow 2 demo uses an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case -- cgit v1.2.3 From 5daa17473ba3b21683f111989eaa1156f72171cd Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 16:36:01 +0000 Subject: SCI: applying forceRealMerge change to pq1 and qfg3 demo as well (see r49936) for now svn-id: r49938 --- engines/sci/graphics/palette.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 608c2339f5..1b2e5f410e 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -64,8 +64,14 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case + // Quest for Glory 3 demo and police quest 1 vga behave the same interpreter wise and all have glitches, if we don't + // switch back if (!strcmp(g_sci->getGameID(), "laurabow2") && (g_sci->isDemo())) _alwaysForceRealMerge = true; + if (!strcmp(g_sci->getGameID(), "qfg3") && (g_sci->isDemo())) + _alwaysForceRealMerge = true; + if (!strcmp(g_sci->getGameID(), "pq1sci")) + _alwaysForceRealMerge = true; } GfxPalette::~GfxPalette() { -- cgit v1.2.3 From 1cb4f703f116d5d69e72f9ae45fa863fb062ab9f Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 18:30:11 +0000 Subject: Fix the QFG4 Demo: kStrSplit has been replaced with kRemapColors. svn-id: r49939 --- engines/sci/engine/kernel.cpp | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index ef219390a4..b6e064b4d5 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -748,14 +748,16 @@ void Kernel::setDefaultKernelNames() { // In SCI1.1, kSetSynonyms is an empty function _kernelNames[0x26] = "Empty"; - // In the Windows version of KQ6 CD, the empty kSetSynonyms - // function has been replaced with kPortrait. In KQ6 Mac, - // kPlayBack has been replaced by kShowMovie. if (!strcmp(g_sci->getGameID(), "kq6")) { + // In the Windows version of KQ6 CD, the empty kSetSynonyms + // function has been replaced with kPortrait. In KQ6 Mac, + // kPlayBack has been replaced by kShowMovie. if (g_sci->getPlatform() == Common::kPlatformWindows) _kernelNames[0x26] = "Portrait"; else if (g_sci->getPlatform() == Common::kPlatformMacintosh) _kernelNames[0x84] = "ShowMovie"; + } else if (!strcmp(g_sci->getGameID(), "qfg4") && g_sci->isDemo()) { + _kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit } _kernelNames[0x71] = "PalVary"; -- cgit v1.2.3 From 27741ee9707b97bcfa09d4bb4f274e4788a46449 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 17 Jun 2010 19:42:34 +0000 Subject: SCI: dont subtract offTop on wmgrPort when using old gfx functions - fixes about window in pq2 svn-id: r49947 --- engines/sci/graphics/ports.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index b8d38910d1..c964ccd346 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -95,9 +95,12 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te setPort(_wmgrPort); // SCI0 games till kq4 (.502 - not including) did not adjust against _wmgrPort in kNewWindow // We leave _wmgrPort top at 0, so the adjustment wont get done - if (!g_sci->_features->usesOldGfxFunctions()) + if (!g_sci->_features->usesOldGfxFunctions()) { setOrigin(0, offTop); - _wmgrPort->rect.bottom = _screen->getHeight() - offTop; + _wmgrPort->rect.bottom = _screen->getHeight() - offTop; + } else { + _wmgrPort->rect.bottom = _screen->getHeight(); + } _wmgrPort->rect.right = _screen->getWidth(); _wmgrPort->rect.moveTo(0, 0); _wmgrPort->curTop = 0; -- cgit v1.2.3 From c8dfa255a3c812dbd4a852c839407a31c0122a70 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 20:49:33 +0000 Subject: Fixed the selector console command (don't change the selector name to lowercase...) svn-id: r49949 --- engines/sci/console.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 6845e7282e..99494fa800 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -488,7 +488,6 @@ bool Console::cmdSelector(int argc, const char **argv) { } Common::String name = argv[1]; - name.toLowercase(); int seeker = _engine->getKernel()->findSelector(name.c_str()); if (seeker >= 0) { DebugPrintf("Selector %s found at %03x (%d)\n", name.c_str(), seeker, seeker); -- cgit v1.2.3 From 701d69d6e2c1cd6007107720e41c2de2670951a1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 20:52:53 +0000 Subject: Don't show warnings for a known script bug in SQ4CD with the Sq4GlobalNarrator object svn-id: r49950 --- engines/sci/engine/vm.cpp | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 95ed13a3d3..f38ce5e3ab 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -406,19 +406,24 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } if (argc > 1) { - // argc can indeed be bigger than 1 in some cases, and it seems correct - // (i.e. we should skip that many bytes later on)... question is, why - // does this occur? Could such calls be used to point to data after X - // bytes in the heap? What are the skipped bytes in this case? - // In SQ4CD, this occurs with the returnVal selector of object - // Sq4GlobalNarrator when the game starts, and right after the narrator - // is heard (e.g. after he talks when examining something) - reg_t oldReg = *varp.getPointer(s->_segMan); - reg_t newReg = argp[1]; - warning("send_selector(): argc = %d while modifying variable selector " - "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", - argc, selector, g_sci->getKernel()->getSelectorName(selector).c_str(), PRINT_REG(send_obj), - s->_segMan->getObjectName(send_obj), PRINT_REG(oldReg), PRINT_REG(newReg)); + // argc can indeed be bigger than 1 in some cases, and it's usually the + // result of a script bug + + const char *objectName = s->_segMan->getObjectName(send_obj); + + if (!strcmp(objectName, "Sq4GlobalNarrator") && selector == 606) { + // SQ4 has a script bug in the Sq4GlobalNarrator object when invoking the + // returnVal selector, which doesn't affect gameplay, thus don't diplay it + } else { + // Unknown script bug, show it + reg_t oldReg = *varp.getPointer(s->_segMan); + reg_t newReg = argp[1]; + const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); + warning("send_selector(): argc = %d while modifying variable selector " + "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", + argc, selector, selectorName, PRINT_REG(send_obj), + objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); + } } { -- cgit v1.2.3 From 82c36b6b262bd435fc358917494eed34a25eac5c Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 17 Jun 2010 21:00:45 +0000 Subject: Only do video scaling when required (hopefully fixes SQ6). Adapt the scaling code to normal SCI videos as well. svn-id: r49951 --- engines/sci/engine/kgraphics.cpp | 128 +++++++++++++++++---------------------- 1 file changed, 55 insertions(+), 73 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8b2501ff62..4727694729 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1085,6 +1085,58 @@ reg_t kDisplay(EngineState *s, int argc, reg_t *argv) { return g_sci->_gfxPaint16->kernelDisplay(g_sci->strSplit(text.c_str()).c_str(), argc, argv); } +void playVideo(Graphics::VideoDecoder *videoDecoder) { + if (!videoDecoder) + return; + + byte *scaleBuffer = 0; + uint16 width = videoDecoder->getWidth(); + uint16 height = videoDecoder->getHeight(); + uint16 screenWidth = g_system->getWidth(); + uint16 screenHeight = g_system->getHeight(); + + if (screenWidth == 640 && width <= 320 && height <= 240) { + assert(videoDecoder->getPixelFormat().bytesPerPixel == 1); + width *= 2; + height *= 2; + scaleBuffer = new byte[width * height]; + } + + uint16 x = (screenWidth - width) / 2; + uint16 y = (screenHeight - height) / 2; + bool skipVideo = false; + + while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { + if (videoDecoder->needsUpdate()) { + Graphics::Surface *frame = videoDecoder->decodeNextFrame(); + if (frame) { + if (scaleBuffer) { + // TODO: Probably should do aspect ratio correction in e.g. GK1 Windows + g_sci->_gfxScreen->scale2x((byte *)frame->pixels, scaleBuffer, videoDecoder->getWidth(), videoDecoder->getHeight()); + g_system->copyRectToScreen(scaleBuffer, width, x, y, width, height); + } else + g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, width, height); + + if (videoDecoder->hasDirtyPalette()) + videoDecoder->setSystemPalette(); + + g_system->updateScreen(); + } + } + + Common::Event event; + while (g_system->getEventManager()->pollEvent(event)) { + if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) + skipVideo = true; + } + + g_system->delayMillis(10); + } + + delete[] scaleBuffer; + delete videoDecoder; +} + reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { // Hide the cursor if it's showing and then show it again if it was // previously visible. @@ -1161,31 +1213,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { } if (videoDecoder) { - uint16 x = (screenWidth - videoDecoder->getWidth()) / 2; - uint16 y = (screenHeight - videoDecoder->getHeight()) / 2; - bool skipVideo = false; - - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { - if (videoDecoder->needsUpdate()) { - Graphics::Surface *frame = videoDecoder->decodeNextFrame(); - if (frame) { - g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); - - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); - - g_system->updateScreen(); - } - } - - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) { - if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) - skipVideo = true; - } - - g_system->delayMillis(10); - } + playVideo(videoDecoder); // HACK: Switch back to 8bpp if we played a QuickTime video. // We also won't be copying the screen to the SCI screen... @@ -1193,8 +1221,6 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { initGraphics(screenWidth, screenHeight, screenWidth > 320); else g_sci->_gfxScreen->kernelSyncWithFramebuffer(); - - delete videoDecoder; } if (reshowCursor) @@ -1255,52 +1281,8 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { if (reshowCursor) g_sci->_gfxCursor->kernelHide(); - if (videoDecoder && videoDecoder->loadFile(fileName)) { - //uint16 x = (g_system->getWidth() - videoDecoder->getWidth()) / 2; - //uint16 y = (g_system->getHeight() - videoDecoder->getHeight()) / 2; - uint16 w = videoDecoder->getWidth() * 2; - uint16 h = videoDecoder->getHeight() * 2; - uint16 x = (g_system->getWidth() - w) / 2; - uint16 y = (g_system->getHeight() - h) / 2; - byte *frameBuf = new byte[w * h]; - - bool skipVideo = false; - - while (!g_engine->shouldQuit() && !videoDecoder->endOfVideo() && !skipVideo) { - if (videoDecoder->needsUpdate()) { - Graphics::Surface *frame = videoDecoder->decodeNextFrame(); - - if (frame) { - //g_system->copyRectToScreen((byte *)frame->pixels, frame->pitch, x, y, frame->w, frame->h); - // All the VMD videos in SCI2.1 need to be scaled by 2 - // TODO: This isn't optimized much, but since the VMD decoder code will be revamped, we - // don't really care about performance at this point anyway - g_sci->_gfxScreen->scale2x((byte *)frame->pixels, frameBuf, videoDecoder->getWidth(), videoDecoder->getHeight()); - g_system->copyRectToScreen(frameBuf, frame->pitch * 2, x, y, frame->w * 2, frame->h * 2); - - if (videoDecoder->hasDirtyPalette()) - videoDecoder->setSystemPalette(); - - g_system->updateScreen(); - } - } - - Common::Event event; - while (g_system->getEventManager()->pollEvent(event)) { - if ((event.type == Common::EVENT_KEYDOWN && event.kbd.keycode == Common::KEYCODE_ESCAPE) || event.type == Common::EVENT_LBUTTONUP) - skipVideo = true; - } - - g_system->delayMillis(10); - } - - // Copy video contents to screen buffer - g_sci->_gfxScreen->kernelSyncWithFramebuffer(); - - delete[] frameBuf; - delete videoDecoder; - } else - warning("Could not play video %s\n", fileName.c_str()); + if (videoDecoder && videoDecoder->loadFile(fileName)) + playVideo(videoDecoder); if (reshowCursor) g_sci->_gfxCursor->kernelShow(); -- cgit v1.2.3 From d1964ec18b81b157617ac7fb914400ec98cf8255 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Thu, 17 Jun 2010 22:05:28 +0000 Subject: Add additional documentation and code to PlayVMD(1) describing the myriad parameters settable here, and dump actual parameters passed svn-id: r49952 --- engines/sci/engine/kgraphics.cpp | 52 ++++++++++++++++++++++++++++++++++++++-- 1 file changed, 50 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4727694729..cb1a4794b8 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1288,8 +1288,56 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelShow(); break; case 1: - // Unknown. Called with 5 extra integer parameterrs - // (e.g. 174, 95, 20, 0, 55, 236) + { + // Set VMD parameters. Called with a maximum of 5 parameters: + // + // x, y, flags, gammaBoost, gammaFirst, gammaLast + // + // Flags are as follows: + // bit 0 doubled + // bit 1 "drop frames"? + // bit 2 insert black lines + // bit 3 unknown + // bit 4 gamma correction + // bit 5 hold black frame + // bit 6 hold last frame + // bit 7 unknown + // bit 8 stretch + + // gammaBoost boosts palette colors in the range gammaFirst to gammaLast, but + // only if bit 4 in flags is set. Percent value such that 100% = no amplification + // These three parameters are optional if bit 4 is clear. + // Also note that the x, y parameters play subtle games if used with subfx 21. + + int flags = argv[3].offset; + Common::String flagspec; + + if (flags & 1) + flagspec += "doubled "; + if (flags & 2) + flagspec += "dropframes "; + if (flags & 4) + flagspec += "blacklines "; + if (flags & 8) + flagspec += "bit3 "; + if (flags & 16) + flagspec += "gammaboost "; + if (flags & 32) + flagspec += "holdblack "; + if (flags & 64) + flagspec += "holdlast "; + if (flags & 128) + flagspec += "bit7 "; + if (flags & 256) + flagspec += "stretch"; + + warning("VMDFlags: %s", flagspec.c_str()); + warning("x, y: %d, %d", argv[1].offset, argv[2].offset); + + if (argc > 4) + warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset); + break; + } case 6: // Play, perhaps? Or stop? This is the last call made, and takes no extra parameters case 14: -- cgit v1.2.3 From 37434d86ae8f4e7ca3e7f0258c78ad9441f99e31 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Thu, 17 Jun 2010 22:08:07 +0000 Subject: SCI: PlayVMD(1): Hmmm. Don't print gammaBoost etc if they aren't used svn-id: r49953 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index cb1a4794b8..6241c22f88 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1334,7 +1334,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { warning("VMDFlags: %s", flagspec.c_str()); warning("x, y: %d, %d", argv[1].offset, argv[2].offset); - if (argc > 4) + if (argc > 4 && flags & 16) warning("gammaBoost: %d%% between palette entries %d and %d", argv[4].offset, argv[5].offset, argv[6].offset); break; } -- cgit v1.2.3 From 8e07a1e16768548112a290d04348e26173e8afa0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:10:37 +0000 Subject: SCI: Moved the event code a little bit around. * Move sleep() from EventManager to SciEngine * Rename EventManager methods: get -> getSciEvent, and getFromScummVM -> getScummVMEvent * Make scancode_rows static const * Turn altify & numlockify from EventManager methods into static functions (and comment out the currently unused numlockify) svn-id: r49959 --- engines/sci/engine/kevent.cpp | 2 +- engines/sci/engine/kmisc.cpp | 2 +- engines/sci/engine/state.cpp | 2 +- engines/sci/event.cpp | 18 ++++++++++-------- engines/sci/event.h | 9 ++------- engines/sci/graphics/cursor.cpp | 2 +- engines/sci/graphics/menu.cpp | 8 ++++---- engines/sci/graphics/portrait.cpp | 2 +- engines/sci/sci.h | 2 ++ 9 files changed, 23 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index c5a37dde94..718da6c3d3 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -65,7 +65,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { oldx = mousePos.x; oldy = mousePos.y; - curEvent = g_sci->getEventManager()->get(mask); + curEvent = g_sci->getEventManager()->getSciEvent(mask); if (g_sci->getVocabulary()) g_sci->getVocabulary()->parser_event = NULL_REG; // Invalidate parser event diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index ef6088b6d5..99b268f774 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -79,7 +79,7 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { uint32 duration = curTime - s->_throttleLastTime; if (duration < neededSleep) { - g_sci->getEventManager()->sleep(neededSleep - duration); + g_sci->sleep(neededSleep - duration); s->_throttleLastTime = g_system->getMillis(); } else { s->_throttleLastTime = curTime; diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 1c8113e5e4..80b9ba3bcb 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -121,7 +121,7 @@ void EngineState::wait(int16 ticks) { lastWaitTime = time; ticks *= g_debug_sleeptime_factor; - g_sci->getEventManager()->sleep(ticks * 1000 / 60); + g_sci->sleep(ticks * 1000 / 60); } void EngineState::initGlobals() { diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 7a55555a70..6681e12008 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -44,7 +44,7 @@ EventManager::EventManager(ResourceManager *resMan) { EventManager::~EventManager() { } -struct scancode_row { +static const struct scancode_row { int offset; const char *keys; } scancode_rows[SCANCODE_ROWS_NR] = { @@ -53,7 +53,7 @@ struct scancode_row { {0x2c, "ZXCVBNM,./"} }; -int EventManager::altify (int ch) { +static int altify(int ch) { // Calculates a PC keyboard scancode from a character */ int row; int c = toupper((char)ch); @@ -74,7 +74,8 @@ int EventManager::altify (int ch) { return ch; } -int EventManager::numlockify (int c) { +/* +static int numlockify(int c) { switch (c) { case SCI_KEY_DELETE: return '.'; @@ -102,6 +103,7 @@ int EventManager::numlockify (int c) { return c; // Unchanged } } +*/ static const byte codepagemap_88591toDOS[0x80] = { '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', '?', // 0x8x @@ -114,7 +116,7 @@ static const byte codepagemap_88591toDOS[0x80] = { '?', 0xa4, 0x95, 0xa2, 0x93, '?', 0x94, '?', '?', 0x97, 0xa3, 0x96, 0x81, '?', '?', 0x98 // 0xFx }; -sciEvent EventManager::getFromScummVM() { +sciEvent EventManager::getScummVMEvent() { static int _modifierStates = 0; // FIXME: Avoid non-const global vars sciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; @@ -315,7 +317,7 @@ sciEvent EventManager::getFromScummVM() { return input; } -sciEvent EventManager::get(unsigned int mask) { +sciEvent EventManager::getSciEvent(unsigned int mask) { //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; sciEvent event = { 0, 0, 0, 0 }; @@ -328,7 +330,7 @@ sciEvent EventManager::get(unsigned int mask) { // Get all queued events from graphics driver do { - event = getFromScummVM(); + event = getScummVMEvent(); if (event.type != SCI_EVENT_NONE) _events.push_back(event); } while (event.type != SCI_EVENT_NONE); @@ -384,13 +386,13 @@ sciEvent EventManager::get(unsigned int mask) { return event; } -void EventManager::sleep(uint32 msecs) { +void SciEngine::sleep(uint32 msecs) { uint32 time; const uint32 wakeup_time = g_system->getMillis() + msecs; while (true) { // let backend process events and update the screen - get(SCI_EVENT_PEEK); + _eventMan->getSciEvent(SCI_EVENT_PEEK); time = g_system->getMillis(); if (time + 10 < wakeup_time) { g_system->delayMillis(10); diff --git a/engines/sci/event.h b/engines/sci/event.h index 7882e56c02..b973733f48 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -116,15 +116,10 @@ public: EventManager(ResourceManager *resMgr); ~EventManager(); - sciEvent get(unsigned int mask); - - void sleep(uint32 msecs); + sciEvent getSciEvent(unsigned int mask); private: - int altify (int ch); - int shiftify (int c); - int numlockify (int c); - sciEvent getFromScummVM(); + sciEvent getScummVMEvent(); ResourceManager *_resMan; diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 2930bb8a46..369549cf7b 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -341,7 +341,7 @@ void GfxCursor::kernelMoveCursor(Common::Point pos) { // Trigger event reading to make sure the mouse coordinates will // actually have changed the next time we read them. - _event->get(SCI_EVENT_PEEK); + _event->getSciEvent(SCI_EVENT_PEEK); } } // End of namespace Sci diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 5ca4d8176b..f5eac70ccd 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -705,7 +705,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { _paint16->bitsShow(_menuRect); while (true) { - curEvent = _event->get(SCI_EVENT_ANY); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); switch (curEvent.type) { case SCI_EVENT_KEYBOARD: @@ -795,7 +795,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { } break; case SCI_EVENT_NONE: - _event->sleep(2500 / 1000); + g_sci->sleep(2500 / 1000); break; } } @@ -823,7 +823,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { _paint16->bitsShow(_ports->_menuRect); while (true) { - curEvent = _event->get(SCI_EVENT_ANY); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); switch (curEvent.type) { case SCI_EVENT_MOUSE_RELEASE: @@ -834,7 +834,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { return curItemEntry; case SCI_EVENT_NONE: - _event->sleep(2500 / 1000); + g_sci->sleep(2500 / 1000); break; } diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index f7d6f4de0a..9c113cf5f4 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -182,7 +182,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Wait till syncTime passed, then show specific animation bitmap do { g_sci->getEngineState()->wait(1); - curEvent = _event->get(SCI_EVENT_ANY); + curEvent = _event->getSciEvent(SCI_EVENT_ANY); if (curEvent.type == SCI_EVENT_MOUSE_PRESS || (curEvent.type == SCI_EVENT_KEYBOARD && curEvent.data == SCI_KEY_ESC) || g_engine->shouldQuit()) diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 7d04840759..6a069fecda 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -176,6 +176,8 @@ public: /** Remove the 'TARGET-' prefix of the given filename, if present. */ Common::String unwrapFilename(const Common::String &name) const; + void sleep(uint32 msecs); + public: /** -- cgit v1.2.3 From a2bcf9ac31d025d09fabcd2d636eeb34d3c75df0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:11:12 +0000 Subject: SCI: Rename sciEvent to SciEvent svn-id: r49960 --- engines/sci/engine/kevent.cpp | 2 +- engines/sci/event.cpp | 10 +++++----- engines/sci/event.h | 8 ++++---- engines/sci/graphics/menu.cpp | 4 ++-- engines/sci/graphics/portrait.cpp | 2 +- 5 files changed, 13 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 718da6c3d3..2f1afd4358 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -41,7 +41,7 @@ namespace Sci { reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { int mask = argv[0].toUint16(); reg_t obj = argv[1]; - sciEvent curEvent; + SciEvent curEvent; int oldx, oldy; int modifier_mask = getSciVersion() <= SCI_VERSION_01 ? SCI_KEYMOD_ALL : SCI_KEYMOD_NO_FOOLOCK; SegManager *segMan = s->_segMan; diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 6681e12008..9ba4f166b4 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -116,9 +116,9 @@ static const byte codepagemap_88591toDOS[0x80] = { '?', 0xa4, 0x95, 0xa2, 0x93, '?', 0x94, '?', '?', 0x97, 0xa3, 0x96, 0x81, '?', '?', 0x98 // 0xFx }; -sciEvent EventManager::getScummVMEvent() { +SciEvent EventManager::getScummVMEvent() { static int _modifierStates = 0; // FIXME: Avoid non-const global vars - sciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; + SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; Common::EventManager *em = g_system->getEventManager(); Common::Event ev; @@ -317,9 +317,9 @@ sciEvent EventManager::getScummVMEvent() { return input; } -sciEvent EventManager::getSciEvent(unsigned int mask) { +SciEvent EventManager::getSciEvent(unsigned int mask) { //sci_event_t error_event = { SCI_EVT_ERROR, 0, 0, 0 }; - sciEvent event = { 0, 0, 0, 0 }; + SciEvent event = { 0, 0, 0, 0 }; // Update the screen here, since it's called very often. // Throttle the screen update rate to 60fps. @@ -336,7 +336,7 @@ sciEvent EventManager::getSciEvent(unsigned int mask) { } while (event.type != SCI_EVENT_NONE); // Search for matching event in queue - Common::List::iterator iter = _events.begin(); + Common::List::iterator iter = _events.begin(); while (iter != _events.end() && !((*iter).type & mask)) ++iter; diff --git a/engines/sci/event.h b/engines/sci/event.h index b973733f48..bdfbf4bebe 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -34,7 +34,7 @@ namespace Sci { #define SCI_INPUT_DEFAULT_REDRAWTIME 30000 -struct sciEvent { +struct SciEvent { short type; short data; short modifiers; @@ -116,15 +116,15 @@ public: EventManager(ResourceManager *resMgr); ~EventManager(); - sciEvent getSciEvent(unsigned int mask); + SciEvent getSciEvent(unsigned int mask); private: - sciEvent getScummVMEvent(); + SciEvent getScummVMEvent(); ResourceManager *_resMan; bool _fontIsExtended; - Common::List _events; + Common::List _events; }; } // End of namespace Sci diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index f5eac70ccd..00eb533b41 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -681,7 +681,7 @@ uint16 GfxMenu::mouseFindMenuItemSelection(Common::Point mousePosition, uint16 m } GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { - sciEvent curEvent; + SciEvent curEvent; uint16 newMenuId = _curMenuId; uint16 newItemId = _curItemId; GuiMenuItemEntry *curItemEntry = findItem(_curMenuId, _curItemId); @@ -805,7 +805,7 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { // The menu item that is selected at that time is chosen. If no menu item is selected we cancel // No keyboard interaction is allowed, cause that wouldnt make any sense at all GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { - sciEvent curEvent; + SciEvent curEvent; uint16 newMenuId = 0, newItemId = 0; uint16 curMenuId = 0, curItemId = 0; Common::Point mousePosition = _cursor->getPosition(); diff --git a/engines/sci/graphics/portrait.cpp b/engines/sci/graphics/portrait.cpp index 9c113cf5f4..8f4fe094a8 100644 --- a/engines/sci/graphics/portrait.cpp +++ b/engines/sci/graphics/portrait.cpp @@ -166,7 +166,7 @@ void Portrait::doit(Common::Point position, uint16 resourceId, uint16 noun, uint // Do animation depending on sync resource till audio is done playing uint16 syncCue; int timerPosition, curPosition; - sciEvent curEvent; + SciEvent curEvent; bool userAbort = false; while ((syncOffset < syncResource->size - 2) && (!userAbort)) { -- cgit v1.2.3 From fabba55e6df2a3ae1b1bba5f3e145cae5bba0dc4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:11:34 +0000 Subject: SCI: cleanup svn-id: r49961 --- engines/sci/event.cpp | 4 +--- engines/sci/event.h | 36 ++++++++++++++++-------------------- engines/sci/sci.cpp | 2 +- 3 files changed, 18 insertions(+), 24 deletions(-) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 9ba4f166b4..45de30cb5c 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -36,9 +36,7 @@ namespace Sci { #define SCANCODE_ROWS_NR 3 -EventManager::EventManager(ResourceManager *resMan) { - // Check, if font of current game includes extended chars - _fontIsExtended = resMan->detectFontExtended(); +EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) { } EventManager::~EventManager() { diff --git a/engines/sci/event.h b/engines/sci/event.h index bdfbf4bebe..dc7aebc98e 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -23,31 +23,29 @@ * */ -#ifndef SCI_ENGINE_EVENT_H -#define SCI_ENGINE_EVENT_H +#ifndef SCI_EVENT_H +#define SCI_EVENT_H #include "common/list.h" namespace Sci { -#define SCI_INPUT_DEFAULT_CLOCKTIME 100000 -#define SCI_INPUT_DEFAULT_REDRAWTIME 30000 - - struct SciEvent { short type; short data; short modifiers; - short character; /* for keyboard events: 'data' after applying - ** the effects of 'modifiers', e.g. if - ** type == SCI_EVT_KEYBOARD - ** data == 'a' - ** buckybits == SCI_EVM_LSHIFT - ** then - ** character == 'A' - ** For 'Alt', characters are interpreted by their - ** PC keyboard scancodes. - */ + /** + * For keyboard events: 'data' after applying + * the effects of 'modifiers', e.g. if + * type == SCI_EVT_KEYBOARD + * data == 'a' + * buckybits == SCI_EVM_LSHIFT + * then + * character == 'A' + * For 'Alt', characters are interpreted by their + * PC keyboard scancodes. + */ + short character; }; /*Values for type*/ @@ -113,7 +111,7 @@ struct SciEvent { class EventManager { public: - EventManager(ResourceManager *resMgr); + EventManager(bool fontIsExtended); ~EventManager(); SciEvent getSciEvent(unsigned int mask); @@ -121,9 +119,7 @@ public: private: SciEvent getScummVMEvent(); - ResourceManager *_resMan; - - bool _fontIsExtended; + const bool _fontIsExtended; Common::List _events; }; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 1dc02ac7c3..f29811cfae 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -237,7 +237,7 @@ Common::Error SciEngine::run() { _vocabulary = (getSciVersion() <= SCI_VERSION_1_EGA) ? new Vocabulary(_resMan) : NULL; _audio = new AudioPlayer(_resMan); _gamestate = new EngineState(segMan); - _eventMan = new EventManager(_resMan); + _eventMan = new EventManager(_resMan->detectFontExtended()); // The game needs to be initialized before the graphics system is initialized, as // the graphics code checks parts of the seg manager upon initialization (e.g. for -- cgit v1.2.3 From 06997c0da6f45a760b8bf4dcf3d604bc1a977bad Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:11:56 +0000 Subject: SCI: Update FIXME in SegmentManager * Turn one FIXME into a simple comment * Rewrap comment to 80 columns * Turn several warnings into errors svn-id: r49962 --- engines/sci/engine/seg_manager.cpp | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 310e600133..58b496ccfc 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -100,16 +100,10 @@ void SegManager::initSysStrings() { } SegmentId SegManager::findFreeSegment() const { - // FIXME: This is a very crude approach: We find a free segment id by scanning - // from the start. This can be slow if the number of segments becomes large. - // Optimizations are possible and easy, but I refrain from doing any until this - // refactoring is complete. - // One very simple yet probably effective approach would be to add - // "int firstFreeSegment", which is updated when allocating/freeing segments. - // There are some scenarios where it performs badly, but we should first check - // whether those occur at all. If so, there are easy refinements that deal - // with this. Finally, we could switch to a more elaborate scheme, - // such as keeping track of all free segments. But I doubt this is necessary. + // The following is a very crude approach: We find a free segment id by + // scanning from the start. This can be slow if the number of segments + // becomes large. Optimizations are possible and easy, but I'll refrain + // from attempting any until we determine we actually need it. uint seg = 1; while (seg < _heap.size() && _heap[seg]) { ++seg; @@ -516,14 +510,14 @@ reg_t SegManager::newNode(reg_t value, reg_t key) { List *SegManager::lookupList(reg_t addr) { if (getSegmentType(addr.segment) != SEG_TYPE_LISTS) { - warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); + error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } ListTable *lt = (ListTable *)_heap[addr.segment]; if (!lt->isValidEntry(addr.offset)) { - warning("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); + error("Attempt to use non-list %04x:%04x as list", PRINT_REG(addr)); return NULL; } @@ -535,14 +529,14 @@ Node *SegManager::lookupNode(reg_t addr) { return NULL; // Non-error null if (getSegmentType(addr.segment) != SEG_TYPE_NODES) { - warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + error("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); return NULL; } NodeTable *nt = (NodeTable *)_heap[addr.segment]; if (!nt->isValidEntry(addr.offset)) { - warning("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + error("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); return NULL; } -- cgit v1.2.3 From 2556ea192cac369f86d1b237335ae7c0aa0b13e2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:12:17 +0000 Subject: SCI: Turn _modifierStates into member of class EventManager svn-id: r49963 --- engines/sci/event.cpp | 3 +-- engines/sci/event.h | 1 + 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 45de30cb5c..b93f7bddec 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -36,7 +36,7 @@ namespace Sci { #define SCANCODE_ROWS_NR 3 -EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended) { +EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) { } EventManager::~EventManager() { @@ -115,7 +115,6 @@ static const byte codepagemap_88591toDOS[0x80] = { }; SciEvent EventManager::getScummVMEvent() { - static int _modifierStates = 0; // FIXME: Avoid non-const global vars SciEvent input = { SCI_EVENT_NONE, 0, 0, 0 }; Common::EventManager *em = g_system->getEventManager(); diff --git a/engines/sci/event.h b/engines/sci/event.h index dc7aebc98e..314add7b2c 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -120,6 +120,7 @@ private: SciEvent getScummVMEvent(); const bool _fontIsExtended; + int _modifierStates; Common::List _events; }; -- cgit v1.2.3 From 69fb7032460e7874d12d8f07bcc436eb0bbab18d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:12:38 +0000 Subject: SCI: cleanup scancode rows code svn-id: r49964 --- engines/sci/event.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index b93f7bddec..eff7984d39 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -34,18 +34,19 @@ namespace Sci { -#define SCANCODE_ROWS_NR 3 - EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) { } EventManager::~EventManager() { } -static const struct scancode_row { + +struct ScancodeRow { int offset; const char *keys; -} scancode_rows[SCANCODE_ROWS_NR] = { +}; + +static const ScancodeRow s_scancodeRows[] = { {0x10, "QWERTYUIOP[]"}, {0x1e, "ASDFGHJKL;'\\"}, {0x2c, "ZXCVBNM,./"} @@ -56,9 +57,9 @@ static int altify(int ch) { int row; int c = toupper((char)ch); - for (row = 0; row < SCANCODE_ROWS_NR; row++) { - const char *keys = scancode_rows[row].keys; - int offset = scancode_rows[row].offset; + for (row = 0; row < ARRAYSIZE(s_scancodeRows); row++) { + const char *keys = s_scancodeRows[row].keys; + int offset = s_scancodeRows[row].offset; while (*keys) { if (*keys == c) -- cgit v1.2.3 From 337711d3215bf199260746920c46f7db85a2f70c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:12:59 +0000 Subject: SCI: Get rid of duplicate _system member in SciEngine svn-id: r49965 --- engines/sci/sci.cpp | 2 +- engines/sci/sci.h | 1 - 2 files changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index f29811cfae..c594184f29 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -72,7 +72,7 @@ SciEngine *g_sci = 0; class GfxDriver; SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) - : Engine(syst), _gameDescription(desc), _system(syst) { + : Engine(syst), _gameDescription(desc) { assert(g_sci == 0); g_sci = this; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 6a069fecda..5ea5edc17b 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -272,7 +272,6 @@ private: EventManager *_eventMan; reg_t _gameObj; /**< Pointer to the game object */ Console *_console; - OSystem *_system; }; -- cgit v1.2.3 From cfcbdf86569dac5856d364316caa5b0a57713fd7 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:13:30 +0000 Subject: SCI: Remove selector_name function, some cleanup svn-id: r49966 --- engines/sci/console.cpp | 28 +++++++------------ engines/sci/engine/kernel.cpp | 8 ++++-- engines/sci/engine/kernel.h | 2 ++ engines/sci/engine/scriptdebug.cpp | 56 +++++++++++++++----------------------- engines/sci/sci.cpp | 2 +- 5 files changed, 40 insertions(+), 56 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 99494fa800..d17b1facaa 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -419,13 +419,6 @@ ResourceType parseResourceType(const char *resid) { return res; } -const char *selector_name(EngineState *s, int selector) { - if (selector >= 0 && selector < (int)g_sci->getKernel()->getSelectorNamesSize()) - return g_sci->getKernel()->getSelectorName(selector).c_str(); - else - return "--INVALID--"; -} - bool Console::cmdGetVersion(int argc, const char **argv) { const char *viewTypeDesc[] = { "Unknown", "EGA", "VGA", "VGA SCI1.1", "Amiga" }; @@ -2217,7 +2210,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { if (reg_end.segment != 0 && size < reg_end.offset - reg.offset) { DebugPrintf("Block end out of bounds (size %d). Resetting.\n", size); - reg_end = NULL_REG; + reg_end = NULL_REG; } if (reg_end.segment != 0 && (size >= reg_end.offset - reg.offset)) @@ -2324,11 +2317,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) { switch (call.type) { - case EXEC_STACK_TYPE_CALL: {// Normal function + case EXEC_STACK_TYPE_CALL: // Normal function DebugPrintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "" : - selector_name(_engine->_gamestate, call.selector)); - } - break; + _engine->getKernel()->getSelectorName(call.selector).c_str()); + break; case EXEC_STACK_TYPE_KERNEL: // Kernel function DebugPrintf(" %x:[%x] k%s(", i, call.origin, _engine->getKernel()->getKernelName(call.selector).c_str()); @@ -2554,11 +2546,11 @@ bool Console::cmdSend(int argc, const char **argv) { return true; } - const char *selector_name = argv[2]; - int selectorId = _engine->getKernel()->findSelector(selector_name); + const char *selectorName = argv[2]; + int selectorId = _engine->getKernel()->findSelector(selectorName); if (selectorId < 0) { - DebugPrintf("Unknown selector: \"%s\"\n", selector_name); + DebugPrintf("Unknown selector: \"%s\"\n", selectorName); return true; } @@ -2571,7 +2563,7 @@ bool Console::cmdSend(int argc, const char **argv) { SelectorType selector_type = lookupSelector(_engine->_gamestate->_segMan, object, selectorId, NULL, NULL); if (selector_type == kSelectorNone) { - DebugPrintf("Object does not support selector: \"%s\"\n", selector_name); + DebugPrintf("Object does not support selector: \"%s\"\n", selectorName); return true; } @@ -3273,7 +3265,7 @@ int Console::printObject(reg_t pos) { DebugPrintf(" "); if (i < var_container->getVarCount()) { uint16 varSelector = var_container->getVarSelector(i); - DebugPrintf("[%03x] %s = ", varSelector, selector_name(s, varSelector)); + DebugPrintf("[%03x] %s = ", varSelector, _engine->getKernel()->getSelectorName(varSelector).c_str()); } else DebugPrintf("p#%x = ", i); @@ -3292,7 +3284,7 @@ int Console::printObject(reg_t pos) { DebugPrintf(" -- methods:\n"); for (i = 0; i < obj->getMethodCount(); i++) { reg_t fptr = obj->getFunction(i); - DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), selector_name(s, obj->getFuncSelector(i)), PRINT_REG(fptr)); + DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } if (s->_segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT) DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->_nr); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index b6e064b4d5..8ebe78637c 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -410,7 +410,8 @@ SciKernelFunction kfunct_mappers[] = { {NULL, NULL, NULL} // Terminator }; -Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan) { +Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) + : _resMan(resMan), _segMan(segMan), _invalid("") { loadSelectorNames(); mapSelectors(); // Map a few special selectors for later use } @@ -428,6 +429,8 @@ uint Kernel::getSelectorNamesSize() const { } const Common::String &Kernel::getSelectorName(uint selector) const { + if (selector >= _selectorNames.size()) + return _invalid; return _selectorNames[selector]; } @@ -439,9 +442,8 @@ const Common::String &Kernel::getKernelName(uint number) const { // FIXME: The following check is a temporary workaround for // an issue leading to crashes when using the debugger's backtrace // command. - static const Common::String invalid = "(invalid)"; if (number >= _kernelNames.size()) - return invalid; + return _invalid; return _kernelNames[number]; } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 0a4998868d..f17e751709 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -246,6 +246,8 @@ private: // Kernel-related lists Common::StringArray _selectorNames; Common::StringArray _kernelNames; + + const Common::String _invalid; }; #ifdef USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 436eaafec5..d829b01c31 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -63,9 +63,7 @@ const char *opcodeNames[] = { "-sli", "-sti", "-spi" }; -extern const char *selector_name(EngineState *s, int selector); - -DebugState g_debugState; +DebugState g_debugState; // FIXME: Avoid non-const global vars // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) { @@ -197,7 +195,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!obj) warning("Attempted to reference on non-object at %04x:%04x", PRINT_REG(s->xs->objp)); else - printf(" (%s)", selector_name(s, obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1]))); + printf(" (%s)", g_sci->getKernel()->getSelectorName(obj->propertyOffsetToId(s->_segMan, scr[pos.offset + 1])).c_str()); } } @@ -244,7 +242,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod if (!name) name = ""; - printf(" %s::%s[", name, (selector > kernel->getSelectorNamesSize()) ? "" : selector_name(s, selector)); + printf(" %s::%s[", name, g_sci->getKernel()->getSelectorName(selector).c_str()); switch (lookupSelector(s->_segMan, called_obj_addr, selector, 0, &fun_ref)) { case kSelectorMethod: @@ -314,17 +312,15 @@ void script_debug(EngineState *s) { if (paramb1 != g_debugState.seekSpecial) return; - case kDebugSeekCallk: { + case kDebugSeekCallk: if (op != op_callk) return; break; - } - case kDebugSeekLevelRet: { + case kDebugSeekLevelRet: if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1)) return; break; - } case kDebugSeekGlobal: if (op < op_sag) @@ -361,7 +357,7 @@ void script_debug(EngineState *s) { g_debugState.debugging = false; - Console *con = ((Sci::SciEngine*)g_engine)->getSciDebugger(); + Console *con = ((Sci::SciEngine *)g_engine)->getSciDebugger(); con->attach(); } @@ -491,19 +487,17 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { dumpScriptObject((char *)script->data, seeker, objsize); break; - case SCI_OBJ_CODE: { + case SCI_OBJ_CODE: printf("Code\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case 3: { + case 3: printf("\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_SAID: { + case SCI_OBJ_SAID: printf("Said\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); @@ -551,46 +545,40 @@ void Kernel::dissectScript(int scriptNumber, Vocabulary *vocab) { } } printf("\n"); - } - break; + break; - case SCI_OBJ_STRINGS: { + case SCI_OBJ_STRINGS: printf("Strings\n"); while (script->data [seeker]) { printf("%04x: %s\n", seeker, script->data + seeker); seeker += strlen((char *)script->data + seeker) + 1; } seeker++; // the ending zero byte - }; - break; + break; case SCI_OBJ_CLASS: dumpScriptClass((char *)script->data, seeker, objsize); break; - case SCI_OBJ_EXPORTS: { + case SCI_OBJ_EXPORTS: printf("Exports\n"); Common::hexdump((unsigned char *)script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_POINTERS: { + case SCI_OBJ_POINTERS: printf("Pointers\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case 9: { + case 9: printf("\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; - case SCI_OBJ_LOCALVARS: { + case SCI_OBJ_LOCALVARS: printf("Local vars\n"); Common::hexdump(script->data + seeker, objsize - 4, 16, seeker); - }; - break; + break; default: printf("Unsupported!\n"); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index c594184f29..00f832817b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -276,7 +276,7 @@ Common::Error SciEngine::run() { #ifdef ENABLE_SCI32 } #endif - + _kernel->loadKernelNames(_features); // Must be called after game_init() script_adjust_opcode_formats(); -- cgit v1.2.3 From 78cd1aa145fb454de67444ef58bed6381ce2396c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:13:54 +0000 Subject: SCI: Remove hack related to compiled kernel signatures. Also change some things to comply to our code formatting conventions. svn-id: r49967 --- engines/sci/engine/kernel.cpp | 45 ++++++++++++++++++++----------------------- engines/sci/engine/kernel.h | 6 +++--- engines/sci/engine/vm.cpp | 6 +++--- 3 files changed, 27 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 8ebe78637c..7367e3f34a 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -201,11 +201,11 @@ static const char *s_defaultKernelNames[] = { struct SciKernelFunction { const char *name; - KernelFunc *fun; /* The actual function */ + KernelFunc *func; /* The actual function */ const char *signature; /* kfunct signature */ }; -SciKernelFunction kfunct_mappers[] = { +static SciKernelFunction s_kernelFuncMap[] = { /*00*/ { "Load", kLoad, "iii*" }, /*01*/ { "UnLoad", kUnLoad, "i.*" }, // Work around SQ1 bug, when exiting the Ulence flats bar /*02*/ { "ScriptID", kScriptID, "Ioi*" }, @@ -418,10 +418,7 @@ Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) Kernel::~Kernel() { for (KernelFuncsContainer::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i) - // TODO: Doing a const_cast is not that nice actually... But since KernelFuncWithSignature - // keeps the signature member as "const char *" there is no way around it. - // Think of a clever way to avoid this. - free(const_cast(i->signature)); + free(i->signature); } uint Kernel::getSelectorNamesSize() const { @@ -498,23 +495,23 @@ void Kernel::loadSelectorNames() { } } -static void kernel_compile_signature(const char **s) { - const char *src = *s; +static char *compileKernelSignature(const char *s) { + const char *src = s; char *result; bool ellipsis = false; int index = 0; if (!src) - return; // NULL signature: Nothing to do + return 0; // NULL signature: Nothing to do - result = (char *)malloc(strlen(*s) + 1); + result = (char *)malloc(strlen(s) + 1); while (*src) { char c; char v = 0; if (ellipsis) { - error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", *s, *src); + error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", s, *src); } do { @@ -558,7 +555,7 @@ static void kernel_compile_signature(const char **s) { break; default: - error("ERROR compiling kernel function signature '%s': (%02x / '%c') not understood", *s, c, c); + error("ERROR compiling kernel function signature '%s': (%02x / '%c') not understood", s, c, c); } } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY))); @@ -567,7 +564,8 @@ static void kernel_compile_signature(const char **s) { } result[index] = 0; - *s = result; // Write back + + return result; } void Kernel::mapFunctions() { @@ -584,9 +582,9 @@ void Kernel::mapFunctions() { Common::String sought_name = _kernelNames[functnr]; // Reset the table entry - _kernelFuncs[functnr].fun = NULL; + _kernelFuncs[functnr].func = NULL; _kernelFuncs[functnr].signature = NULL; - _kernelFuncs[functnr].orig_name = sought_name; + _kernelFuncs[functnr].origName = sought_name; if (sought_name.empty()) { // No name was given -> must be an unknown opcode @@ -601,10 +599,10 @@ void Kernel::mapFunctions() { continue; } - // If the name is known, look it up in kfunct_mappers. This table + // If the name is known, look it up in s_kernelFuncMap. This table // maps kernel func names to actual function (pointers). - for (uint seeker = 0; (found == -1) && kfunct_mappers[seeker].name; seeker++) - if (sought_name == kfunct_mappers[seeker].name) + for (uint seeker = 0; (found == -1) && s_kernelFuncMap[seeker].name; seeker++) + if (sought_name == s_kernelFuncMap[seeker].name) found = seeker; // Found a kernel function with the correct name! if (found == -1) { @@ -612,15 +610,14 @@ void Kernel::mapFunctions() { warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr); _kernelFuncs[functnr].isDummy = true; } else { - // A match in kfunct_mappers was found - if (kfunct_mappers[found].fun) { - _kernelFuncs[functnr].fun = kfunct_mappers[found].fun; - _kernelFuncs[functnr].signature = kfunct_mappers[found].signature; + // A match in s_kernelFuncMap was found + if (s_kernelFuncMap[found].func) { + _kernelFuncs[functnr].func = s_kernelFuncMap[found].func; + _kernelFuncs[functnr].signature = compileKernelSignature(s_kernelFuncMap[found].signature); _kernelFuncs[functnr].isDummy = false; - kernel_compile_signature(&(_kernelFuncs[functnr].signature)); ++mapped; } else { - //warning("Ignoring function %s\n", kfunct_mappers[found].name); + //warning("Ignoring function %s\n", s_kernelFuncMap[found].name); ++ignored; } } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index f17e751709..11bc76348d 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -115,9 +115,9 @@ enum { typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv); struct KernelFuncWithSignature { - KernelFunc *fun; /**< The actual function */ - const char *signature; /**< KernelFunc signature */ - Common::String orig_name; /**< Original name, in case we couldn't map it */ + KernelFunc *func; /**< The actual function */ + char *signature; /**< KernelFunc signature */ + Common::String origName; /**< Original name, in case we couldn't map it */ bool isDummy; }; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f38ce5e3ab..3fbfba1c92 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -590,7 +590,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { xstack->selector = kernelFuncNum; xstack->type = EXEC_STACK_TYPE_KERNEL; - //warning("callk %s", kernelFunc.orig_name.c_str()); + //warning("callk %s", kernelFunc.origName.c_str()); // TODO: SCI2.1 equivalent if (s->loadFromLauncher >= 0 && ( @@ -614,13 +614,13 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { kRestoreGame(s, 2, restoreArgv); } else { // Call kernel function - s->r_acc = kernelFunc.fun(s, argc, argv); + s->r_acc = kernelFunc.func(s, argc, argv); } // Remove callk stack frame again s->_executionStack.pop_back(); } else { - Common::String warningMsg = "Dummy function " + kernelFunc.orig_name + + Common::String warningMsg = "Dummy function " + kernelFunc.origName + Common::String::printf("[0x%x]", kernelFuncNum) + " invoked - ignoring. Params: " + Common::String::printf("%d", argc) + " ("; -- cgit v1.2.3 From 359be0c0665d9fed898ad1c511614a76ee92e331 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:14:34 +0000 Subject: SCI: Change SciEngine's 'char *getGameID()' to 'Common::String getGameId()' svn-id: r49968 --- engines/sci/console.cpp | 2 +- engines/sci/engine/kernel.cpp | 4 ++-- engines/sci/engine/kgraphics.cpp | 8 ++++---- engines/sci/engine/kmisc.cpp | 4 ++-- engines/sci/engine/kpathing.cpp | 4 ++-- engines/sci/graphics/palette.cpp | 6 +++--- engines/sci/graphics/picture.cpp | 4 ++-- engines/sci/graphics/ports.cpp | 2 +- engines/sci/graphics/screen.cpp | 4 ++-- engines/sci/sci.cpp | 20 +++++++------------- engines/sci/sci.h | 3 ++- 11 files changed, 28 insertions(+), 33 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index d17b1facaa..b46e03830d 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -424,7 +424,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) { bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false; - DebugPrintf("Game ID: %s\n", _engine->getGameID()); + DebugPrintf("Game ID: %s\n", _engine->getGameId().c_str()); DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); DebugPrintf("\n"); DebugPrintf("Detected features:\n"); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 7367e3f34a..6e02bbbb4e 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -747,7 +747,7 @@ void Kernel::setDefaultKernelNames() { // In SCI1.1, kSetSynonyms is an empty function _kernelNames[0x26] = "Empty"; - if (!strcmp(g_sci->getGameID(), "kq6")) { + if (g_sci->getGameId() == "kq6") { // In the Windows version of KQ6 CD, the empty kSetSynonyms // function has been replaced with kPortrait. In KQ6 Mac, // kPlayBack has been replaced by kShowMovie. @@ -755,7 +755,7 @@ void Kernel::setDefaultKernelNames() { _kernelNames[0x26] = "Portrait"; else if (g_sci->getPlatform() == Common::kPlatformMacintosh) _kernelNames[0x84] = "ShowMovie"; - } else if (!strcmp(g_sci->getGameID(), "qfg4") && g_sci->isDemo()) { + } else if (g_sci->getGameId() == "qfg4" && g_sci->isDemo()) { _kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 6241c22f88..0a334924ab 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -534,7 +534,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened, // till the actual problem is found - if (!strcmp(g_sci->getGameID(), "lsl1sci") && s->currentRoomNumber() == 300) { + if (g_sci->getGameId() == "lsl1sci" && s->currentRoomNumber() == 300) { int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop)); writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2); } @@ -807,7 +807,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { // ALL other games use a hardcoded -1 (madness!) // We are detecting jones/talkie as "jones" as well, but the sierra interpreter of talkie doesnt have this // "hack". Hopefully it wont cause regressions (the code causes regressions if used against kq5/floppy) - if (!strcmp(g_sci->getGameID(), "jones")) + if (g_sci->getGameId() == "jones") priority = readSelectorValue(s->_segMan, controlObject, SELECTOR(priority)); else priority = -1; @@ -991,7 +991,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; - if (!strcmp(g_sci->getGameID(), "freddypharkas") || !strcmp(g_sci->getGameID(), "freddypharkas-demo")) { + if (g_sci->getGameId() == "freddypharkas" || g_sci->getGameId() == "freddypharkas-demo") { // WORKAROUND // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would @@ -1002,7 +1002,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { priority = 15; } - if (!strcmp(g_sci->getGameID(), "laurabow2")) { + if (g_sci->getGameId() == "laurabow2") { // WORKAROUND // see the one above if ((viewId == 995) && (priority == 0)) diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 99b268f774..525f9f5bf4 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -59,9 +59,9 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { // LSL3 calculates a machinespeed variable during game startup (right after the filthy questions) // This one would go through w/o throttling resulting in having to do 1000 pushups or something // Another way of handling this would be delaying incrementing of "machineSpeed" selector - if (!strcmp(g_sci->getGameID(), "lsl3") && s->currentRoomNumber() == 290) + if (g_sci->getGameId() == "lsl3" && s->currentRoomNumber() == 290) s->_throttleTrigger = true; - if (!strcmp(g_sci->getGameID(), "iceman") && s->currentRoomNumber() == 27) { + if (g_sci->getGameId() == "iceman" && s->currentRoomNumber() == 27) { s->_throttleTrigger = true; neededSleep = 60; } diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 857ccc2a08..09cec29a79 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1056,7 +1056,7 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { // WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator // Polygon has 17 points but size is set to 19 - if ((size == 19) && !strcmp(g_sci->getGameID(), "lsl1sci")) { + if ((size == 19) && g_sci->getGameId() == "lsl1sci") { if ((s->currentRoomNumber() == 350) && (read_point(segMan, points, 18) == Common::Point(108, 137))) { debug(1, "Applying fix for broken polygon in lsl1sci, room 350"); @@ -1174,7 +1174,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co // WORKAROUND LSL5 room 660. Priority glitch due to us choosing a different path // than SSCI. Happens when Patti walks to the control room. - if (!strcmp(g_sci->getGameID(), "lsl5") && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { + if (g_sci->getGameId() == "lsl5" && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { debug(1, "[avoidpath] Applying fix for priority problem in LSL5, room 660"); pf_s->_prependPoint = new_start; new_start = new Common::Point(77, 107); diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 1b2e5f410e..35741dedf7 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -66,11 +66,11 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) // and those will overwrite the current palette in that case // Quest for Glory 3 demo and police quest 1 vga behave the same interpreter wise and all have glitches, if we don't // switch back - if (!strcmp(g_sci->getGameID(), "laurabow2") && (g_sci->isDemo())) + if (g_sci->getGameId() == "laurabow2" && (g_sci->isDemo())) _alwaysForceRealMerge = true; - if (!strcmp(g_sci->getGameID(), "qfg3") && (g_sci->isDemo())) + else if (g_sci->getGameId() == "qfg3" && (g_sci->isDemo())) _alwaysForceRealMerge = true; - if (!strcmp(g_sci->getGameID(), "pq1sci")) + else if (g_sci->getGameId() == "pq1sci") _alwaysForceRealMerge = true; } diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index a59153f116..0b62a558ca 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -437,7 +437,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette)); memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority)); - if (strcmp(g_sci->getGameID(), "iceman") == 0) { + if (g_sci->getGameId() == "iceman") { // WORKAROUND: we remove certain visual&priority lines in underwater rooms of iceman, when not dithering the // picture. Normally those lines aren't shown, because they share the same color as the dithered // fill color combination. When not dithering, those lines would appear and get distracting. @@ -532,7 +532,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { // inside picture data for such games case PIC_OP_SET_PATTERN: if (_resourceType >= SCI_PICTURE_TYPE_SCI11) { - if (strcmp(g_sci->getGameID(), "sq4") == 0) { + if (g_sci->getGameId() == "sq4") { // WORKAROUND: For SQ4 / for some pictures handle this like a terminator // This picture includes garbage data, first a set pattern w/o parameter and then short pattern // I guess that garbage is a left over from the sq4-floppy (sci1) to sq4-cd (sci1.1) conversion diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index c964ccd346..b762872357 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -87,7 +87,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort - Common::String gameId = g_sci->getGameID(); + Common::String gameId = g_sci->getGameId(); if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 0e054d5a76..82ff478da2 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -97,9 +97,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) { // For SCI1.1 Mac, we need to expand the screen to accommodate for // the icon bar. Of course, both KQ6 and QFG1 VGA differ in size. - if (!scumm_stricmp(g_sci->getGameID(), "kq6")) + if (g_sci->getGameId() == "kq6") initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320); - else if (!scumm_stricmp(g_sci->getGameID(), "qfg1")) + else if (g_sci->getGameId() == "qfg1") initGraphics(_displayWidth, _displayHeight + 20, _displayWidth > 320); else error("Unknown SCI1.1 Mac game"); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 00f832817b..265d5dc151 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -72,7 +72,7 @@ SciEngine *g_sci = 0; class GfxDriver; SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) - : Engine(syst), _gameDescription(desc) { + : Engine(syst), _gameDescription(desc), _gameId(_gameDescription->gameid) { assert(g_sci == 0); g_sci = this; @@ -128,7 +128,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) // Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD // is for the demo of Phantasmagoria, included in the disk - if (strcmp(getGameID(), "kq6")) + if (_gameId != "kq6") SearchMan.addSubDirectoryMatching(gameDataDir, "patches"); // resource patches } @@ -167,7 +167,7 @@ Common::Error SciEngine::run() { */ // Add the after market GM patches for the specified game, if they exist - _resMan->addNewGMPatch(getGameID()); + _resMan->addNewGMPatch(_gameId); _gameObj = _resMan->findGameObject(); SegManager *segMan = new SegManager(_resMan); @@ -179,10 +179,10 @@ Common::Error SciEngine::run() { // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit // it to platform windows. if (getPlatform() == Common::kPlatformWindows) { - if (!strcmp(getGameID(), "kq6")) + if (_gameId == "kq6") upscaledHires = GFX_SCREEN_UPSCALED_640x440; #ifdef ENABLE_SCI32 - if (!strcmp(getGameID(), "gk1")) + if (_gameId == "gk1") upscaledHires = GFX_SCREEN_UPSCALED_640x480; #endif } @@ -494,10 +494,6 @@ Console *SciEngine::getSciDebugger() { return _console; } -const char* SciEngine::getGameID() const { - return _gameDescription->gameid; -} - Common::Language SciEngine::getLanguage() const { return _gameDescription->language; } @@ -523,14 +519,12 @@ Common::String SciEngine::getSavegamePattern() const { } Common::String SciEngine::getFilePrefix() const { - const char* gameID = getGameID(); - if (!strcmp(gameID, "qfg2")) { + if (_gameId == "qfg2") { // Quest for Glory 2 wants to read files from Quest for Glory 1 (EGA/VGA) to import character data if (_gamestate->currentRoomNumber() == 805) return "qfg1"; // TODO: Include import-room for qfg1vga - } - if (!strcmp(gameID, "qfg3")) { + } else if (_gameId == "qfg3") { // Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data if (_gamestate->currentRoomNumber() == 54) return "qfg2"; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 5ea5edc17b..ee51147a4e 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -151,7 +151,7 @@ public: bool canSaveGameStateCurrently(); void syncSoundSettings(); - const char* getGameID() const; + const Common::String &getGameId() const { return _gameId; } int getResourceVersion() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; @@ -265,6 +265,7 @@ private: void initStackBaseWithSelector(Selector selector); const ADGameDescription *_gameDescription; + const Common::String _gameId; ResourceManager *_resMan; /**< The resource manager */ EngineState *_gamestate; Kernel *_kernel; -- cgit v1.2.3 From b474a72d1823d721f6f50de07bdebfdab3951632 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 17 Jun 2010 23:14:57 +0000 Subject: SCI: Remove incorrect gameid check svn-id: r49969 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 0a334924ab..596f8fb4b7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -991,7 +991,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; - if (g_sci->getGameId() == "freddypharkas" || g_sci->getGameId() == "freddypharkas-demo") { + if (g_sci->getGameId() == "freddypharkas") { // WORKAROUND // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would -- cgit v1.2.3 From 50c3a087e3fb75ac06ea6186909b49885de6226d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 23:20:39 +0000 Subject: Reduced header dependency svn-id: r49970 --- engines/sci/graphics/fontsjis.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/fontsjis.h b/engines/sci/graphics/fontsjis.h index 24c8423ddb..684e6cac5e 100644 --- a/engines/sci/graphics/fontsjis.h +++ b/engines/sci/graphics/fontsjis.h @@ -26,10 +26,12 @@ #ifndef SCI_GRAPHICS_FONTSJIS_H #define SCI_GRAPHICS_FONTSJIS_H -#include "graphics/sjis.h" - #include "sci/graphics/helpers.h" +namespace Graphics { + class FontSJIS; +} + namespace Sci { /** -- cgit v1.2.3 From f977faaf9f9d2289adfbc2ccf9338cb24266dce5 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Thu, 17 Jun 2010 23:44:01 +0000 Subject: SCI: Fix a few errors in PlayVMD comment. svn-id: r49971 --- engines/sci/engine/kgraphics.cpp | 49 ++++++++++++++++++++++------------------ 1 file changed, 27 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 596f8fb4b7..8f59f553a7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1289,7 +1289,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { break; case 1: { - // Set VMD parameters. Called with a maximum of 5 parameters: + // Set VMD parameters. Called with a maximum of 6 parameters: // // x, y, flags, gammaBoost, gammaFirst, gammaLast // @@ -1305,33 +1305,38 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // bit 8 stretch // gammaBoost boosts palette colors in the range gammaFirst to gammaLast, but - // only if bit 4 in flags is set. Percent value such that 100% = no amplification + // only if bit 4 in flags is set. Percent value such that 0% = no amplification // These three parameters are optional if bit 4 is clear. // Also note that the x, y parameters play subtle games if used with subfx 21. + // The subtleness has to do with creation of temporary planes and positioning relative to such planes. int flags = argv[3].offset; Common::String flagspec; - if (flags & 1) - flagspec += "doubled "; - if (flags & 2) - flagspec += "dropframes "; - if (flags & 4) - flagspec += "blacklines "; - if (flags & 8) - flagspec += "bit3 "; - if (flags & 16) - flagspec += "gammaboost "; - if (flags & 32) - flagspec += "holdblack "; - if (flags & 64) - flagspec += "holdlast "; - if (flags & 128) - flagspec += "bit7 "; - if (flags & 256) - flagspec += "stretch"; - - warning("VMDFlags: %s", flagspec.c_str()); + if (argc > 3) + { + if (flags & 1) + flagspec += "doubled "; + if (flags & 2) + flagspec += "dropframes "; + if (flags & 4) + flagspec += "blacklines "; + if (flags & 8) + flagspec += "bit3 "; + if (flags & 16) + flagspec += "gammaboost "; + if (flags & 32) + flagspec += "holdblack "; + if (flags & 64) + flagspec += "holdlast "; + if (flags & 128) + flagspec += "bit7 "; + if (flags & 256) + flagspec += "stretch"; + + warning("VMDFlags: %s", flagspec.c_str()); + } + warning("x, y: %d, %d", argv[1].offset, argv[2].offset); if (argc > 4 && flags & 16) -- cgit v1.2.3 From 9c1ec81d76def56d55df701df9d158532da1bf0f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 23:45:38 +0000 Subject: Strict mode: Turned several severe errors (almost all detection related) into errors, instead of warnings svn-id: r49972 --- engines/sci/engine/features.cpp | 6 +++--- engines/sci/engine/ksound.cpp | 4 ++-- engines/sci/engine/message.cpp | 6 +++--- engines/sci/resource.cpp | 14 +++++++------- engines/sci/sci.cpp | 2 +- engines/sci/sound/soundcmd.cpp | 4 ++-- 6 files changed, 18 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 4eb6bf2a56..e8f2fe326c 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -51,13 +51,13 @@ reg_t GameFeatures::getDetectionAddr(const Common::String &objName, Selector slc reg_t addr; if (objAddr.isNull()) { - warning("getDetectionAddr: %s object couldn't be found", objName.c_str()); + error("getDetectionAddr: %s object couldn't be found", objName.c_str()); return NULL_REG; } if (methodNum == -1) { if (lookupSelector(_segMan, objAddr, slc, NULL, &addr) != kSelectorMethod) { - warning("getDetectionAddr: target selector is not a method of object %s", objName.c_str()); + error("getDetectionAddr: target selector is not a method of object %s", objName.c_str()); return NULL_REG; } } else { @@ -491,7 +491,7 @@ MoveCountType GameFeatures::detectMoveCountType() { _moveCountType = kIncrementMoveCount; } else { if (!autoDetectMoveCountType()) { - warning("Move count autodetection failed"); + error("Move count autodetection failed"); _moveCountType = kIncrementMoveCount; // Most games do this, so best guess } } diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index d4af4ade5c..83407c140d 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -80,7 +80,7 @@ reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { // Init return make_reg(0, 1); default: - warning("kCdDoAudio: Unhandled case %d", argv[0].toUint16()); + error("kCdDoAudio: Unhandled case %d", argv[0].toUint16()); } return s->r_acc; @@ -223,7 +223,7 @@ reg_t kDoSync(EngineState *s, int argc, reg_t *argv) { g_sci->_audio->stopSoundSync(); break; default: - warning("DoSync: Unhandled subfunction %d", argv[0].toUint16()); + error("DoSync: Unhandled subfunction %d", argv[0].toUint16()); } return s->r_acc; diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index 523e8321db..a4bde9b582 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -161,7 +161,7 @@ bool MessageState::getRecord(CursorStack &stack, bool recurse, MessageRecord &re reader = new MessageReaderV4(res->data, res->size); break; default: - warning("Message: unsupported resource version %d", version); + error("Message: unsupported resource version %d", version); return false; } @@ -259,7 +259,7 @@ void MessageState::popCursorStack() { if (!_cursorStackStack.empty()) _cursorStack = _cursorStackStack.pop(); else - warning("Message: attempt to pop from empty stack"); + error("Message: attempt to pop from empty stack"); } int MessageState::hexDigitToInt(char h) { @@ -380,7 +380,7 @@ void MessageState::outputString(reg_t buf, const Common::String &str) { if ((unsigned)buffer_r.maxSize >= str.size() + 1) { _segMan->strcpy(buf, str.c_str()); } else { - warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); + error("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); // Set buffer to empty string if possible if (buffer_r.maxSize > 0) diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index bda854cfd0..46a8352567 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -714,7 +714,7 @@ void ResourceManager::init() { debugC(1, kDebugLevelResMan, "resMan: Detected Amiga graphic resources"); break; default: - warning("resMan: Couldn't determine view type"); + error("resMan: Couldn't determine view type"); } } @@ -1116,7 +1116,7 @@ void ResourceManager::processPatch(ResourceSource *source, ResourceType resource patchDataOffset = 8; break; default: - warning("Resource patch unsupported special case %X", patchDataOffset & 0x7F); + error("Resource patch unsupported special case %X", patchDataOffset & 0x7F); return; } } @@ -1636,7 +1636,7 @@ int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file break; #endif default: - warning("Resource %s: Compression method %d not supported", _id.toString().c_str(), compression); + error("Resource %s: Compression method %d not supported", _id.toString().c_str(), compression); return SCI_ERROR_UNKNOWN_COMPRESSION; } @@ -1752,7 +1752,7 @@ ViewType ResourceManager::detectViewType() { } } - warning("resMan: Couldn't find any views"); + error("resMan: Couldn't find any views"); return kViewUnknown; } @@ -1862,7 +1862,7 @@ void ResourceManager::detectSciVersion() { } } - warning("Failed to accurately determine SCI version"); + error("Failed to accurately determine SCI version"); // No parser, we assume SCI_VERSION_01. s_sciVersion = SCI_VERSION_01; return; @@ -1919,7 +1919,7 @@ bool ResourceManager::detectHires() { } } - warning("resMan: Couldn't detect hires"); + error("resMan: Couldn't detect hires"); return false; #else error("no sci32 support"); @@ -1944,7 +1944,7 @@ bool ResourceManager::hasOldScriptHeader() { Resource *res = findResource(ResourceId(kResourceTypeScript, 0), 0); if (!res) { - warning("resMan: Failed to find script.000"); + error("resMan: Failed to find script.000"); return false; } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 265d5dc151..b8c541fc03 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -365,7 +365,7 @@ bool SciEngine::initGame() { _gamestate->stack_top = stack->_entries + stack->_capacity; if (!script_instantiate(_resMan, _gamestate->_segMan, 0)) { - warning("initGame(): Could not instantiate script 0"); + error("initGame(): Could not instantiate script 0"); return false; } diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index fa215ac302..6b0a69f5b8 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -203,7 +203,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM _cmdUpdateCuesIndex = 17; break; default: - warning("Sound command parser: unknown sound version %d", _soundVersion); + error("Sound command parser: unknown sound version %d", _soundVersion); break; } } @@ -246,7 +246,7 @@ reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { (this->*(_soundCommands[command]->sndCmd))(obj, value); } else { - warning("Invalid sound command requested (%d), valid range is 0-%d", command, _soundCommands.size() - 1); + error("Invalid sound command requested (%d), valid range is 0-%d", command, _soundCommands.size() - 1); } return _acc; -- cgit v1.2.3 From db70d66e4ae872ebdeb2a88ef0870708a30c7667 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 23:50:28 +0000 Subject: Strict mode: Changed several warnings due to logic bugs into errors. If an error pops up from these ones, please add the game where it occurred and the steps to reproduce the error before turning it into a warning svn-id: r49973 --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/kmovement.cpp | 8 ++++---- engines/sci/engine/savegame.cpp | 6 +++--- engines/sci/engine/script.cpp | 4 ++-- engines/sci/engine/segment.cpp | 20 +++++++++++--------- engines/sci/engine/segment.h | 2 ++ engines/sci/engine/selector.cpp | 6 +++--- engines/sci/engine/state.cpp | 2 +- engines/sci/engine/vm.cpp | 18 +++++++++++------- engines/sci/graphics/ports.cpp | 2 +- engines/sci/sound/drivers/adlib.cpp | 4 ++-- engines/sci/sound/music.cpp | 2 +- 12 files changed, 42 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 6e02bbbb4e..71bedd5ad9 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -640,7 +640,7 @@ int Kernel::findRegType(reg_t reg) { return 0; // Invalid if (!mobj->isValidOffset(reg.offset)) - warning("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); + error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); switch (mobj->getType()) { case SEG_TYPE_SCRIPT: diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index c30a6e885a..b247275e8c 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -373,14 +373,14 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { s->r_acc = SIGNAL_REG; if (!s->_segMan->isHeapObject(avoider)) { - warning("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider)); + error("DoAvoider() where avoider %04x:%04x is not an object", PRINT_REG(avoider)); return NULL_REG; } client = readSelector(segMan, avoider, SELECTOR(client)); if (!s->_segMan->isHeapObject(client)) { - warning("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client)); + error("DoAvoider() where client %04x:%04x is not an object", PRINT_REG(client)); return NULL_REG; } @@ -389,7 +389,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { if (!s->_segMan->isHeapObject(mover)) { if (mover.segment) { - warning("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover)); + error("DoAvoider() where mover %04x:%04x is not an object", PRINT_REG(mover)); } return s->r_acc; } @@ -450,7 +450,7 @@ reg_t kDoAvoider(EngineState *s, int argc, reg_t *argv) { angle -= 360; } - warning("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider)); + error("DoAvoider failed for avoider %04x:%04x", PRINT_REG(avoider)); } else { int heading = readSelectorValue(segMan, client, SELECTOR(heading)); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 256a1aef03..eba5e67cb6 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -776,8 +776,8 @@ void SegManager::reconstructScripts(EngineState *s) { if (getSciVersion() < SCI_VERSION_1_1) { if (!obj->initBaseObject(this, addr, false)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); + error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + //scr->scriptObjRemove(addr); } } } @@ -809,7 +809,7 @@ void SegManager::reconstructClones() { const Object *baseObj = getObject(seeker.getSpeciesSelector()); seeker.cloneFromObject(baseObj); if (!baseObj) - warning("Clone entry without a base class: %d", j); + error("Clone entry without a base class: %d", j); } // end for } // end if } // end for diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 19e0b6f81a..8f3792552f 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -277,8 +277,8 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { obj->initSpecies(segMan, addr); if (!obj->initBaseObject(segMan, addr)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); + error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + //scr->scriptObjRemove(addr); } } break; diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index a6154e7512..c2f72ecdbd 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -221,7 +221,7 @@ void Script::load(ResourceManager *resMan) { _localsOffset = 0; if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { - warning("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); + error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); _localsCount = (_bufSize - _localsOffset) >> 1; } } else { @@ -268,12 +268,14 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { return obj; } +#if 0 void Script::scriptObjRemove(reg_t obj_pos) { if (getSciVersion() < SCI_VERSION_1_1) obj_pos.offset += 8; _objects.erase(obj_pos.toUint16()); } +#endif // This helper function is used by Script::relocateLocal and Object::relocate static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { @@ -288,7 +290,7 @@ static bool relocateBlock(Common::Array &block, int block_location, Segme return false; if (rel & 1) { - warning("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); + error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); return false; } block[idx].segment = segment; // Perform relocation @@ -372,7 +374,7 @@ uint16 Script::validateExportFunc(int pubfunct) { bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); if (_numExports <= pubfunct) { - warning("validateExportFunc(): pubfunct is invalid"); + error("validateExportFunc(): pubfunct is invalid"); return 0; } @@ -464,7 +466,7 @@ SegmentRef LocalVariables::dereference(reg_t pointer) { if (ret.maxSize > 0) { ret.reg = &_locals[pointer.offset / 2]; } else { - warning("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); ret.reg = 0; } return ret; @@ -551,7 +553,7 @@ void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback not for (uint i = 0; i < obj->getVarCount(); i++) (*note)(param, obj->getVariable(i)); } else { - warning("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); + error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); } } else { /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ @@ -642,7 +644,7 @@ void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { - warning("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); + error("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } @@ -662,7 +664,7 @@ void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { - warning("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); + error("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } const Node *node = &(_table[addr.offset]); @@ -736,7 +738,7 @@ int Object::propertyOffsetToId(SegManager *segMan, int propertyOffset) const { int selectors = getVarCount(); if (propertyOffset < 0 || (propertyOffset >> 1) >= selectors) { - warning("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])", + error("Applied propertyOffsetToId to invalid property offset %x (property #%d not in [0..%d])", propertyOffset, propertyOffset >> 1, selectors - 1); return -1; } @@ -814,7 +816,7 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { if (!isValidEntry(addr.offset)) { - warning("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); + error("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); return; } diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 253d94cc53..141576cb67 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -406,11 +406,13 @@ public: */ Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); +#if 0 /** * Removes a script object * @param obj_pos Location (segment, offset) of the object. */ void scriptObjRemove(reg_t obj_pos); +#endif /** * Processes a relocation block witin a script diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 15b008430b..08e2ba5e99 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -188,13 +188,13 @@ void writeSelector(SegManager *segMan, reg_t object, Selector selectorId, reg_t ObjVarRef address; if ((selectorId < 0) || (selectorId > (int)g_sci->getKernel()->getSelectorNamesSize())) { - warning("Attempt to write to invalid selector %d of" + error("Attempt to write to invalid selector %d of" " object at %04x:%04x.", selectorId, PRINT_REG(object)); return; } if (lookupSelector(segMan, object, selectorId, &address, NULL) != kSelectorVariable) - warning("Selector '%s' of object at %04x:%04x could not be" + error("Selector '%s' of object at %04x:%04x could not be" " written to", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); else *address.getPointer(segMan) = value; @@ -217,7 +217,7 @@ void invokeSelector(EngineState *s, reg_t object, int selectorId, g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); } if (slc_type == kSelectorVariable) { - warning("Attempting to invoke variable selector %s of object %04x:%04x", + error("Attempting to invoke variable selector %s of object %04x:%04x", g_sci->getKernel()->getSelectorName(selectorId).c_str(), PRINT_REG(object)); } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 80b9ba3bcb..129976ce99 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -207,7 +207,7 @@ Common::String SciEngine::getSciLanguageString(const char *str, kLanguage lang, // Copy double-byte character char c2 = *(++seeker); if (!c2) { - warning("SJIS character %02X is missing second byte", c); + error("SJIS character %02X is missing second byte", c); break; } fullWidth += c; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3fbfba1c92..c3f27b77b3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -128,7 +128,8 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static int validate_arithmetic(reg_t reg) { if (reg.segment) { - warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); + // The results of this are likely unpredictable... + error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); return 0; } @@ -137,7 +138,8 @@ static int validate_arithmetic(reg_t reg) { static int signed_validate_arithmetic(reg_t reg) { if (reg.segment) { - warning("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); + // The results of this are likely unpredictable... + error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); return 0; } @@ -159,8 +161,8 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in if (type == VAR_PARAM || type == VAR_TEMP) { int total_offset = r - stack_base; if (total_offset < 0 || total_offset >= VM_STACK_SIZE) { - warning("%s", txt.c_str()); - warning("[VM] Access would be outside even of the stack (%d); access denied", total_offset); + // Fatal, as the game is trying to do an OOB access + error("%s. [VM] Access would be outside even of the stack (%d); access denied", txt.c_str(), total_offset); return false; } else { debugC(2, kDebugLevelVM, "%s", txt.c_str()); @@ -298,7 +300,7 @@ static void _exec_varselectors(EngineState *s) { ExecStack &xs = s->_executionStack.back(); reg_t *var = xs.getVarPointer(s->_segMan); if (!var) { - warning("Invalid varselector exec stack entry"); + error("Invalid varselector exec stack entry"); } else { // varselector access? if (xs.argc) { // write? @@ -419,7 +421,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt reg_t oldReg = *varp.getPointer(s->_segMan); reg_t newReg = argp[1]; const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); - warning("send_selector(): argc = %d while modifying variable selector " + error("send_selector(): argc = %d while modifying variable selector " "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", argc, selector, selectorName, PRINT_REG(send_obj), objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); @@ -762,6 +764,7 @@ void run_vm(EngineState *s, bool restoring) { scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); if (!scr) { // No script? Implicit return via fake instruction buffer + // FIXME: Why does this happen? Are there leftover calls in the call stack? warning("Running on non-existant script in segment %x", s->xs->addr.pc.segment); code_buf = _fake_return_buffer; #ifndef DISABLE_VALIDATIONS @@ -779,6 +782,7 @@ void run_vm(EngineState *s, bool restoring) { #endif local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); if (!local_script) { + // FIXME: Why does this happen? Is the script not loaded yet at this point? warning("Could not find local script from segment %x", s->xs->local_segment); local_script = NULL; s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; @@ -1661,7 +1665,7 @@ void run_vm(EngineState *s, bool restoring) { //#ifndef DISABLE_VALIDATIONS if (s->xs != &(s->_executionStack.back())) { - warning("xs is stale (%p vs %p); last command was %02x", + error("xs is stale (%p vs %p); last command was %02x", (void *)s->xs, (void *)&(s->_executionStack.back()), opcode); } diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index b762872357..a3135e7177 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -216,7 +216,7 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor Common::Rect r; if (!pwnd) { - warning("Can't open window!"); + error("Can't open window!"); return 0; } diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index a743e4b5d9..4f93314b64 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -703,7 +703,7 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { - warning("ADLIB: Invalid patch %i requested", patch); + error("ADLIB: Invalid patch %i requested", patch); patch = 0; } @@ -749,7 +749,7 @@ void MidiDriver_AdLib::playSwitch(bool play) { bool MidiDriver_AdLib::loadResource(const byte *data, uint size) { if ((size != 1344) && (size != 2690) && (size != 5382)) { - warning("ADLIB: Unsupported patch format (%i bytes)", size); + error("ADLIB: Unsupported patch format (%i bytes)", size); return false; } diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index c5fc07bfd7..f6a4d5beb4 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -455,7 +455,7 @@ void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { if (pSnd->pMidiParser) pSnd->pMidiParser->sendToDriver(cmd); else - warning("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); + error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); } void SciMusic::printPlayList(Console *con) { -- cgit v1.2.3 From c9c9a21a0836edfc824e821702e886a656167692 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 23:52:17 +0000 Subject: Renamed error -> errorNum to avoid name clashes with error() svn-id: r49974 --- engines/sci/resource.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 46a8352567..e59f69513c 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1603,14 +1603,14 @@ int Resource::readResourceInfo(ResVersion volVersion, Common::SeekableReadStream } int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file) { - int error; + int errorNum; uint32 szPacked = 0; ResourceCompression compression = kCompUnknown; // fill resource info - error = readResourceInfo(volVersion, file, szPacked, compression); - if (error) - return error; + errorNum = readResourceInfo(volVersion, file, szPacked, compression); + if (errorNum) + return errorNum; // getting a decompressor Decompressor *dec = NULL; @@ -1642,12 +1642,12 @@ int Resource::decompress(ResVersion volVersion, Common::SeekableReadStream *file data = new byte[size]; _status = kResStatusAllocated; - error = data ? dec->unpack(file, data, szPacked, size) : SCI_ERROR_RESOURCE_TOO_BIG; - if (error) + errorNum = data ? dec->unpack(file, data, szPacked, size) : SCI_ERROR_RESOURCE_TOO_BIG; + if (errorNum) unalloc(); delete dec; - return error; + return errorNum; } ResourceCompression ResourceManager::getViewCompression() { -- cgit v1.2.3 From 6946167f34518d16036e37ce19683be1592a9424 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 17 Jun 2010 23:53:30 +0000 Subject: Strict mode: error out on unhandled subops, to note if they actually exist and where they're used svn-id: r49975 --- engines/sci/engine/kgraphics.cpp | 20 ++++++++++---------- engines/sci/graphics/paint16.cpp | 2 +- 2 files changed, 11 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 8f59f553a7..15567a08e3 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -173,7 +173,7 @@ static reg_t kSetCursorSci11(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxCursor->kernelSetView(argv[0].toUint16(), argv[1].toUint16(), argv[2].toUint16(), hotspot); break; default : - warning("kSetCursor: Unhandled case: %d arguments given", argc); + error("kSetCursor: Unhandled case: %d arguments given", argc); break; } return s->r_acc; @@ -186,7 +186,7 @@ reg_t kSetCursor(EngineState *s, int argc, reg_t *argv) { case SCI_VERSION_1_1: return kSetCursorSci11(s, argc, argv); default: - warning("Unknown SetCursor type"); + error("Unknown SetCursor type"); return NULL_REG; } } @@ -316,7 +316,7 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) { return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect); default: - warning("Unsupported kGraph() operation %04x", argv[0].toSint16()); + error("Unsupported kGraph() operation %04x", argv[0].toSint16()); } return s->r_acc; @@ -627,7 +627,7 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { break; } default: - warning("kPalette(%d), not implemented", argv[0].toUint16()); + error("kPalette(%d), not implemented", argv[0].toUint16()); } return s->r_acc; @@ -680,7 +680,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { break; } default: - warning("kPalVary(%d), not implemented (argc = %d)", operation, argc); + error("kPalVary(%d), not implemented (argc = %d)", operation, argc); } return NULL_REG; } @@ -702,7 +702,7 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { Common::String resourceName = s->_segMan->getString(argv[1]); s->r_acc = g_sci->_gfxPaint16->kernelPortraitLoad(resourceName); } else { - warning("kPortrait(loadResource) called with unsupported argc %d", argc); + error("kPortrait(loadResource) called with unsupported argc %d", argc); } break; } @@ -720,7 +720,7 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxPaint16->kernelPortraitShow(resourceName, position, resourceNum, noun, verb, cond, seq); return SIGNAL_REG; } else { - warning("kPortrait(show) called with unsupported argc %d", argc); + error("kPortrait(show) called with unsupported argc %d", argc); } break; } @@ -729,12 +729,12 @@ reg_t kPortrait(EngineState *s, int argc, reg_t *argv) { uint16 portraitId = argv[1].toUint16(); g_sci->_gfxPaint16->kernelPortraitUnload(portraitId); } else { - warning("kPortrait(unload) called with unsupported argc %d", argc); + error("kPortrait(unload) called with unsupported argc %d", argc); } break; } default: - warning("kPortrait(%d), not implemented (argc = %d)", operation, argc); + error("kPortrait(%d), not implemented (argc = %d)", operation, argc); } return s->r_acc; @@ -1160,7 +1160,7 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { initGraphics(screenWidth, screenHeight, screenWidth > 320, NULL); if (g_system->getScreenFormat().bytesPerPixel == 1) { - warning("This video requires >8bpp color to be displayed, but could not switch to RGB color mode."); + error("This video requires >8bpp color to be displayed, but could not switch to RGB color mode."); return NULL_REG; } diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index a52fd304e2..feda84e993 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -514,7 +514,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { bRedraw = 0; break; default: - warning("Unknown kDisplay argument %X", displayArg); + error("Unknown kDisplay argument %X", displayArg); break; } } -- cgit v1.2.3 From 39e77edbb71f04dc1436db152849aec1cd09e873 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 00:05:41 +0000 Subject: Process kAddAfter with 4 parameters (Torin's Passage) svn-id: r49976 --- engines/sci/engine/klists.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 050c8e515f..ba3ab61237 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -293,11 +293,14 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - if (argc != 3) { - warning("kAddAfter: Haven't got 3 arguments, aborting"); + if (argc != 3 && argc != 4) { + warning("kAddAfter: Haven't got 3 or 4 arguments, aborting"); return NULL_REG; } + if (argc == 4) // Torin's Passage + warning("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); + if (firstnode) { // We're really appending after reg_t oldnext = firstnode->succ; -- cgit v1.2.3 From 660ae052c88fc2e209dde87595799bff8b2bd09b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 00:36:20 +0000 Subject: Fixed a bug in detectHires(), so that it actually works svn-id: r49978 --- engines/sci/resource.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index e59f69513c..b71c6b9317 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1909,8 +1909,8 @@ bool ResourceManager::detectHires() { if (res) { if (READ_LE_UINT16(res->data) == 0x0e) { // SCI32 picture - uint16 width = READ_LE_UINT16(res->data + 10); - uint16 height = READ_LE_UINT16(res->data + 12); + uint16 width = READ_LE_UINT16(res->data + 14); + uint16 height = READ_LE_UINT16(res->data + 16); if ((width == 320) && ((height == 190) || (height == 200))) return false; if ((width >= 600) || (height >= 400)) -- cgit v1.2.3 From 880e07250ea86416c29fde16341429f347dc4d8a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 00:37:56 +0000 Subject: Added warning about unhandled kGraph subop 1 (GK1CD) svn-id: r49979 --- engines/sci/engine/kgraphics.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 15567a08e3..7f5ae82a99 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -245,6 +245,11 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) { } switch (argv[0].toSint16()) { + case 1: + // Happens in GK1CD, right when it starts + warning("Unsupported kGraph() operation %04x", argv[0].toSint16()); + return s->r_acc; + case K_GRAPH_GET_COLORS_NR: if (g_sci->getResMan()->isAmiga32color()) return make_reg(0, 32); -- cgit v1.2.3 From 949493d14160530a37c02f2440f41e5dac49e725 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 00:49:55 +0000 Subject: Fixed invalid memory read in GK1CD svn-id: r49980 --- engines/sci/engine/kgraphics.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 7f5ae82a99..348855964c 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -246,9 +246,10 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toSint16()) { case 1: - // Happens in GK1CD, right when it starts + // TODO: Happens in GK1CD, right when it starts warning("Unsupported kGraph() operation %04x", argv[0].toSint16()); - return s->r_acc; + // Returns an integer + return SIGNAL_REG; case K_GRAPH_GET_COLORS_NR: if (g_sci->getResMan()->isAmiga32color()) -- cgit v1.2.3 From d2a9fdae260b74b23be7b2f14f5723914ab5a559 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 00:59:10 +0000 Subject: Added stubs for kPalVary, subops 2 and 5 (XMAS '92, QFG4 demo) svn-id: r49981 --- engines/sci/engine/kgraphics.cpp | 10 ++++++++++ 1 file changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 348855964c..b20c98f16b 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -661,6 +661,11 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } + case 2: { // Unknown + // Called in QFG4 demo (1 parameter) + warning("kPalVary(2) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + break; + } case 3: { // DeInit if (argc == 1) { g_sci->_gfxPalette->stopPalVary(); @@ -674,6 +679,11 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(4) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } + case 5: { // Unknown + // Called in xmas 1992 demo (2 parameters) + warning("kPalVary(5) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + break; + } case 6: { // Pause bool pauseState; if (argc == 2) { -- cgit v1.2.3 From b453d139d49bb17fef58a329d1fba55b3fa8fbba Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Fri, 18 Jun 2010 01:09:40 +0000 Subject: SCI: (Temporary?) workaround for firmware bug in common USB-MIDI cables. svn-id: r49982 --- engines/sci/sound/drivers/midi.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index 2432a8fab0..b97564342c 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -271,6 +271,17 @@ void MidiPlayer_Midi::setPatch(int channel, int patch) { _driver->setPitchBendRange(channel, bendRange); _driver->send(0xc0 | channel, _patchMap[patch], 0); + + // Send a pointless command to work around a firmware bug in common + // USB-MIDI cables. If the first MIDI command in a USB packet is a + // Cx or Dx command, the second command in the packet is dropped + // somewhere. + // FIXME: consider putting a workaround in the MIDI backend drivers + // instead. + // Known to be affected: alsa, coremidi + // Known *not* to be affected: windows (only seems to send one MIDI + // command per USB packet even if the device allows larger packets). + _driver->send(0xb0 | channel, 0x0a, _channels[channel].pan); } void MidiPlayer_Midi::send(uint32 b) { -- cgit v1.2.3 From ac4659b92acd42690dae6b09a1a72bb0d30c1764 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 01:11:00 +0000 Subject: Added several unimplemented kDisplay subops, as well as a new sound command, found in the demo of Longbow svn-id: r49983 --- engines/sci/graphics/paint16.cpp | 15 +++++++++++++++ engines/sci/sound/soundcmd.cpp | 1 + 2 files changed, 16 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index feda84e993..ebb6cebb44 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -513,6 +513,21 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { case SCI_DISPLAY_DONTSHOWBITS: bRedraw = 0; break; + case 4: // Longbow demo + warning("Unknown kDisplay argument %X", displayArg); + break; + case 7: // Longbow demo + warning("Unknown kDisplay argument %X", displayArg); + break; + case 9: // Longbow demo + warning("Unknown kDisplay argument %X", displayArg); + break; + case 114: // Longbow demo + warning("Unknown kDisplay argument %X", displayArg); + break; + case 115: // Longbow demo + warning("Unknown kDisplay argument %X", displayArg); + break; default: error("Unknown kDisplay argument %X", displayArg); break; diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 6b0a69f5b8..6470b17e83 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -176,6 +176,7 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM SOUNDCOMMAND(cmdSendMidi); SOUNDCOMMAND(cmdReverb); SOUNDCOMMAND(cmdSetSoundHold); + SOUNDCOMMAND(cmdDummy); // Longbow demo _cmdUpdateCuesIndex = 11; break; case SCI_VERSION_1_LATE: -- cgit v1.2.3 From 30ea5f3ad2c45702f15e0941829fe002a4d22711 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 01:27:25 +0000 Subject: Added a workaround for the KQ1 demo (looks like a script bug) svn-id: r49984 --- engines/sci/engine/seg_manager.cpp | 14 +++++++++++--- 1 file changed, 11 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 58b496ccfc..5c49855367 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -528,15 +528,23 @@ Node *SegManager::lookupNode(reg_t addr) { if (addr.isNull()) return NULL; // Non-error null - if (getSegmentType(addr.segment) != SEG_TYPE_NODES) { - error("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + SegmentType type = getSegmentType(addr.segment); + + if (type != SEG_TYPE_NODES) { + if (g_sci->getGameId() == "kq1sci") { + // The demo of KQ1 is trying to use an invalid memory reference as a list node + warning("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); + return NULL; + } + + error("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); return NULL; } NodeTable *nt = (NodeTable *)_heap[addr.segment]; if (!nt->isValidEntry(addr.offset)) { - error("Attempt to use non-node %04x:%04x as list node", PRINT_REG(addr)); + error("Attempt to use invalid reference %04x:%04x as list node", PRINT_REG(addr)); return NULL; } -- cgit v1.2.3 From 7a22e491e39a5e15cf17168c2fde1368eea2d96b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 01:29:07 +0000 Subject: Marked the KQ1 demo workaround as a workaround svn-id: r49985 --- engines/sci/engine/seg_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 5c49855367..f19c03d5a8 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -532,7 +532,7 @@ Node *SegManager::lookupNode(reg_t addr) { if (type != SEG_TYPE_NODES) { if (g_sci->getGameId() == "kq1sci") { - // The demo of KQ1 is trying to use an invalid memory reference as a list node + // WORKAROUND: The demo of KQ1 is trying to use an invalid memory reference as a list node warning("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); return NULL; } -- cgit v1.2.3 From 2d61dd8608aafe0e524cec3e496f6d33f55cd922 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 01:38:08 +0000 Subject: Fixed invalid memory access in SQ6 svn-id: r49986 --- engines/sci/engine/ksound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 83407c140d..daff676a28 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -151,7 +151,7 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { volume = CLIP(volume, 0, AUDIO_VOLUME_MAX); debugC(2, kDebugLevelSound, "kDoAudio: set volume to %d", volume); mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); - break; + return make_reg(0, volume); } case kSciAudioLanguage: // In SCI1.1: tests for digital audio support -- cgit v1.2.3 From 8f761de15ffb4475bf529248b0bf7b635db53400 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 01:48:56 +0000 Subject: Added a new subop of kPalVary (PQ4) svn-id: r49987 --- engines/sci/engine/kgraphics.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index b20c98f16b..2ee30f1771 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -695,6 +695,11 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } break; } + case 8: { // Unknown + // Called in PQ4 (1 parameter) + warning("kPalVary(8) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + break; + } default: error("kPalVary(%d), not implemented (argc = %d)", operation, argc); } -- cgit v1.2.3 From 01cb1cf01164987770ac76b897f2dc7eb7cb300d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:03:28 +0000 Subject: Turned more warnings into errors, some cleanup svn-id: r49990 --- engines/sci/engine/klists.cpp | 34 +++------------------------------- 1 file changed, 3 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index ba3ab61237..86d82bd3d1 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -127,31 +127,6 @@ reg_t kDisposeList(EngineState *s, int argc, reg_t *argv) { // This function is not needed in ScummVM. The garbage collector // cleans up unused objects automatically -#if 0 - List *l = s->_segMan->lookupList(argv[0]); - - if (!l) { - // FIXME: This should be an error, but it's turned to a warning for now - warning("Attempt to dispose non-list at %04x:%04x", PRINT_REG(argv[0])); - return NULL_REG; - } - - checkListPointer(s->_segMan, argv[0]); - - if (!l->first.isNull()) { - reg_t n_addr = l->first; - - while (!n_addr.isNull()) { // Free all nodes - Node *n = s->_segMan->lookupNode(n_addr); - n_addr = n->succ; - - //s->_segMan->free_Node(n_addr); // TODO - } - } - - //s->_segMan->free_list(argv[0]); // TODO -#endif - return s->r_acc; } @@ -211,9 +186,8 @@ static void _k_add_to_front(EngineState *s, reg_t listbase, reg_t nodebase) { debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - // FIXME: This should be an error, but it's turned to a warning for now if (!new_n) - warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); checkListPointer(s->_segMan, listbase); new_n->succ = l->first; @@ -234,9 +208,8 @@ static void _k_add_to_end(EngineState *s, reg_t listbase, reg_t nodebase) { debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - // FIXME: This should be an error, but it's turned to a warning for now if (!new_n) - warning("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); checkListPointer(s->_segMan, listbase); new_n->succ = NULL_REG; @@ -287,9 +260,8 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { checkListPointer(s->_segMan, argv[0]); - // FIXME: This should be an error, but it's turned to a warning for now if (!newnode) { - warning("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2])); + error("New 'node' %04x:%04x is not a node", PRINT_REG(argv[2])); return NULL_REG; } -- cgit v1.2.3 From 31930b6d09a711a1c1ed708d2f23a6fc05ba2d63 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:09:12 +0000 Subject: Error out on unimplemented kDeviceInfo() calls svn-id: r49993 --- engines/sci/engine/kfile.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index ad188f503a..1c0ff31ec1 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -402,8 +402,7 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { break; default: - // TODO: Not all sub-commands are handled. E.g. KQ5CD calls sub-command 5 - warning("Unknown DeviceInfo() sub-command: %d", mode); + error("Unknown DeviceInfo() sub-command: %d", mode); break; } -- cgit v1.2.3 From 0eee4e79bf320a2b068a1460613e879751853b17 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:16:00 +0000 Subject: Changed an assert into a warning with a FIXME (happens in SQ1) svn-id: r49994 --- engines/sci/sound/midiparser_sci.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 1ea990332b..b2ccbd5c81 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -160,7 +160,12 @@ void MidiParser_SCI::sendToDriver(uint32 b) { return; // Channel remapping int16 realChannel = _channelRemap[midiChannel]; - assert(realChannel != -1); + if (realChannel == -1) { + // FIXME: Happens in SQ1VGA when the game starts + warning("Attempt to send to uninitialized channel %d", midiChannel); + return; + } + b = (b & 0xFFFFFFF0) | realChannel; _driver->send(b); } -- cgit v1.2.3 From 773f3bf1453b7e4cc55753e8ca882f5346ef5f83 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:23:30 +0000 Subject: Changed another warning into an error. Cleanup svn-id: r49995 --- engines/sci/engine/kscripts.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 7e33f17f5f..5f552080e3 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -66,6 +66,7 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { if (id.getType() == kResourceTypeInvalid) warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type); else + // Happens in CD games (e.g. LSL6CD) with the message resource warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); } break; @@ -163,7 +164,6 @@ reg_t kDisposeClone(EngineState *s, int argc, reg_t *argv) { } if (!victim_obj->isClone()) { - //warning("Attempt to dispose something other than a clone at %04x", offset); // SCI silently ignores this behaviour; some games actually depend on it return s->r_acc; } @@ -193,9 +193,10 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { // and this call is probably used to load them in memory, ignoring // the return value. If only one argument is passed, this call is done // only to load the script in memory. Thus, don't show any warning, - // as no return value is expected + // as no return value is expected. If an export is requested, then + // it will most certainly fail with OOB access. if (argc == 2) - warning("Script 0x%x does not have a dispatch table and export %d " + error("Script 0x%x does not have a dispatch table and export %d " "was requested from it", script, index); return NULL_REG; } -- cgit v1.2.3 From 492f748a4baaf72a5ca41a4b487966b3110ea580 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 18 Jun 2010 02:28:58 +0000 Subject: Add a comment on the unknown switch command argument. svn-id: r49999 --- engines/mohawk/riven_scripts.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index d574a455c6..a23fd26b96 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -61,7 +61,7 @@ uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) { uint16 command = script->readUint16BE(); uint32 commandSize = 2; if (command == 8) { - if (script->readUint16BE() != 2) + if (script->readUint16BE() != 2) // Arg count? warning ("if-then-else unknown value is not 2"); script->readUint16BE(); // variable to check against uint16 logicBlockCount = script->readUint16BE(); // number of logic blocks -- cgit v1.2.3 From 8bd71a6ab2ba9dcce676ee7935540ca651c0f5e6 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 18 Jun 2010 02:29:04 +0000 Subject: Cleanup; add a TODO. svn-id: r50000 --- engines/mohawk/riven.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index f1536b3204..fa7ffd7c45 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -50,15 +50,13 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _ignoreNextMouseUp = false; _extrasFile = NULL; - // Attempt to let game run from the CDs - // NOTE: assets2 contains higher quality audio than assets1 - const Common::FSNode gameDataDir(ConfMan.get("path")); + // TODO: Add support for CD swapping + const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.addSubDirectoryMatching(gameDataDir, "all"); SearchMan.addSubDirectoryMatching(gameDataDir, "data"); SearchMan.addSubDirectoryMatching(gameDataDir, "exe"); SearchMan.addSubDirectoryMatching(gameDataDir, "assets1"); - SearchMan.addSubDirectoryMatching(gameDataDir, "assets2"); g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426); g_atrusJournalRect = new Common::Rect(222, 402, 240, 426); -- cgit v1.2.3 From 98944b81719ba0c173e8c603a22e229994318447 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:29:20 +0000 Subject: Added information regarding a FIXME svn-id: r50002 --- engines/sci/sound/midiparser_sci.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index b2ccbd5c81..b6f4a6802b 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -463,6 +463,8 @@ byte *MidiParser_SCI::midiMixChannels() { } while (par1 != 0xF7); break; case kEndOfTrack: // end of channel + // FIXME: Why does this need to be fixed? There's no + // additional information available channel->time = -1; // FIXME break; default: // MIDI command -- cgit v1.2.3 From cccfed3ba352edc81ccc06f51bbd2f8f18b892ea Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 02:30:19 +0000 Subject: Cleanup svn-id: r50004 --- engines/saga/console.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/saga/console.cpp b/engines/saga/console.cpp index 2c201ac57d..228febfe9c 100644 --- a/engines/saga/console.cpp +++ b/engines/saga/console.cpp @@ -40,9 +40,6 @@ Console::Console(SagaEngine *vm) : GUI::Debugger() { DCmd_Register("continue", WRAP_METHOD(Console, Cmd_Exit)); - // CVAR_Register_I(&_soundEnabled, "sound", NULL, CVAR_CFG, 0, 1); - // CVAR_Register_I(&_musicEnabled, "music", NULL, CVAR_CFG, 0, 1); - // Actor commands DCmd_Register("actor_walk_to", WRAP_METHOD(Console, cmdActorWalkTo)); -- cgit v1.2.3 From 8f655615d774d7172e606ad2b99e02afe3ad5010 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 05:40:12 +0000 Subject: SCI: reverting #49978, it worked correctly. the new values contain the full height/width of the picture (may be much larger cause of scrollable areas) and we actually don't want that. the values before and now contain the height/width of the on-screen picture size - although this may contain 0, 0 for low-res games, but that's fine then svn-id: r50006 --- engines/sci/resource.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index b71c6b9317..e59f69513c 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1909,8 +1909,8 @@ bool ResourceManager::detectHires() { if (res) { if (READ_LE_UINT16(res->data) == 0x0e) { // SCI32 picture - uint16 width = READ_LE_UINT16(res->data + 14); - uint16 height = READ_LE_UINT16(res->data + 16); + uint16 width = READ_LE_UINT16(res->data + 10); + uint16 height = READ_LE_UINT16(res->data + 12); if ((width == 320) && ((height == 190) || (height == 200))) return false; if ((width >= 600) || (height >= 400)) -- cgit v1.2.3 From 08ff57cc9705bcbce30439a489988bcc059ce22b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 05:55:27 +0000 Subject: SCI: partially revert r49983 - all of those are not implemented in sierra sci or not even pseudo-valid in there. all of those seem to be script bugs svn-id: r50007 --- engines/sci/graphics/paint16.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index ebb6cebb44..a52fd304e2 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -513,23 +513,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { case SCI_DISPLAY_DONTSHOWBITS: bRedraw = 0; break; - case 4: // Longbow demo - warning("Unknown kDisplay argument %X", displayArg); - break; - case 7: // Longbow demo - warning("Unknown kDisplay argument %X", displayArg); - break; - case 9: // Longbow demo - warning("Unknown kDisplay argument %X", displayArg); - break; - case 114: // Longbow demo - warning("Unknown kDisplay argument %X", displayArg); - break; - case 115: // Longbow demo - warning("Unknown kDisplay argument %X", displayArg); - break; default: - error("Unknown kDisplay argument %X", displayArg); + warning("Unknown kDisplay argument %X", displayArg); break; } } -- cgit v1.2.3 From 8493edf0827f8c931b68ce35fe71718e3a3c176a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 06:47:16 +0000 Subject: SCI: changing error to warning inside detectHires() for gk1 to work again... svn-id: r50008 --- engines/sci/resource.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index e59f69513c..1639b954b9 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1919,7 +1919,8 @@ bool ResourceManager::detectHires() { } } - error("resMan: Couldn't detect hires"); + // This is fine for (some?) low-res sci32 games, because in those games the picture size is specified as 0, 0 + warning("resMan: Couldn't detect hires"); return false; #else error("no sci32 support"); -- cgit v1.2.3 From bb528d894cff2a6e249d6b7fe469fc86f048a894 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 09:37:06 +0000 Subject: SCI: Rewrap some overlong comments svn-id: r50012 --- engines/sci/engine/kernel.cpp | 5 +-- engines/sci/engine/kernel32.cpp | 36 ++++++++++-------- engines/sci/engine/kfile.cpp | 80 +++++++++++++++++++++++----------------- engines/sci/engine/kgraphics.cpp | 28 +++++++------- engines/sci/engine/kmenu.cpp | 2 +- engines/sci/engine/kmisc.cpp | 35 ++++++++++-------- engines/sci/engine/kmovement.cpp | 75 ++++++++++++++++++------------------- engines/sci/engine/kscripts.cpp | 4 +- engines/sci/engine/ksound.cpp | 9 +++-- engines/sci/engine/kstring.cpp | 25 ++++++++----- 10 files changed, 165 insertions(+), 134 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 71bedd5ad9..c9b547e6f8 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -436,9 +436,8 @@ uint Kernel::getKernelNamesSize() const { } const Common::String &Kernel::getKernelName(uint number) const { - // FIXME: The following check is a temporary workaround for - // an issue leading to crashes when using the debugger's backtrace - // command. + // FIXME: The following check is a temporary workaround for an issue + // leading to crashes when using the debugger's backtrace command. if (number >= _kernelNames.size()) return _invalid; return _kernelNames[number]; diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index fb90cfb147..b317719252 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -378,12 +378,14 @@ void Kernel::setKernelNamesSci2() { } void Kernel::setKernelNamesSci21(GameFeatures *features) { - // Some SCI games use a modified SCI2 kernel table instead of the SCI2.1/SCI3 kernel table. - // The GK2 demo does this as well as at least one version of KQ7. We detect which version - // to use based on where kDoSound is called from Sound::play(). + // Some SCI games use a modified SCI2 kernel table instead of the + // SCI2.1/SCI3 kernel table. The GK2 demo does this as well as at + // least one version of KQ7. We detect which version to use based on + // where kDoSound is called from Sound::play(). - // This is interesting because they all have the same interpreter version (2.100.002), yet - // they would not be compatible with other games of the same interpreter. + // This is interesting because they all have the same interpreter + // version (2.100.002), yet they would not be compatible with other + // games of the same interpreter. if (features->detectSci21KernelType() == SCI_VERSION_2) { _kernelNames = Common::StringArray(sci2_default_knames, kKernelEntriesGk2Demo); @@ -399,7 +401,8 @@ void Kernel::setKernelNamesSci21(GameFeatures *features) { // SCI2 Kernel Functions reg_t kIsHiRes(EngineState *s, int argc, reg_t *argv) { - // Returns 0 if the screen width or height is less than 640 or 400, respectively. + // Returns 0 if the screen width or height is less than 640 or 400, + // respectively. if (g_system->getWidth() < 640 || g_system->getHeight() < 400) return make_reg(0, 0); @@ -606,8 +609,9 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { if (string1->getSize() < index1 + count) string1->setSize(index1 + count); - // Note: We're accessing from c_str() here because the string's size ignores - // the trailing 0 and therefore triggers an assert when doing string2[i + index2]. + // Note: We're accessing from c_str() here because the + // string's size ignores the trailing 0 and therefore + // triggers an assert when doing string2[i + index2]. for (uint16 i = 0; i < count; i++) string1->setValue(i + index1, string2[i + index2]); } @@ -793,8 +797,9 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { uint16 itemX = readSelectorValue(s->_segMan, targetObject, SELECTOR(x)); uint16 itemY = readSelectorValue(s->_segMan, targetObject, SELECTOR(y)); - // If top and left are negative, we need to adjust coordinates by the item's x and y - // (e.g. happens in GK1, day 1, with detective Mosely's hotspot in his office) + // If top and left are negative, we need to adjust coordinates by + // the item's x and y (e.g. happens in GK1, day 1, with detective + // Mosely's hotspot in his office) if (nsRect.left < 0) nsRect.translate(itemX, 0); @@ -802,8 +807,8 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { if (nsRect.top < 0) nsRect.translate(0, itemY); - // HACK: nsLeft and nsTop can be invalid, so try and fix them here using x and y - // (e.g. with the inventory screen in GK1) + // HACK: nsLeft and nsTop can be invalid, so try and fix them here + // using x and y (e.g. with the inventory screen in GK1) if (nsRect.left == itemY && nsRect.top == itemX) { // Swap the values, as they're inversed (eh???) nsRect.left = itemX; @@ -821,8 +826,8 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv) { } reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { - // Tests if the cursor is on the passed object, after adjusting the coordinates - // of the object according to the object's plane + // Tests if the cursor is on the passed object, after adjusting the + // coordinates of the object according to the object's plane uint16 x = argv[0].toUint16(); uint16 y = argv[1].toUint16(); @@ -848,7 +853,8 @@ reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv) { planeTop = (planeTop * g_sci->_gfxScreen->getHeight()) / planeResY; planeLeft = (planeLeft * g_sci->_gfxScreen->getWidth()) / planeResX; - // Adjust the bounding rectangle of the object by the object's actual X, Y coordinates + // Adjust the bounding rectangle of the object by the object's + // actual X, Y coordinates itemY = ((itemY * g_sci->_gfxScreen->getHeight()) / planeResY); itemX = ((itemX * g_sci->_gfxScreen->getWidth()) / planeResX); itemY += planeTop; diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 1c0ff31ec1..f371e8a799 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -115,15 +115,17 @@ void file_open(EngineState *s, const char *filename, int mode) { if (mode == _K_FILE_MODE_OPEN_OR_FAIL) { // Try to open file, abort if not possible inFile = saveFileMan->openForLoading(wrappedName); - // If no matching savestate exists: fall back to reading from a regular file + // If no matching savestate exists: fall back to reading from a regular + // file if (!inFile) inFile = SearchMan.createReadStreamForMember(englishName); - // Special case for LSL3: It tries to create a new dummy file, LARRY3.DRV - // Apparently, if the file doesn't exist here, it should be created. The game - // scripts then go ahead and fill its contents with data. It seems to be a similar - // case as the dummy MEMORY.DRV file in LSL5, but LSL5 creates the file if it can't - // find it with a separate call to file_open() + // Special case for LSL3: It tries to create a new dummy file, + // LARRY3.DRV. Apparently, if the file doesn't exist here, it should be + // created. The game scripts then go ahead and fill its contents with + // data. It seems to be a similar case as the dummy MEMORY.DRV file in + // LSL5, but LSL5 creates the file if it can't find it with a separate + // call to file_open(). if (!inFile && englishName == "LARRY3.DRV") { outFile = saveFileMan->openForSaving(wrappedName); outFile->finalize(); @@ -144,10 +146,11 @@ void file_open(EngineState *s, const char *filename, int mode) { outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str()); - // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, closes it immediately and opens it again - // with this here - // Perhaps other games use this for read access as well - // I guess changing this whole code into using virtual files and writing them after close would be more appropriate + // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, + // closes it immediately and opens it again with this here. Perhaps + // other games use this for read access as well. I guess changing this + // whole code into using virtual files and writing them after close + // would be more appropriate. } else { error("file_open: unsupported mode %d (filename '%s')", mode, englishName.c_str()); } @@ -163,7 +166,8 @@ void file_open(EngineState *s, const char *filename, int mode) { while ((handle < s->_fileHandles.size()) && s->_fileHandles[handle].isOpen()) handle++; - if (handle == s->_fileHandles.size()) { // Hit size limit => Allocate more space + if (handle == s->_fileHandles.size()) { + // Hit size limit => Allocate more space s->_fileHandles.resize(s->_fileHandles.size() + 1); } @@ -274,7 +278,8 @@ void listSavegames(Common::Array &saves) { SavegameDesc desc; desc.id = strtol(filename.end() - 3, NULL, 10); desc.date = meta.savegame_date; - // We need to fix date in here, because we save DDMMYYYY instead of YYYYMMDD, so sorting wouldnt work + // We need to fix date in here, because we save DDMMYYYY instead of + // YYYYMMDD, so sorting wouldn't work desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); desc.time = meta.savegame_time; desc.version = meta.savegame_version; @@ -429,9 +434,9 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { Common::String path = s->_segMan->getString(argv[0]); debug(3, "kCheckFreeSpace(%s)", path.c_str()); - // We simply always pretend that there is enough space. - // The alternative would be to write a big test file, which is not nice - // on systems where doing so is very slow. + // We simply always pretend that there is enough space. The alternative + // would be to write a big test file, which is not nice on systems where + // doing so is very slow. return make_reg(0, 1); } @@ -641,7 +646,8 @@ reg_t DirSeeker::firstFile(const Common::String &mask, reg_t buffer, SegManager Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); _savefiles = saveFileMan->listSavefiles(wrappedMask); - // Reset the list iterator and write the first match to the output buffer, if any. + // Reset the list iterator and write the first match to the output buffer, + // if any. _iter = _savefiles.begin(); return nextFile(segMan); } @@ -671,7 +677,8 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { case K_FILEIO_OPEN : { Common::String name = s->_segMan->getString(argv[1]); - // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to just be checking if it exists. + // SCI32 can call K_FILEIO_OPEN with only two arguments. It seems to + // just be checking if it exists. int mode = (argc < 3) ? (int)_K_FILE_MODE_OPEN_OR_FAIL : argv[2].toUint16(); // SQ4 floppy prepends /\ to the filenames @@ -680,10 +687,10 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { name.deleteChar(0); } - // SQ4 floppy attempts to update the savegame index file sq4sg.dir - // when deleting saved games. We don't use an index file for saving - // or loading, so just stop the game from modifying the file here - // in order to avoid having it saved in the ScummVM save directory + // SQ4 floppy attempts to update the savegame index file sq4sg.dir when + // deleting saved games. We don't use an index file for saving or + // loading, so just stop the game from modifying the file here in order + // to avoid having it saved in the ScummVM save directory. if (name == "sq4sg.dir") { debugC(2, kDebugLevelFile, "Not opening unused file sq4sg.dir"); return SIGNAL_REG; @@ -744,11 +751,13 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { name.deleteChar(0); } - // Special case for SQ4 floppy: This game has hardcoded names for all of its - // savegames, and they are all named "sq4sg.xxx", where xxx is the slot. We just - // take the slot number here, and delete the appropriate save game + // Special case for SQ4 floppy: This game has hardcoded names for all of + // its savegames, and they are all named "sq4sg.xxx", where xxx is the + // slot. We just take the slot number here, and delete the appropriate + // save game. if (name.hasPrefix("sq4sg.")) { - // Special handling for SQ4... get the slot number and construct the save game name + // Special handling for SQ4... get the slot number and construct the + // save game name. int slotNum = atoi(name.c_str() + name.size() - 3); Common::Array saves; listSavegames(saves); @@ -848,14 +857,17 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { delete inFile; } - // Special case for non-English versions of LSL5: The English version of LSL5 calls - // kFileIO(), case K_FILEIO_OPEN for reading to check if memory.drv exists (which is - // where the game's password is stored). If it's not found, it calls kFileIO() again, - // case K_FILEIO_OPEN for writing and creates a new file. Non-English versions call - // kFileIO(), case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be found. - // We create a default memory.drv file with no password, so that the game can continue + // Special case for non-English versions of LSL5: The English version of + // LSL5 calls kFileIO(), case K_FILEIO_OPEN for reading to check if + // memory.drv exists (which is where the game's password is stored). If + // it's not found, it calls kFileIO() again, case K_FILEIO_OPEN for + // writing and creates a new file. Non-English versions call kFileIO(), + // case K_FILEIO_FILE_EXISTS instead, and fail if memory.drv can't be + // found. We create a default memory.drv file with no password, so that + // the game can continue. if (!exists && name == "memory.drv") { - // Create a new file, and write the bytes for the empty password string inside + // Create a new file, and write the bytes for the empty password + // string inside byte defaultContent[] = { 0xE9, 0xE9, 0xEB, 0xE1, 0x0D, 0x0A, 0x31, 0x30, 0x30, 0x30 }; Common::WriteStream *outFile = saveFileMan->openForSaving(wrappedName); for (int i = 0; i < 10; i++) @@ -872,8 +884,8 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { Common::String oldName = s->_segMan->getString(argv[1]); Common::String newName = s->_segMan->getString(argv[2]); - // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 returns -1 on fail. - // We just return -1 for all versions. + // SCI1.1 returns 0 on success and a DOS error code on fail. SCI32 + // returns -1 on fail. We just return -1 for all versions. if (g_engine->getSaveFileManager()->renameSavefile(oldName, newName)) return NULL_REG; else diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2ee30f1771..4614ee878a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1325,11 +1325,12 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { // bit 7 unknown // bit 8 stretch - // gammaBoost boosts palette colors in the range gammaFirst to gammaLast, but - // only if bit 4 in flags is set. Percent value such that 0% = no amplification - // These three parameters are optional if bit 4 is clear. - // Also note that the x, y parameters play subtle games if used with subfx 21. - // The subtleness has to do with creation of temporary planes and positioning relative to such planes. + // gammaBoost boosts palette colors in the range gammaFirst to + // gammaLast, but only if bit 4 in flags is set. Percent value such that + // 0% = no amplification These three parameters are optional if bit 4 is + // clear. Also note that the x, y parameters play subtle games if used + // with subfx 21. The subtleness has to do with creation of temporary + // planes and positioning relative to such planes. int flags = argv[3].offset; Common::String flagspec; @@ -1392,20 +1393,21 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { #endif reg_t kSetVideoMode(EngineState *s, int argc, reg_t *argv) { - // This call is used for KQ6's intro. It has one parameter, which is - // 1 when the intro begins, and 0 when it ends. It is suspected that - // this is actually a flag to enable video planar memory access, as - // the video decoder in KQ6 is specifically written for the planar - // memory model. Planar memory mode access was used for VGA "Mode X" - // (320x240 resolution, although the intro in KQ6 is 320x200). + // This call is used for KQ6's intro. It has one parameter, which is 1 when + // the intro begins, and 0 when it ends. It is suspected that this is + // actually a flag to enable video planar memory access, as the video + // decoder in KQ6 is specifically written for the planar memory model. + // Planar memory mode access was used for VGA "Mode X" (320x240 resolution, + // although the intro in KQ6 is 320x200). // Refer to http://en.wikipedia.org/wiki/Mode_X //warning("STUB: SetVideoMode %d", argv[0].toUint16()); return s->r_acc; } -// New calls for SCI11. Using those is only needed when using text-codes so that one is able to change -// font and/or color multiple times during kDisplay and kDrawControl +// New calls for SCI11. Using those is only needed when using text-codes so that +// one is able to change font and/or color multiple times during kDisplay and +// kDrawControl reg_t kTextFonts(EngineState *s, int argc, reg_t *argv) { g_sci->_gfxText16->kernelTextFonts(argc, argv); return s->r_acc; diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 13937c2f61..54543d783f 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -73,7 +73,7 @@ reg_t kDrawStatus(EngineState *s, int argc, reg_t *argv) { int16 colorBack = (argc > 2) ? argv[2].toSint16() : g_sci->getResMan()->isVGA() ? 255 : 15; if (!textReference.isNull()) { - // Sometimes this is called without giving text, if thats the case dont process it + // Sometimes this is called without giving text, if thats the case dont process it. text = s->_segMan->getString(textReference); g_sci->_gfxMenu->kernelDrawStatus(g_sci->strSplit(text.c_str(), NULL).c_str(), colorPen, colorBack); diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 525f9f5bf4..64da511ca8 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -55,20 +55,22 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { uint32 neededSleep = 30; - // WORKAROUND: - // LSL3 calculates a machinespeed variable during game startup (right after the filthy questions) - // This one would go through w/o throttling resulting in having to do 1000 pushups or something - // Another way of handling this would be delaying incrementing of "machineSpeed" selector + // WORKAROUND: LSL3 calculates a machinespeed variable during game startup + // (right after the filthy questions). This one would go through w/o + // throttling resulting in having to do 1000 pushups or something. Another + // way of handling this would be delaying incrementing of "machineSpeed" + // selector. if (g_sci->getGameId() == "lsl3" && s->currentRoomNumber() == 290) s->_throttleTrigger = true; - if (g_sci->getGameId() == "iceman" && s->currentRoomNumber() == 27) { + else if (g_sci->getGameId() == "iceman" && s->currentRoomNumber() == 27) { s->_throttleTrigger = true; neededSleep = 60; } if (s->_throttleTrigger) { - // Some games seem to get the duration of main loop initially and then switch of animations for the whole game - // based on that (qfg2, iceman). We are now running full speed initially to avoid that. + // Some games seem to get the duration of main loop initially and then + // switch of animations for the whole game based on that (qfg2, iceman). + // We are now running full speed initially to avoid that. // It seems like we dont need to do that anymore //if (s->_throttleCounter < 50) { // s->_throttleCounter++; @@ -332,11 +334,12 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { bool isWindows = g_sci->getPlatform() == Common::kPlatformWindows; if (argc == 0 && getSciVersion() < SCI_VERSION_2) { - // This is called in KQ5CD with no parameters, where it seems to do some graphics - // driver check. This kernel function didn't have subfunctions then. If 0 is - // returned, the game functions normally, otherwise all the animations show up - // like a slideshow (e.g. in the intro). So we return 0. However, the behavior - // changed for kPlatform with no parameters in SCI32. + // This is called in KQ5CD with no parameters, where it seems to do some + // graphics driver check. This kernel function didn't have subfunctions + // then. If 0 is returned, the game functions normally, otherwise all + // the animations show up like a slideshow (e.g. in the intro). So we + // return 0. However, the behavior changed for kPlatform with no + // parameters in SCI32. return NULL_REG; } @@ -375,10 +378,10 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { } reg_t kEmpty(EngineState *s, int argc, reg_t *argv) { - // Placeholder for empty kernel functions which are still called from the engine - // scripts (like the empty kSetSynonyms function in SCI1.1). This differs from - // dummy functions because it does nothing and never throws a warning when it's - // called + // Placeholder for empty kernel functions which are still called from the + // engine scripts (like the empty kSetSynonyms function in SCI1.1). This + // differs from dummy functions because it does nothing and never throws a + // warning when it is called. return s->r_acc; } diff --git a/engines/sci/engine/kmovement.cpp b/engines/sci/engine/kmovement.cpp index b247275e8c..ccef3d862a 100644 --- a/engines/sci/engine/kmovement.cpp +++ b/engines/sci/engine/kmovement.cpp @@ -33,42 +33,43 @@ namespace Sci { -/* -Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to (dx,dy), with gravity gy. -The gravity is assumed to be non-negative. - -If this was ordinary continuous physics, we would compute the desired (floating point!) -velocity vector (vx,vy) as follows, under the assumption that vx and vy are linearly correlated -by some constant factor c, i.e. vy = c * vx: - dx = t * vx - dy = t * vy + gy * t^2 / 2 -=> dy = c * dx + gy * (dx/vx)^2 / 2 -=> |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) ) -Here, the sign of vx must be chosen equal to the sign of dx, obviously. - -Clearly, this square root only makes sense in our context if the denominator is positive, -or equivalently, (dy - c * dx) must be positive. For simplicity and by symmetry -along the x-axis, we assume dx to be positive for all computations, and only adjust for -its sign in the end. Switching the sign of c appropriately, we set tmp := (dy + c * dx) -and compute c so that this term becomes positive. - -Remark #1: If the jump is straight up, i.e. dx == 0, then we should not assume the above -linear correlation vy = c * vx of the velocities (as vx will be 0, but vy shouldn't be, -unless we drop). - - -Remark #2: We are actually in a discrete setup. The motion is computed iteratively: each iteration, -we add vx and vy to the position, then add gy to vy. So the real formula is the following -(where t is ideally close to an int): - - dx = t * vx - dy = t * vy + gy * t*(t-1) / 2 - -But the solution resulting from that is a lot more complicated, so we use the above approximation instead. - -Still, what we compute in the end is of course not a real velocity anymore, but an integer approximation, -used in an iterative stepping algorithm -*/ +/** + * Compute "velocity" vector (xStep,yStep)=(vx,vy) for a jump from (0,0) to + * (dx,dy), with gravity constant gy. The gravity is assumed to be non-negative. + * + * If this was ordinary continuous physics, we would compute the desired + * (floating point!) velocity vector (vx,vy) as follows, under the assumption + * that vx and vy are linearly correlated by a constant c, i.e., vy = c * vx: + * dx = t * vx + * dy = t * vy + gy * t^2 / 2 + * => dy = c * dx + gy * (dx/vx)^2 / 2 + * => |vx| = sqrt( gy * dx^2 / (2 * (dy - c * dx)) ) + * Here, the sign of vx must be chosen equal to the sign of dx, obviously. + * + * This square root only makes sense in our context if the denominator is + * positive, or equivalently, (dy - c * dx) must be positive. For simplicity + * and by symmetry along the x-axis, we assume dx to be positive for all + * computations, and only adjust for its sign in the end. Switching the sign of + * c appropriately, we set tmp := (dy + c * dx) and compute c so that this term + * becomes positive. + * + * Remark #1: If the jump is straight up, i.e. dx == 0, then we should not + * assume the above linear correlation vy = c * vx of the velocities (as vx + * will be 0, but vy shouldn't be, unless we drop down). + * + * Remark #2: We are actually in a discrete setup. The motion is computed + * iteratively: each iteration, we add vx and vy to the position, then add gy + * to vy. So the real formula is the following (where t ideally is close to an int): + * + * dx = t * vx + * dy = t * vy + gy * t*(t-1) / 2 + * + * But the solution resulting from that is a lot more complicated, so we use + * the above approximation instead. + * + * Still, what we compute in the end is of course not a real velocity anymore, + * but an integer approximation, used in an iterative stepping algorithm. + */ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) { SegManager *segMan = s->_segMan; // Input data @@ -115,7 +116,7 @@ reg_t kSetJump(EngineState *s, int argc, reg_t *argv) { //tmp = dx * 3 / 2; // ALMOST the resulting value, except for obvious rounding issues // FIXME: Where is the 3 coming from? Maybe they hard/coded, by "accident", that usually gy=3 ? - // Then this choice of will make t equal to roughly sqrt(dx) + // Then this choice of scalar will make t equal to roughly sqrt(dx) } } // POST: c >= 1 diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 5f552080e3..de8710bd83 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -234,8 +234,8 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { if (argc != 2) { return s->r_acc; } else { - // This exists in the KQ5CD and GK1 interpreter. We know it is used when GK1 starts - // up, before the Sierra logo. + // This exists in the KQ5CD and GK1 interpreter. We know it is used + // when GK1 starts up, before the Sierra logo. warning("kDisposeScript called with 2 parameters, still untested"); return argv[1]; } diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index daff676a28..0d08cc2e06 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -110,8 +110,10 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { number = argv[1].toUint16(); } else if (argc == 6 || argc == 8) { module = argv[1].toUint16(); - number = ((argv[2].toUint16() & 0xff) << 24) | ((argv[3].toUint16() & 0xff) << 16) | - ((argv[4].toUint16() & 0xff) << 8) | (argv[5].toUint16() & 0xff); + number = ((argv[2].toUint16() & 0xff) << 24) | + ((argv[3].toUint16() & 0xff) << 16) | + ((argv[4].toUint16() & 0xff) << 8) | + (argv[5].toUint16() & 0xff); if (argc == 8) warning("kDoAudio: Play called with SQ6 extra parameters"); } else { @@ -180,7 +182,8 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); break; case 12: - // Seems to be audio sync, used in Pharkas, silenced warning cause of the spam it produces + // Seems to be audio sync, used in Pharkas. Silenced the warning due to + // the high level of spam it produces. //warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); break; case 13: diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 2681b612e9..5dd3910e3e 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -141,19 +141,22 @@ reg_t kReadNumber(EngineState *s, int argc, reg_t *argv) { int16 result = 0; if (*source == '$') { - // hexadecimal input + // Hexadecimal input result = (int16)strtol(source + 1, NULL, 16); } else { - // decimal input, we can not use strtol/atoi in here, because sierra used atoi BUT it was a non standard compliant - // atoi, that didnt do clipping. In SQ4 we get the door code in here and that's even larger than uint32! + // Decimal input. We can not use strtol/atoi in here, because while + // Sierra used atoi, it was a non standard compliant atoi, that didn't + // do clipping. In SQ4 we get the door code in here and that's even + // larger than uint32! if (*source == '-') { result = -1; source++; } while (*source) { if ((*source < '0') || (*source > '9')) { - // Sierras atoi stopped processing at anything different than number - // Sometimes the input has a trailing space, that's fine (example: lsl3) + // Sierra's atoi stopped processing at anything which is not + // a digit. Sometimes the input has a trailing space, that's + // fine (example: lsl3) if (*source != ' ') { // TODO: this happens in lsl5 right in the intro -> we get '1' '3' 0xCD 0xCD 0xCD 0xCD 0xCD // find out why this happens and fix it @@ -423,15 +426,16 @@ reg_t kGetFarText(EngineState *s, int argc, reg_t *argv) { seeker = (char *)textres->data; - // The second parameter (counter) determines the number of the string inside the text - // resource. + // The second parameter (counter) determines the number of the string + // inside the text resource. while (counter--) { while (*seeker++) ; } - // If the third argument is NULL, allocate memory for the destination. This occurs in - // SCI1 Mac games. The memory will later be freed by the game's scripts. + // If the third argument is NULL, allocate memory for the destination. This + // occurs in SCI1 Mac games. The memory will later be freed by the game's + // scripts. if (argv[2] == NULL_REG) s->_segMan->allocDynmem(strlen(seeker) + 1, "Mac FarText", &argv[2]); @@ -578,7 +582,8 @@ reg_t kStrSplit(EngineState *s, int argc, reg_t *argv) { // Make sure target buffer is large enough SegmentRef buf_r = s->_segMan->dereference(argv[0]); if (!buf_r.isValid() || buf_r.maxSize < (int)str.size() + 1) { - warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(argv[0]), str.size() + 1, str.c_str()); + warning("StrSplit: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", + PRINT_REG(argv[0]), str.size() + 1, str.c_str()); return NULL_REG; } s->_segMan->strcpy(argv[0], str.c_str()); -- cgit v1.2.3 From 5a95c2a652e5043673dff16383f3114247059d46 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 09:37:25 +0000 Subject: SCI: Doxygenify some comments svn-id: r50013 --- engines/sci/engine/kpathing.cpp | 238 +++++++++++++++++++++++----------------- 1 file changed, 140 insertions(+), 98 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 09cec29a79..8988aa5734 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -436,33 +436,41 @@ static void print_input(EngineState *s, reg_t poly_list, Common::Point start, Co } } +/** + * Computes the area of a triangle + * Parameters: (const Common::Point &) a, b, c: The points of the triangle + * Returns : (int) The area multiplied by two + */ static int area(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Computes the area of a triangle - // Parameters: (const Common::Point &) a, b, c: The points of the triangle - // Returns : (int) The area multiplied by two return (b.x - a.x) * (a.y - c.y) - (c.x - a.x) * (a.y - b.y); } +/** + * Determines whether or not a point is to the left of a directed line + * Parameters: (const Common::Point &) a, b: The directed line (a, b) + * (const Common::Point &) c: The query point + * Returns : (int) true if c is to the left of (a, b), false otherwise + */ static bool left(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not a point is to the left of a directed line - // Parameters: (const Common::Point &) a, b: The directed line (a, b) - // (const Common::Point &) c: The query point - // Returns : (int) true if c is to the left of (a, b), false otherwise return area(a, b, c) > 0; } +/** + * Determines whether or not three points are collinear + * Parameters: (const Common::Point &) a, b, c: The three points + * Returns : (int) true if a, b, and c are collinear, false otherwise + */ static bool collinear(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not three points are collinear - // Parameters: (const Common::Point &) a, b, c: The three points - // Returns : (int) true if a, b, and c are collinear, false otherwise return area(a, b, c) == 0; } +/** + * Determines whether or not a point lies on a line segment + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (const Common::Point &) c: The query point + * Returns : (int) true if c lies on (a, b), false otherwise + */ static bool between(const Common::Point &a, const Common::Point &b, const Common::Point &c) { - // Determines whether or not a point lies on a line segment - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (const Common::Point &) c: The query point - // Returns : (int) true if c lies on (a, b), false otherwise if (!collinear(a, b, c)) return false; @@ -473,25 +481,29 @@ static bool between(const Common::Point &a, const Common::Point &b, const Common return ((a.y <= c.y) && (c.y <= b.y)) || ((a.y >= c.y) && (c.y >= b.y)); } +/** + * Determines whether or not two line segments properly intersect + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (const Common::Point &) c, d: The line segment (c, d) + * Returns : (int) true if (a, b) properly intersects (c, d), false otherwise + */ static bool intersect_proper(const Common::Point &a, const Common::Point &b, const Common::Point &c, const Common::Point &d) { - // Determines whether or not two line segments properly intersect - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (const Common::Point &) c, d: The line segment (c, d) - // Returns : (int) true if (a, b) properly intersects (c, d), false otherwise int ab = (left(a, b, c) && left(b, a, d)) || (left(a, b, d) && left(b, a, c)); int cd = (left(c, d, a) && left(d, c, b)) || (left(c, d, b) && left(d, c, a)); return ab && cd; } +/** + * Polygon containment test + * Parameters: (const Common::Point &) p: The point + * (Polygon *) polygon: The polygon + * Returns : (int) CONT_INSIDE if p is strictly contained in polygon, + * CONT_ON_EDGE if p lies on an edge of polygon, + * CONT_OUTSIDE otherwise + * Number of ray crossing left and right + */ static int contained(const Common::Point &p, Polygon *polygon) { - // Polygon containment test - // Parameters: (const Common::Point &) p: The point - // (Polygon *) polygon: The polygon - // Returns : (int) CONT_INSIDE if p is strictly contained in polygon, - // CONT_ON_EDGE if p lies on an edge of polygon, - // CONT_OUTSIDE otherwise - // Number of ray crossing left and right int lcross = 0, rcross = 0; Vertex *vertex; @@ -549,10 +561,12 @@ static int contained(const Common::Point &p, Polygon *polygon) { return CONT_OUTSIDE; } +/** + * Computes polygon area + * Parameters: (Polygon *) polygon: The polygon + * Returns : (int) The area multiplied by two + */ static int polygon_area(Polygon *polygon) { - // Computes polygon area - // Parameters: (Polygon *) polygon: The polygon - // Returns : (int) The area multiplied by two Vertex *first = polygon->vertices.first(); Vertex *v; int size = 0; @@ -567,11 +581,13 @@ static int polygon_area(Polygon *polygon) { return size; } +/** + * Fixes the vertex order of a polygon if incorrect. Contained access + * polygons should have their vertices ordered clockwise, all other types + * anti-clockwise + * Parameters: (Polygon *) polygon: The polygon + */ static void fix_vertex_order(Polygon *polygon) { - // Fixes the vertex order of a polygon if incorrect. Contained access - // polygons should have their vertices ordered clockwise, all other types - // anti-clockwise - // Parameters: (Polygon *) polygon: The polygon int area = polygon_area(polygon); // When the polygon area is positive the vertices are ordered @@ -584,13 +600,15 @@ static void fix_vertex_order(Polygon *polygon) { } } +/** + * Determines whether or not a line from a point to a vertex intersects the + * interior of the polygon, locally at that vertex + * Parameters: (Common::Point) p: The point + * (Vertex *) vertex: The vertex + * Returns : (int) 1 if the line (p, vertex->v) intersects the interior of + * the polygon, locally at the vertex. 0 otherwise + */ static int inside(const Common::Point &p, Vertex *vertex) { - // Determines whether or not a line from a point to a vertex intersects the - // interior of the polygon, locally at that vertex - // Parameters: (Common::Point) p: The point - // (Vertex *) vertex: The vertex - // Returns : (int) 1 if the line (p, vertex->v) intersects the interior of - // the polygon, locally at the vertex. 0 otherwise // Check that it's not a single-vertex polygon if (VERTEX_HAS_EDGES(vertex)) { const Common::Point &prev = CLIST_PREV(vertex)->v; @@ -655,28 +673,34 @@ static VertexList *visible_vertices(PathfindingState *s, Vertex *vertex_cur) { return visVerts; } +/** + * Determines if a point lies on the screen border + * Parameters: (const Common::Point &) p: The point + * Returns : (int) true if p lies on the screen border, false otherwise + */ bool PathfindingState::pointOnScreenBorder(const Common::Point &p) { - // Determines if a point lies on the screen border - // Parameters: (const Common::Point &) p: The point - // Returns : (int) true if p lies on the screen border, false otherwise return (p.x == 0) || (p.x == _width - 1) || (p.y == 0) || (p.y == _height - 1); } +/** + * Determines if an edge lies on the screen border + * Parameters: (const Common::Point &) p, q: The edge (p, q) + * Returns : (int) true if (p, q) lies on the screen border, false otherwise + */ bool PathfindingState::edgeOnScreenBorder(const Common::Point &p, const Common::Point &q) { - // Determines if an edge lies on the screen border - // Parameters: (const Common::Point &) p, q: The edge (p, q) - // Returns : (int) true if (p, q) lies on the screen border, false otherwise return ((p.x == 0 && q.x == 0) || (p.y == 0 && q.y == 0) || ((p.x == _width - 1) && (q.x == _width - 1)) || ((p.y == _height - 1) && (q.y == _height - 1))); } +/** + * Searches for a nearby point that is not contained in a polygon + * Parameters: (FloatPoint) f: The pointf to search nearby + * (Polygon *) polygon: The polygon + * Returns : (int) PF_OK on success, PF_FATAL otherwise + * (Common::Point) *ret: The non-contained point on success + */ static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) { - // Searches for a nearby point that is not contained in a polygon - // Parameters: (FloatPoint) f: The pointf to search nearby - // (Polygon *) polygon: The polygon - // Returns : (int) PF_OK on success, PF_FATAL otherwise - // (Common::Point) *ret: The non-contained point on success Common::Point p; // Try nearest point first @@ -706,12 +730,14 @@ static int find_free_point(FloatPoint f, Polygon *polygon, Common::Point *ret) { return PF_OK; } +/** + * Computes the near point of a point contained in a polygon + * Parameters: (const Common::Point &) p: The point + * (Polygon *) polygon: The polygon + * Returns : (int) PF_OK on success, PF_FATAL otherwise + * (Common::Point) *ret: The near point of p in polygon on success + */ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Common::Point *ret) { - // Computes the near point of a point contained in a polygon - // Parameters: (const Common::Point &) p: The point - // (Polygon *) polygon: The polygon - // Returns : (int) PF_OK on success, PF_FATAL otherwise - // (Common::Point) *ret: The near point of p in polygon on success Vertex *vertex; FloatPoint near_p; uint32 dist = HUGE_DISTANCE; @@ -751,13 +777,15 @@ int PathfindingState::findNearPoint(const Common::Point &p, Polygon *polygon, Co return find_free_point(near_p, polygon, ret); } +/** + * Computes the intersection point of a line segment and an edge (not + * including the vertices themselves) + * Parameters: (const Common::Point &) a, b: The line segment (a, b) + * (Vertex *) vertex: The first vertex of the edge + * Returns : (int) FP_OK on success, PF_ERROR otherwise + * (FloatPoint) *ret: The intersection point + */ static int intersection(const Common::Point &a, const Common::Point &b, Vertex *vertex, FloatPoint *ret) { - // Computes the intersection point of a line segment and an edge (not - // including the vertices themselves) - // Parameters: (const Common::Point &) a, b: The line segment (a, b) - // (Vertex *) vertex: The first vertex of the edge - // Returns : (int) FP_OK on success, PF_ERROR otherwise - // (FloatPoint) *ret: The intersection point // Parameters of parametric equations float s, t; // Numerator and denominator of equations @@ -790,16 +818,18 @@ static int intersection(const Common::Point &a, const Common::Point &b, Vertex * return PF_ERROR; } +/** + * Computes the nearest intersection point of a line segment and the polygon + * set. Intersection points that are reached from the inside of a polygon + * are ignored as are improper intersections which do not obstruct + * visibility + * Parameters: (PathfindingState *) s: The pathfinding state + * (const Common::Point &) p, q: The line segment (p, q) + * Returns : (int) PF_OK on success, PF_ERROR when no intersections were + * found, PF_FATAL otherwise + * (Common::Point) *ret: On success, the closest intersection point + */ static int nearest_intersection(PathfindingState *s, const Common::Point &p, const Common::Point &q, Common::Point *ret) { - // Computes the nearest intersection point of a line segment and the polygon - // set. Intersection points that are reached from the inside of a polygon - // are ignored as are improper intersections which do not obstruct - // visibility - // Parameters: (PathfindingState *) s: The pathfinding state - // (const Common::Point &) p, q: The line segment (p, q) - // Returns : (int) PF_OK on success, PF_ERROR when no intersections were - // found, PF_FATAL otherwise - // (Common::Point) *ret: On success, the closest intersection point Polygon *polygon = 0; FloatPoint isec; Polygon *ipolygon = 0; @@ -981,14 +1011,16 @@ static Common::Point *fixup_end_point(PathfindingState *s, const Common::Point & return new_end; } +/** + * Merges a point into the polygon set. A new vertex is allocated for this + * point, unless a matching vertex already exists. If the point is on an + * already existing edge that edge is split up into two edges connected by + * the new vertex + * Parameters: (PathfindingState *) s: The pathfinding state + * (const Common::Point &) v: The point to merge + * Returns : (Vertex *) The vertex corresponding to v + */ static Vertex *merge_point(PathfindingState *s, const Common::Point &v) { - // Merges a point into the polygon set. A new vertex is allocated for this - // point, unless a matching vertex already exists. If the point is on an - // already existing edge that edge is split up into two edges connected by - // the new vertex - // Parameters: (PathfindingState *) s: The pathfinding state - // (const Common::Point &) v: The point to merge - // Returns : (Vertex *) The vertex corresponding to v Vertex *vertex; Vertex *v_new; Polygon *polygon; @@ -1029,11 +1061,13 @@ static Vertex *merge_point(PathfindingState *s, const Common::Point &v) { return v_new; } +/** + * Converts an SCI polygon into a Polygon + * Parameters: (EngineState *) s: The game state + * (reg_t) polygon: The SCI polygon to convert + * Returns : (Polygon *) The converted polygon, or NULL on error + */ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { - // Converts an SCI polygon into a Polygon - // Parameters: (EngineState *) s: The game state - // (reg_t) polygon: The SCI polygon to convert - // Returns : (Polygon *) The converted polygon, or NULL on error SegManager *segMan = s->_segMan; int i; reg_t points = readSelector(segMan, polygon, SELECTOR(points)); @@ -1074,11 +1108,13 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { return poly; } +/** + * Changes the polygon list for optimization level 0 (used for keyboard + * support). Totally accessible polygons are removed and near-point + * accessible polygons are changed into totally accessible polygons. + * Parameters: (PathfindingState *) s: The pathfinding state + */ static void change_polygons_opt_0(PathfindingState *s) { - // Changes the polygon list for optimization level 0 (used for keyboard - // support). Totally accessible polygons are removed and near-point - // accessible polygons are changed into totally accessible polygons. - // Parameters: (PathfindingState *) s: The pathfinding state PolygonList::iterator it = s->polygons.begin(); while (it != s->polygons.end()) { @@ -1096,15 +1132,17 @@ static void change_polygons_opt_0(PathfindingState *s) { } } +/** + * Converts the SCI input data for pathfinding + * Parameters: (EngineState *) s: The game state + * (reg_t) poly_list: Polygon list + * (Common::Point) start: The start point + * (Common::Point) end: The end point + * (int) opt: Optimization level (0, 1 or 2) + * Returns : (PathfindingState *) On success a newly allocated pathfinding state, + * NULL otherwise + */ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Common::Point start, Common::Point end, int width, int height, int opt) { - // Converts the SCI input data for pathfinding - // Parameters: (EngineState *) s: The game state - // (reg_t) poly_list: Polygon list - // (Common::Point) start: The start point - // (Common::Point) end: The end point - // (int) opt: Optimization level (0, 1 or 2) - // Returns : (PathfindingState *) On success a newly allocated pathfinding state, - // NULL otherwise SegManager *segMan = s->_segMan; Polygon *polygon; int err; @@ -1297,11 +1335,13 @@ static reg_t allocateOutputArray(SegManager *segMan, int size) { return addr; } +/** + * Stores the final path in newly allocated dynmem + * Parameters: (PathfindingState *) p: The pathfinding state + * (EngineState *) s: The game state + * Returns : (reg_t) Pointer to dynmem containing path + */ static reg_t output_path(PathfindingState *p, EngineState *s) { - // Stores the final path in newly allocated dynmem - // Parameters: (PathfindingState *) p: The pathfinding state - // (EngineState *) s: The game state - // Returns : (reg_t) Pointer to dynmem containing path int path_len = 0; reg_t output; Vertex *vertex = p->vertex_end; @@ -1694,8 +1734,10 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) { } } -// This is a quite rare kernel function. An example of when it's called -// is in QFG1VGA, after killing any monster. +/** + * This is a quite rare kernel function. An example of when it's called + * is in QFG1VGA, after killing any monster. + */ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { // 3 parameters: raw polygon data, polygon list, list size reg_t polygonData = argv[0]; -- cgit v1.2.3 From 8ade66ba132a9ca929838722aa67857666871c6f Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Fri, 18 Jun 2010 10:49:26 +0000 Subject: SCI: Unbreak diskdump console command, maybe others svn-id: r50014 --- engines/sci/resource.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 1639b954b9..6e739a5247 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -114,7 +114,7 @@ static const char *resourceTypeNames[] = { "memory", "vocab", "font", "cursor", "patch", "bitmap", "palette", "cdaudio", "audio", "sync", "message", "map", "heap", - "audio36", "sync36", "", "", "robot" + "audio36", "sync36", "", "", "robot", "vmd" }; static const char *resourceTypeSuffixes[] = { @@ -122,7 +122,7 @@ static const char *resourceTypeSuffixes[] = { " ", "voc", "fon", "cur", "pat", "bit", "pal", "cda", "aud", "syn", "msg", "map", "hep", "aud", "syn", - "trn", " ", "rbt" + "trn", " ", "rbt", "vmd" }; const char *getResourceTypeName(ResourceType restype) { -- cgit v1.2.3 From 543610d4d4a7458ac99e0126e03e96ab581adf68 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 12:15:33 +0000 Subject: Don't throw a warning when we can't find hires content svn-id: r50015 --- engines/sci/resource.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 6e739a5247..075d104f3e 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1911,16 +1911,18 @@ bool ResourceManager::detectHires() { // SCI32 picture uint16 width = READ_LE_UINT16(res->data + 10); uint16 height = READ_LE_UINT16(res->data + 12); + // Surely lowres (e.g. QFG4CD) if ((width == 320) && ((height == 190) || (height == 200))) return false; + // Surely hires if ((width >= 600) || (height >= 400)) return true; } } } - // This is fine for (some?) low-res sci32 games, because in those games the picture size is specified as 0, 0 - warning("resMan: Couldn't detect hires"); + // We haven't been able to find hires content + return false; #else error("no sci32 support"); -- cgit v1.2.3 From 919c348c5a739ed4cd85f7c38cb7cf10f86f3737 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 13:02:48 +0000 Subject: SCI: pseudo-implemented 0x72 and 0x73 for kDisplay used by longbow-demo, although sierra sci doesn't support them at all svn-id: r50016 --- engines/sci/graphics/paint16.cpp | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index a52fd304e2..f9ee3c3ae3 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -448,6 +448,8 @@ void GfxPaint16::kernelGraphRedrawBox(Common::Rect rect) { #define SCI_DISPLAY_WIDTH 106 #define SCI_DISPLAY_SAVEUNDER 107 #define SCI_DISPLAY_RESTOREUNDER 108 +#define SCI_DISPLAY_DUMMY1 114 // used in longbow-demo, not supported in sierra sci - no parameters +#define SCI_DISPLAY_DUMMY2 115 // used in longbow-demo, not supported in sierra sci - has 1 parameter #define SCI_DISPLAY_DONTSHOWBITS 121 reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { @@ -513,8 +515,22 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { case SCI_DISPLAY_DONTSHOWBITS: bRedraw = 0; break; + + // 2 Dummy functions, longbow-demo is using those several times but sierra sci doesn't support them at all + case SCI_DISPLAY_DUMMY1: + case SCI_DISPLAY_DUMMY2: + if (!((g_sci->getGameId() == "longbow") && (g_sci->isDemo()))) + error("Unknown kDisplay argument %X", displayArg); + if (displayArg == SCI_DISPLAY_DUMMY2) { + if (argc) { + argc--; argv++; + } else { + error("No parameter left for kDisplay(0x73)"); + } + } + break; default: - warning("Unknown kDisplay argument %X", displayArg); + error("Unknown kDisplay argument %X", displayArg); break; } } -- cgit v1.2.3 From 661a170c86ee1fc7db05e16b19455bddeb6f66e8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 13:05:08 +0000 Subject: SCI: change error() inside adlib driver ::setPatch() to warning() again, fixing pq2 svn-id: r50017 --- engines/sci/sound/drivers/adlib.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index 4f93314b64..44e52cf768 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -703,7 +703,8 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { - error("ADLIB: Invalid patch %i requested", patch); + // This happens a lot at least in pq2, seems to me as if it's meant for mt32 actually + warning("ADLIB: Invalid patch %i requested", patch); patch = 0; } -- cgit v1.2.3 From 562f8a9463a23e7dfac01d81b6e11c13b4c66600 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 13:36:29 +0000 Subject: SCI: implementing fading for sci1 only for used channels of the object, fixes lsl1 music issues when going right at the start svn-id: r50018 --- engines/sci/sound/midiparser_sci.cpp | 8 ++++---- engines/sci/sound/midiparser_sci.h | 3 +++ 2 files changed, 7 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index b6f4a6802b..931919b2b5 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -646,10 +646,10 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: - // sending volume change to all active channels - for (int i = 0; i < _track->channelCount; i++) - if (_track->channels[i].number <= 0xF) - _driver->send(0xB0 + _track->channels[i].number, 7, _volume); + // sending volume change to all used channels + for (int i = 0; i < 15; i++) + if (_channelUsed[i]) + sendToDriver(0xB0 + i, 7, _volume); break; default: diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 89d1e63d8c..abedafdde0 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -77,6 +77,9 @@ public: void tryToOwnChannels(); void sendToDriver(uint32 b); + void sendToDriver(byte status, byte firstOp, byte secondOp) { + sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); + } protected: void parseNextEvent(EventInfo &info); -- cgit v1.2.3 From b152f6d68ff00290b475df35df180e95f84af6d3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 14:36:22 +0000 Subject: Added an explanation about the invalid instruments used when using the Adlib driver in PQ2 svn-id: r50019 --- engines/sci/sound/drivers/adlib.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index 44e52cf768..2e56b023e0 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -703,8 +703,15 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { - // This happens a lot at least in pq2, seems to me as if it's meant for mt32 actually - warning("ADLIB: Invalid patch %i requested", patch); + // This happens a lot at least in PQ2. This game has a small patch.003 (1344 bytes), + // containing 48 instruments. However it has several songs which use instruments + // not specified in that patch (namely, songs 1, 3, 5, 9, 15, 16, 17, 23, 25, 27, + // 29, 32, 36, 38, 44, 45, 46 all use instruments not specified in patch.003). + // These were probably written for MT32. These warnings in PQ2 can probably go away + // if a bigger patch.003 file is used (one that contains all the instruments used + // by the songs, i.e. 5382 bytes) + warning("ADLIB: Invalid patch %i requested (patch.003 contains %d instruments)", + patch, _patches.size()); patch = 0; } -- cgit v1.2.3 From 874eeb2370164d0a7f8cd588f817beb64d98575d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 14:48:39 +0000 Subject: Added hints inside validate_arithmetic(), together with some code useful for debugging. Some cleanup svn-id: r50020 --- engines/sci/engine/vm.cpp | 30 +++++++++++++++++++++--------- engines/sci/sound/drivers/adlib.cpp | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c3f27b77b3..706d2ceb22 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -128,8 +128,10 @@ static StackPtr validate_stack_addr(EngineState *s, StackPtr sp) { static int validate_arithmetic(reg_t reg) { if (reg.segment) { - // The results of this are likely unpredictable... - error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); + // The results of this are likely unpredictable... It most likely means that a kernel function is returning something wrong. + // If such an error occurs, we usually need to find the last kernel function called and check its return value. Check + // callKernelFunc() below + error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]. Address: %04x:%04x", reg.segment, PRINT_REG(reg)); return 0; } @@ -137,13 +139,7 @@ static int validate_arithmetic(reg_t reg) { } static int signed_validate_arithmetic(reg_t reg) { - if (reg.segment) { - // The results of this are likely unpredictable... - error("[VM] Attempt to read arithmetic value from non-zero segment [%04x]", reg.segment); - return 0; - } - - return (int16)reg.offset; + return (int16)validate_arithmetic(reg); } static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index, int line) { @@ -617,6 +613,22 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { } else { // Call kernel function s->r_acc = kernelFunc.func(s, argc, argv); + +#if 0 + // Used for debugging + Common::String debugMsg = kernelFunc.origName + + Common::String::printf("[0x%x]", kernelFuncNum) + + Common::String::printf(", %d params: ", argc) + + " ("; + + for (int i = 0; i < argc; i++) { + debugMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + debugMsg += (i == argc - 1 ? ")" : ", "); + } + + debugMsg += ", result: " + Common::String::printf("%04x:%04x", PRINT_REG(s->r_acc)); + debug("%s", debugMsg.c_str()); +#endif } // Remove callk stack frame again diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index 2e56b023e0..d0ca00fe0f 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -705,7 +705,7 @@ void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { // This happens a lot at least in PQ2. This game has a small patch.003 (1344 bytes), // containing 48 instruments. However it has several songs which use instruments - // not specified in that patch (namely, songs 1, 3, 5, 9, 15, 16, 17, 23, 25, 27, + // not specified in that patch (namely, songs 1, 3, 5, 9, 15, 16, 17, 23, 25, 27, // 29, 32, 36, 38, 44, 45, 46 all use instruments not specified in patch.003). // These were probably written for MT32. These warnings in PQ2 can probably go away // if a bigger patch.003 file is used (one that contains all the instruments used -- cgit v1.2.3 From 5d378574a438f7b7f60fd01b88dd58e05c0bcd9b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 15:18:14 +0000 Subject: Fixed show_instruments to ignore instruments in Sierra's special MIDI channel 15, and updated the comment regarding PQ2 accordingly (it only has 2 incorrect instruments) svn-id: r50021 --- engines/sci/console.cpp | 24 +++++++++++++----------- engines/sci/sound/drivers/adlib.cpp | 11 ++++------- 2 files changed, 17 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b46e03830d..1fdcd579c0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -919,19 +919,21 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { prevEvent = curEvent; command = curEvent >> 4; + byte channel; + switch (command) { case 0xC: // program change - { - //byte channel = curEvent & 0x0F; - byte instrument = *channelData++; - if (!firstOneShown) - firstOneShown = true; - else - DebugPrintf(","); - - DebugPrintf(" %d", instrument); - instruments[instrument]++; - instrumentsSongs[instrument][itr->getNumber()] = true; + channel = curEvent & 0x0F; + if (channel != 15) { // SCI special + byte instrument = *channelData++; + if (!firstOneShown) + firstOneShown = true; + else + DebugPrintf(","); + + DebugPrintf(" %d", instrument); + instruments[instrument]++; + instrumentsSongs[instrument][itr->getNumber()] = true; } break; case 0xD: diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index d0ca00fe0f..c2cc49e336 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -703,13 +703,9 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { - // This happens a lot at least in PQ2. This game has a small patch.003 (1344 bytes), - // containing 48 instruments. However it has several songs which use instruments - // not specified in that patch (namely, songs 1, 3, 5, 9, 15, 16, 17, 23, 25, 27, - // 29, 32, 36, 38, 44, 45, 46 all use instruments not specified in patch.003). - // These were probably written for MT32. These warnings in PQ2 can probably go away - // if a bigger patch.003 file is used (one that contains all the instruments used - // by the songs, i.e. 5382 bytes) + // This happens with songs 1 and 23 in PQ2. Song 1 (the title song) uses an invalid + // instrument 80, and song 23 (car horn when the car runs over you at the airport, + // rooms 14/15) an invalid instrument 89. These are probably leftovers from MT32. warning("ADLIB: Invalid patch %i requested (patch.003 contains %d instruments)", patch, _patches.size()); patch = 0; @@ -768,6 +764,7 @@ bool MidiDriver_AdLib::loadResource(const byte *data, uint size) { for (int i = 48; i < 96; i++) loadInstrument(data + 2 + (28 * i)); } else if (size == 5382) { + // SCI1.1 and later for (int i = 48; i < 190; i++) loadInstrument(data + (28 * i)); _rhythmKeyMap = new byte[kRhythmKeys]; -- cgit v1.2.3 From 680f7c897af5dac091e1abc47f0500cccbd07a51 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 15:40:18 +0000 Subject: Fixed a problem in kAnimate which occurred when a list was modified by a call (e.g. in KQ1 demo, PQ2) svn-id: r50022 --- engines/sci/engine/seg_manager.cpp | 8 +------- engines/sci/graphics/animate.cpp | 3 +++ 2 files changed, 4 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index f19c03d5a8..5371238304 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -531,12 +531,6 @@ Node *SegManager::lookupNode(reg_t addr) { SegmentType type = getSegmentType(addr.segment); if (type != SEG_TYPE_NODES) { - if (g_sci->getGameId() == "kq1sci") { - // WORKAROUND: The demo of KQ1 is trying to use an invalid memory reference as a list node - warning("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); - return NULL; - } - error("Attempt to use non-node %04x:%04x (type %d) as list node", PRINT_REG(addr), type); return NULL; } @@ -544,7 +538,7 @@ Node *SegManager::lookupNode(reg_t addr) { NodeTable *nt = (NodeTable *)_heap[addr.segment]; if (!nt->isValidEntry(addr.offset)) { - error("Attempt to use invalid reference %04x:%04x as list node", PRINT_REG(addr)); + error("Attempt to use invalid or discarded reference %04x:%04x as list node", PRINT_REG(addr)); return NULL; } diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 598724f2be..06054f3a19 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -606,6 +606,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t if (cycle) { if (!invoke(list, argc, argv)) return; + + // Look up the list again, as it may have been modified + list = _s->_segMan->lookupList(listReference); } Port *oldPort = _ports->setPort((Port *)_ports->_picWind); -- cgit v1.2.3 From 8a8480c0caa2848522cf18ec870343677c6af44f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 17:20:09 +0000 Subject: SCI: fix typo when setting EGA palette svn-id: r50023 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 35741dedf7..0972943b79 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -197,7 +197,7 @@ void GfxPalette::setEGA() { // Now setting colors 16-254 to the correct mix colors that occur when not doing a dithering run on // finished pictures for (curColor = 0x10; curColor <= 0xFE; curColor++) { - _sysPalette.colors[curColor].used = curColor; + _sysPalette.colors[curColor].used = 1; color1 = curColor & 0x0F; color2 = curColor >> 4; _sysPalette.colors[curColor].r = (_sysPalette.colors[color1].r >> 1) + (_sysPalette.colors[color2].r >> 1); _sysPalette.colors[curColor].g = (_sysPalette.colors[color1].g >> 1) + (_sysPalette.colors[color2].g >> 1); -- cgit v1.2.3 From 6f7f6572c4ded607d5f479c699d035cb2c8ebabb Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 18 Jun 2010 17:34:34 +0000 Subject: Fixed invalid memory read in LSL6 hires - kRobot(1) returns an integer svn-id: r50024 --- engines/sci/engine/kgraphics.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 4614ee878a..6e0dab7e28 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1265,6 +1265,9 @@ reg_t kRobot(EngineState *s, int argc, reg_t *argv) { warning("kRobot(init), id %d, obj %04x:%04x, flag %d, x=%d, y=%d", id, PRINT_REG(obj), flag, x, y); } break; + case 1: // LSL6 hires (startup) + // TODO + return NULL_REG; // an integer is expected case 4: { // start int id = argv[1].toUint16(); warning("kRobot(start), id %d", id); -- cgit v1.2.3 From 636ef64c688d1a059bc3dedb2afc35c3acb2e713 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 17:40:13 +0000 Subject: SCI: making vga views work in ega games :P svn-id: r50025 --- engines/sci/graphics/palette.cpp | 1 + engines/sci/graphics/view.cpp | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 0972943b79..8af6b597d6 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -203,6 +203,7 @@ void GfxPalette::setEGA() { _sysPalette.colors[curColor].g = (_sysPalette.colors[color1].g >> 1) + (_sysPalette.colors[color2].g >> 1); _sysPalette.colors[curColor].b = (_sysPalette.colors[color1].b >> 1) + (_sysPalette.colors[color2].b >> 1); } + _sysPalette.timestamp = 1; setOnScreen(); } diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 2ba14fbd8f..40c96dcfed 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -75,12 +75,27 @@ void GfxView::initData(GuiResourceId resourceId) { byte seekEntry; bool isEGA = false; bool isCompressed = true; + ViewType curViewType = _resMan->getViewType(); _loopCount = 0; _embeddedPal = false; _EGAmapping = NULL; - switch (_resMan->getViewType()) { + // If we find a SCI1/SCI1.1 view (not amiga), we switch to that type for EGA + if (curViewType == kViewEga) { + if (_resourceData[1] == 0x80) { + switch (READ_LE_UINT16(_resourceData + 4)) { + case 0: // SCI1 + curViewType = kViewVga; + break; + case 1: // SCI1.1 + curViewType = kViewVga11; + break; + } + } + } + + switch (curViewType) { case kViewEga: // View-format SCI0 (and Amiga 16 colors) isEGA = true; case kViewAmiga: // View-format Amiga (32 colors) -- cgit v1.2.3 From 3197dfc033adba2ced19dcaf3762a5b2c0ad2452 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 17:53:35 +0000 Subject: SCI: added more description about changes in r50025 svn-id: r50026 --- engines/sci/graphics/view.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 40c96dcfed..3fdfd86d2f 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -82,6 +82,9 @@ void GfxView::initData(GuiResourceId resourceId) { _EGAmapping = NULL; // If we find a SCI1/SCI1.1 view (not amiga), we switch to that type for EGA + // This could get used to make view patches for EGA games, where the new views include more colors + // Users could manually adjust old views to make them look better (like removing dithered colors that aren't + // caught by our undithering or even improve the graphics overall) if (curViewType == kViewEga) { if (_resourceData[1] == 0x80) { switch (READ_LE_UINT16(_resourceData + 4)) { -- cgit v1.2.3 From 8c8ce14164c21210e05115ab6a8f4f3f8a1d0e20 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 18:49:06 +0000 Subject: SCI: not using views coming from patch files anymore for detecting view type svn-id: r50027 --- engines/sci/resource.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 075d104f3e..a4eff573ab 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1697,6 +1697,10 @@ ViewType ResourceManager::detectViewType() { Resource *res = findResource(ResourceId(kResourceTypeView, i), 0); if (res) { + // Skip views coming from patch files + if (res->_source->getSourceType() == kSourcePatch) + continue; + switch (res->data[1]) { case 128: // If the 2nd byte is 128, it's a VGA game -- cgit v1.2.3 From 602b32175a75cac3ddf6d8ff531202fe197c91c4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 18:55:17 +0000 Subject: SCI: fixing detection of vga sci11 views for ega games (original change in r50025) svn-id: r50028 --- engines/sci/graphics/view.cpp | 10 +++------- 1 file changed, 3 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 3fdfd86d2f..6c0f6fda75 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -87,14 +87,10 @@ void GfxView::initData(GuiResourceId resourceId) { // caught by our undithering or even improve the graphics overall) if (curViewType == kViewEga) { if (_resourceData[1] == 0x80) { - switch (READ_LE_UINT16(_resourceData + 4)) { - case 0: // SCI1 - curViewType = kViewVga; - break; - case 1: // SCI1.1 + curViewType = kViewVga; + } else { + if (READ_LE_UINT16(_resourceData + 4) == 1) curViewType = kViewVga11; - break; - } } } -- cgit v1.2.3 From 75b7b54fe119bffa74cbba9b5c663b45769f3e10 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 22:06:13 +0000 Subject: SCI: Add mac SQ1 & SQ3 svn-id: r50030 --- engines/sci/detection_tables.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index dba4d879aa..2ac76578fe 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2572,6 +2572,18 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Space Quest 1 VGA Remake - English Mac (from Fingolfin) + {"sq1sci", "VGA Remake", { + {"resource.map", 0, "5c6ad20407261b544238e8dce87afead", 5895}, + {"resource.000", 0, "2c414644b23839069c8d1a93b721df16", 1017033}, + {"resource.001", 0, "8744ae2ea6b316e91e2a35ab1aa301d2", 1024622}, + {"resource.002", 0, "96860704f7a07ecc10bef223b4b2f153", 1273992}, + {"resource.003", 0, "ae46e195e66df5a131917f0aa80b5669", 1242794}, + {"resource.004", 0, "91d58a9eb2187c38424990afe4c12bc6", 1250949}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH + }, + // Space Quest 1 VGA Remake - English Non-Interactive Demo (from FRG) // SCI interpreter version 1.000.181 {"sq1sci", "VGA Remake, Demo", { @@ -2660,6 +2672,15 @@ static const struct ADGameDescription SciGameDescriptions[] = { {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Space Quest 3 - English Mac (from Fingolfin) + {"sq3", "", { + {"resource.map", 0, "5c931675c6e01c4b418faca85d76c92c", 5844}, + {"resource.001", 0, "0d8dfe42683b46f3131823233a91ce6a", 771917}, + {"resource.002", 0, "0d8dfe42683b46f3131823233a91ce6a", 794072}, + {"resource.003", 0, "0d8dfe42683b46f3131823233a91ce6a", 776536}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformMacintosh, 0, GUIO_NOSPEECH }, + // Space Quest 3 - German DOS (from Tobis87) // SCI interpreter version 0.000.453 (?) {"sq3", "", { -- cgit v1.2.3 From e5fcbc0c3a9b926cca5ba61d9c89038b260fbfa1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 22:06:31 +0000 Subject: AGI: Fix serguei1/serguei2/sqx detection svn-id: r50031 --- engines/agi/detection_tables.h | 44 ++++++++++++++++++++++-------------------- 1 file changed, 23 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index a3e95241c1..d4d5c0df76 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -27,10 +27,10 @@ namespace Agi { using Common::GUIO_NONE; -#define GAME_LVFPN(id,name,fname,md5,size,lang,ver,features,gid,platform,interp) { \ +#define GAME_LVFPN(id,extra,fname,md5,size,lang,ver,features,gid,platform,interp) { \ { \ id, \ - name, \ + extra, \ AD_ENTRY1s(fname,md5,size), \ lang, \ platform, \ @@ -59,26 +59,27 @@ using Common::GUIO_NONE; ver, \ } -#define GAME(id,name,md5,ver,gid) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) -#define GAME3(id,name,fname,md5,ver,gid) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) +#define GAME(id,extra,md5,ver,gid) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V2) +#define GAME3(id,extra,fname,md5,ver,gid) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,Common::kPlatformPC,GType_V3) -#define GAME_P(id,name,md5,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) +#define GAME_P(id,extra,md5,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_V2) -#define GAME_FP(id,name,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) +#define GAME_FP(id,extra,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V2) +#define GAME_F(id,extra,md5,ver,flags,gid) GAME_FP(id,extra,md5,ver,flags,gid,Common::kPlatformPC) -#define GAME_PS(id,name,md5,size,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) +#define GAME_PS(id,extra,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,Common::EN_ANY,ver,0,gid,platform,GType_V2) -#define GAME_LPS(id,name,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) +#define GAME_LPS(id,extra,md5,size,lang,ver,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,0,gid,platform,GType_V2) -#define GAME_LFPS(id,name,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,name,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) +#define GAME_LFPS(id,extra,md5,size,lang,ver,flags,gid,platform) GAME_LVFPN(id,extra,"logdir",md5,size,lang,ver,flags,gid,platform,GType_V2) -#define GAME3_P(id,name,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) +#define GAME3_P(id,extra,fname,md5,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,flags,gid,platform,GType_V3) -#define GAMEpre_P(id,name,fname,md5,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) +#define GAMEpre_P(id,extra,fname,md5,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,-1,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) -#define GAMEpre_PS(id,name,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) +#define GAMEpre_PS(id,extra,fname,md5,size,ver,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,0,gid,platform,GType_PreAGI) -#define GAME3_PS(id,name,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,name,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) +#define GAME3_PS(id,extra,fname,md5,size,ver,flags,gid,platform) GAME_LVFPN(id,extra,fname,md5,size,Common::EN_ANY,ver,flags,gid,platform,GType_V3) #define FANMADE_ILVF(id,name,md5,lang,ver,features) GAME_LVFPNF(id,name,"logdir",md5,-1,lang,ver,(GF_FANMADE|features),GID_FANMADE,Common::kPlatformPC,GType_V2) @@ -765,11 +766,12 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Save Santa (v1.3)", "f8afdb6efc5af5e7c0228b44633066af"), FANMADE("Schiller (preview 1)", "ade39dea968c959cfebe1cf935d653e9"), FANMADE("Schiller (preview 2)", "62cd1f8fc758bf6b4aa334e553624cef"), - FANMADE_IF("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", GF_AGIMOUSE|GF_AGIPAL), - FANMADE_IF("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", GF_AGIMOUSE), - FANMADE_IF("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", GF_AGIMOUSE|GF_AGIPAL), + GAME_F("serguei1", "v1.0", "b86725f067e456e10cdbdf5f58e01dec", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + // FIXME: The following two entries have identical MD5 checksums? + GAME_F("serguei1", "v1.1 2002 Sep 5", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + GAME_F("serguei1", "v1.1 2003 Apr 10", "91975c1fb4b13b0f9a8e9ff74731030d", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), + GAME_F("serguei2", "v0.1.1 Demo", "906ccbc2ddedb29b63141acc6d10cd28", 0x2917, GF_FANMADE|GF_AGIMOUSE, GID_FANMADE), + GAME_F("serguei2", "v1.3.1 Demo (March 22nd 2008)", "ad1308fcb8f48723cd388e012ebf5e20", 0x2917, GF_FANMADE|GF_AGIMOUSE|GF_AGIPAL, GID_FANMADE), FANMADE("Shifty (v1.0)", "2a07984d27b938364bf6bd243ac75080"), FANMADE_F("Sliding Tile Game (v1.00)", "949bfff5d8a81c3139152eed4d84ca75", GF_AGIMOUSE), FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), @@ -778,9 +780,9 @@ static const AGIGameDescription gameDescriptions[] = { GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_SQ0), GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_SQ0), GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_SQ0, Common::kPlatformCoCo3), - FANMADE_I("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1"), - FANMADE_I("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910"), - FANMADE_ISVP("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, Common::kPlatformCoCo3), + GAME("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1", 0x2917, GID_FANMADE), + GAME("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910", 0x2917, GID_FANMADE), + GAME_PS("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, GID_FANMADE, Common::kPlatformCoCo3), FANMADE_F("Space Quest 3.5", "c077bc28d7b36213dd99dc9ecb0147fc", GF_AGIMOUSE|GF_AGIPAL), FANMADE_F("Space Trek (v1.0)", "807a1aeadb2ace6968831d36ab5ea37a", GF_CLIPCOORDS), FANMADE("Special Delivery", "88764dfe61126b8e73612c851b510a33"), -- cgit v1.2.3 From 7a8b8c88ae52cb4a6a40ec233e43d006ce645c8d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 22:06:56 +0000 Subject: AGI: cleanup svn-id: r50032 --- engines/agi/agi.h | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 4cc823df5a..34aa99b3f2 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -37,6 +37,14 @@ #include "gui/debugger.h" +// AGI resources +#include "agi/console.h" +#include "agi/view.h" +#include "agi/picture.h" +#include "agi/logic.h" +#include "agi/sound.h" + + namespace Common { class RandomSource; } /** @@ -117,17 +125,6 @@ enum AgiGameID { GID_TROLL // PreAGI }; -} // End of namespace Agi - -// AGI resources -#include "agi/console.h" -#include "agi/view.h" -#include "agi/picture.h" -#include "agi/logic.h" -#include "agi/sound.h" - -namespace Agi { - enum AgiGameType { GType_PreAGI = 0, GType_V2 = 1, -- cgit v1.2.3 From da28fde4c61d8f050be8b2eb90b7b634869e3f22 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 18 Jun 2010 22:07:32 +0000 Subject: AGI: Change some #defines to enums svn-id: r50033 --- engines/agi/agi.cpp | 2 +- engines/agi/agi.h | 53 ++++++++++++++++++++++++++++++------------------ engines/agi/cycle.cpp | 6 +++--- engines/agi/op_cmd.cpp | 4 ++-- engines/agi/op_test.cpp | 2 +- engines/agi/saveload.cpp | 6 +++--- 6 files changed, 43 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 21b28fd445..0875646148 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -556,7 +556,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _restartGame = false; - _oldMode = -1; + _oldMode = INPUT_NONE; _predictiveDialogRunning = false; _predictiveDictText = NULL; diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 34aa99b3f2..fb425b6b87 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -502,10 +502,32 @@ struct ScriptPos { int curIP; }; -#define EGO_VIEW_TABLE 0 -#define HORIZON 36 -#define _WIDTH 160 -#define _HEIGHT 168 +enum { + EGO_VIEW_TABLE = 0, + HORIZON = 36, + _WIDTH = 160, + _HEIGHT = 168 +}; + +enum InputMode { + INPUT_NORMAL = 0x01, + INPUT_GETSTRING = 0x02, + INPUT_MENU = 0x03, + INPUT_NONE = 0x04 +}; + +enum State { + STATE_INIT = 0x00, + STATE_LOADED = 0x01, + STATE_RUNNING = 0x02 +}; + +enum { + SBUF16_OFFSET = 0, + SBUF256_OFFSET = ((_WIDTH) * (_HEIGHT)), + FROM_SBUF16_TO_SBUF256_OFFSET = ((SBUF256_OFFSET) - (SBUF16_OFFSET)), + FROM_SBUF256_TO_SBUF16_OFFSET = ((SBUF16_OFFSET) - (SBUF256_OFFSET)) +}; /** * AGI game structure. @@ -513,10 +535,7 @@ struct ScriptPos { * by the interpreter. */ struct AgiGame { -#define STATE_INIT 0x00 -#define STATE_LOADED 0x01 -#define STATE_RUNNING 0x02 - int state; /**< state of the interpreter */ + State state; /**< state of the interpreter */ // TODO: Check whether adjMouseX and adjMouseY must be saved and loaded when using savegames. // If they must be then loading and saving is partially broken at the moment. @@ -540,12 +559,9 @@ struct AgiGame { uint8 inputBuffer[40]; /**< buffer for user input */ uint8 echoBuffer[40]; /**< buffer for echo.line */ int keypress; -#define INPUT_NORMAL 0x01 -#define INPUT_GETSTRING 0x02 -#define INPUT_MENU 0x03 -#define INPUT_NONE 0x04 - int inputMode; /**< keyboard input mode */ - int inputEnabled; /**< keyboard input enabled */ + + InputMode inputMode; /**< keyboard input mode */ + bool inputEnabled; /**< keyboard input enabled */ int lognum; /**< current logic number */ Common::Array execStack; @@ -573,10 +589,7 @@ struct AgiGame { char cursorChar; unsigned int colorFg; unsigned int colorBg; -#define SBUF16_OFFSET 0 -#define SBUF256_OFFSET ((_WIDTH) * (_HEIGHT)) -#define FROM_SBUF16_TO_SBUF256_OFFSET ((SBUF256_OFFSET) - (SBUF16_OFFSET)) -#define FROM_SBUF256_TO_SBUF16_OFFSET ((SBUF16_OFFSET) - (SBUF256_OFFSET)) + uint8 *sbufOrig; /**< Pointer to the 160x336 AGI screen buffer that contains vertically two 160x168 screens (16 color and 256 color). */ uint8 *sbuf16c; /**< 160x168 16 color (+control line & priority information) AGI screen buffer. Points at sbufOrig + SBUF16_OFFSET. */ uint8 *sbuf256c; /**< 160x168 256 color AGI screen buffer (For AGI256 and AGI256-2 support). Points at sbufOrig + SBUF256_OFFSET. */ @@ -834,7 +847,7 @@ public: int loadGameSimple(); uint8 *_intobj; - int _oldMode; + InputMode _oldMode; bool _restartGame; Menu* _menu; @@ -876,7 +889,7 @@ public: static void agiTimerFunctionLow(void *refCon); void initPriTable(); - void newInputMode(int); + void newInputMode(InputMode mode); void oldInputMode(); int getvar(int); diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index 40d6f2d008..ee55c783f1 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -177,9 +177,9 @@ void AgiEngine::updateTimer() { setvar(vDays, getvar(vDays) + 1); } -void AgiEngine::newInputMode(int i) { +void AgiEngine::newInputMode(InputMode mode) { _oldMode = _game.inputMode; - _game.inputMode = i; + _game.inputMode = mode; } void AgiEngine::oldInputMode() { @@ -436,7 +436,7 @@ int AgiEngine::runGame() { setvar(vFreePages, 180); // Set amount of free memory to realistic value setvar(vMaxInputChars, 38); _game.inputMode = INPUT_NONE; - _game.inputEnabled = 0; + _game.inputEnabled = false; _game.hasPrompt = 0; _game.state = STATE_RUNNING; diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index ab7e5010e7..9728ed9b42 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -1563,8 +1563,8 @@ cmd(shake_screen) { // Disables input while shaking to prevent bug // #1678230: AGI: Entering text while screen is shaking - int originalValue = game.inputEnabled; - game.inputEnabled = 0; + bool originalValue = game.inputEnabled; + game.inputEnabled = false; g_gfx->shakeStart(); diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 71d307556b..f10cdd3f17 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -111,7 +111,7 @@ static uint8 testKeypressed() { game.keypress = 0; if (!x) { - int mode = game.inputMode; + InputMode mode = game.inputMode; game.inputMode = INPUT_NONE; g_agi->mainCycle(); diff --git a/engines/agi/saveload.cpp b/engines/agi/saveload.cpp index 88e279ecf8..88b14dcfe2 100644 --- a/engines/agi/saveload.cpp +++ b/engines/agi/saveload.cpp @@ -132,7 +132,7 @@ int AgiEngine::saveGame(const char *fileName, const char *description) { out->writeSint16BE((int16)_game.hasPrompt); out->writeSint16BE((int16)_game.gameFlags); - out->writeSint16BE((int16)_game.inputEnabled); + out->writeSint16BE(_game.inputEnabled); for (i = 0; i < _HEIGHT; i++) out->writeByte(_game.priTable[i]); @@ -302,7 +302,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { // TODO: played time } - _game.state = in->readByte(); + _game.state = (State)in->readByte(); in->read(loadId, 8); if (strcmp(loadId, _game.id) && checkId) { @@ -361,7 +361,7 @@ int AgiEngine::loadGame(const char *fileName, bool checkId) { _game.echoBuffer[0] = 0; _game.keypress = 0; - _game.inputMode = in->readSint16BE(); + _game.inputMode = (InputMode)in->readSint16BE(); _game.lognum = in->readSint16BE(); _game.playerControl = in->readSint16BE(); -- cgit v1.2.3 From 25c86e8b03574163d7c6df6e54d00cbffc66b4ef Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 18 Jun 2010 22:16:05 +0000 Subject: SCI: set resulting type to keyboard+joystick for sci1middle+ in kMapKeyToDir - fixes keyboard controlling of mouse in all sorts of games - although this is not 100% done, the change actually happened inbetween sci1early, added fixme svn-id: r50034 --- engines/sci/engine/kevent.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 2f1afd4358..f516a9d4b1 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -203,7 +203,12 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { } if (mover >= 0) { - writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK); + // FIXME: changing point was actually inbetween SCI1EARLY, we need to find out when it happened + // and then find some method of finding out those specific games + if (getSciVersion() >= SCI_VERSION_1_MIDDLE) + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_JOYSTICK); + else + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK); writeSelectorValue(segMan, obj, SELECTOR(message), mover); return make_reg(0, 1); } else -- cgit v1.2.3 From f4b700c4c45e601a5d1571f980ec7e5636e0f166 Mon Sep 17 00:00:00 2001 From: Walter van Niftrik Date: Sat, 19 Jun 2010 01:16:25 +0000 Subject: SCI: AdLib: add dummy instruments when there are only 48 in the patch svn-id: r50035 --- engines/sci/sound/drivers/adlib.cpp | 17 ++++++++++------- 1 file changed, 10 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/drivers/adlib.cpp b/engines/sci/sound/drivers/adlib.cpp index c2cc49e336..55c3640c9d 100644 --- a/engines/sci/sound/drivers/adlib.cpp +++ b/engines/sci/sound/drivers/adlib.cpp @@ -703,11 +703,8 @@ void MidiDriver_AdLib::setVelocityReg(int regOffset, int velocity, int kbScaleLe void MidiDriver_AdLib::setPatch(int voice, int patch) { if ((patch < 0) || ((uint)patch >= _patches.size())) { - // This happens with songs 1 and 23 in PQ2. Song 1 (the title song) uses an invalid - // instrument 80, and song 23 (car horn when the car runs over you at the airport, - // rooms 14/15) an invalid instrument 89. These are probably leftovers from MT32. - warning("ADLIB: Invalid patch %i requested (patch.003 contains %d instruments)", - patch, _patches.size()); + warning("ADLIB: Invalid patch %i requested", patch); + // Substitute instrument 0 patch = 0; } @@ -760,10 +757,16 @@ bool MidiDriver_AdLib::loadResource(const byte *data, uint size) { for (int i = 0; i < 48; i++) loadInstrument(data + (28 * i)); - if (size == 2690) { + if (size == 1344) { + byte dummy[28] = {0}; + + // Only 48 instruments, add dummies + for (int i = 0; i < 48; i++) + loadInstrument(dummy); + } else if (size == 2690) { for (int i = 48; i < 96; i++) loadInstrument(data + 2 + (28 * i)); - } else if (size == 5382) { + } else { // SCI1.1 and later for (int i = 48; i < 190; i++) loadInstrument(data + (28 * i)); -- cgit v1.2.3 From 61c40e2bd4cf5f23314d819e70d7eb0a966993cf Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 02:50:46 +0000 Subject: Save the context of a suspended list before resuming the execution, so that it can safely be suspended again. Patch 3004652 by fuzzie. svn-id: r50037 --- engines/parallaction/exec.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/parallaction/exec.cpp b/engines/parallaction/exec.cpp index 24579286e6..434c4f6ae6 100644 --- a/engines/parallaction/exec.cpp +++ b/engines/parallaction/exec.cpp @@ -193,8 +193,10 @@ void CommandExec::runSuspended() { debugC(3, kDebugExec, "CommandExec::runSuspended()"); _execZone = _suspendedCtxt._zone; - runList(_suspendedCtxt._first, _suspendedCtxt._last); + CommandList::iterator first = _suspendedCtxt._first; + CommandList::iterator last = _suspendedCtxt._last; cleanSuspendedList(); + runList(first, last); } } -- cgit v1.2.3 From 5b3075bd653f888d814abd32b878870c2388668c Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 02:51:03 +0000 Subject: Guarded the command execution suspension for NS demo (this was due in r38662 - see bug #2619824). svn-id: r50038 --- engines/parallaction/callables_ns.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/callables_ns.cpp b/engines/parallaction/callables_ns.cpp index a493523301..cfe6ad8954 100644 --- a/engines/parallaction/callables_ns.cpp +++ b/engines/parallaction/callables_ns.cpp @@ -453,14 +453,15 @@ void Parallaction_ns::_c_startIntro(void *parm) { } void Parallaction_ns::_c_endIntro(void *parm) { - // NOTE: suspend command execution queue, to - // avoid running the QUIT command before - // credits are displayed. This solves bug - // #2619824. - // Execution of the command list will resume - // as soon as runGameFrame is run. - _cmdExec->suspend(); - + if (getFeatures() & GF_DEMO) { + // NOTE: suspend command execution queue, to + // avoid running the QUIT command before + // credits are displayed. This solves bug + // #2619824. + // Execution of the command list will resume + // as soon as runGameFrame is run. + _cmdExec->suspend(); + } startCreditSequence(); _intro = false; } -- cgit v1.2.3 From d7a165b9f256244ed5b4e7f48cea82a540cf1698 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 04:50:44 +0000 Subject: Implemented PART command for BRA, largely based on patch #3005434 by fuzzie. svn-id: r50039 --- engines/parallaction/exec_br.cpp | 2 +- engines/parallaction/parallaction.h | 3 +++ engines/parallaction/parallaction_br.cpp | 22 ++++++++++++++++++---- 3 files changed, 22 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index e145c0da94..76e6f0dfe0 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -293,7 +293,7 @@ DECLARE_COMMAND_OPCODE(text) { DECLARE_COMMAND_OPCODE(part) { - warning("Parallaction_br::cmdOp_part not yet implemented"); + _vm->_nextPart = ctxt._cmd->_counterValue; } diff --git a/engines/parallaction/parallaction.h b/engines/parallaction/parallaction.h index 151bfd958d..7bbdf79f1c 100644 --- a/engines/parallaction/parallaction.h +++ b/engines/parallaction/parallaction.h @@ -548,6 +548,9 @@ public: const char **_audioCommandsNamesRes; static const char *_partNames[]; int _part; + int _nextPart; + + #if 0 // disabled since I couldn't find any references to lip sync in the scripts int16 _lipSyncVal; uint _subtitleLipSync; diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index c752c85d4f..5023a05d85 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -86,6 +86,7 @@ Common::Error Parallaction_br::init() { _walker = new PathWalker_BR; _part = -1; + _nextPart = -1; _subtitle[0] = 0; _subtitle[1] = 0; @@ -260,6 +261,8 @@ void Parallaction_br::cleanupGame() { _globalFlagsNames = 0; _objectsNames = 0; _countersNames = 0; + + memset(_zoneFlags, 0, sizeof(_zoneFlags)); } @@ -272,13 +275,23 @@ void Parallaction_br::changeLocation() { strcpy(location, _newLocationName.c_str()); char *partStr = strrchr(location, '.'); - if (partStr) { + if (partStr || _nextPart != -1) { cleanupGame(); - int n = partStr - location; - location[n] = '\0'; + // more cleanup needed for part changes (see also saveload) + _globalFlags = 0; + cleanInventory(true); + strcpy(_characterName1, "null"); + + if (partStr) { + int n = partStr - location; + location[n] = '\0'; + + _part = atoi(++partStr); + } else { + _part = _nextPart; + } - _part = atoi(++partStr); if (getFeatures() & GF_DEMO) { assert(_part == 1); } else { @@ -357,6 +370,7 @@ void Parallaction_br::changeLocation() { _engineFlags &= ~kEngineChangeLocation; _newLocationName.clear(); + _nextPart = -1; } // FIXME: Parallaction_br::parseLocation() is now a verbatim copy of the same routine from Parallaction_ns. -- cgit v1.2.3 From de7de460e8c985764d9e5719789da0aa8df914e9 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 04:51:00 +0000 Subject: Use the new _nextPart member switching part from the menu in BRA. svn-id: r50040 --- engines/parallaction/gui_br.cpp | 30 ++++++++++++++++++++---------- 1 file changed, 20 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/gui_br.cpp b/engines/parallaction/gui_br.cpp index 7096bbe569..21cb2d8b00 100644 --- a/engines/parallaction/gui_br.cpp +++ b/engines/parallaction/gui_br.cpp @@ -98,6 +98,12 @@ public: } }; + +struct LocationPart { + int part; + const char *location; +}; + class MainMenuInputState_BR : public MenuInputState { Parallaction_br *_vm; @@ -158,7 +164,7 @@ class MainMenuInputState_BR : public MenuInputState { const char **_menuStrings; const MenuOptions *_options; - static const char *_firstLocation[]; + static LocationPart _firstLocation[]; int _availItems; int _selection; @@ -205,7 +211,8 @@ public: return this; } - switch (_options[_selection]) { + int selection = _options[_selection]; + switch (selection) { case kMenuQuit: { _vm->quitGame(); break; @@ -218,8 +225,10 @@ public: } break; - default: - _vm->scheduleLocationSwitch(_firstLocation[_options[_selection]]); + default: + _vm->_nextPart = _firstLocation[selection].part; + _vm->scheduleLocationSwitch(_firstLocation[selection].location); + } _vm->_system->showMouse(false); @@ -262,14 +271,15 @@ public: }; -const char *MainMenuInputState_BR::_firstLocation[] = { - "intro.0", - "museo.1", - "start.2", - "bolscoi.3", - "treno.4" +LocationPart MainMenuInputState_BR::_firstLocation[] = { + { 0, "intro" }, + { 1, "museo" }, + { 2, "start" }, + { 3, "bolscoi" }, + { 4, "treno" } }; + const char *MainMenuInputState_BR::_menuStringsAmiga[NUM_MENULINES] = { "See the introduction", "Load a Saved Game", -- cgit v1.2.3 From 96d4ae0fcccbe6438c5829a4a679d94180407159 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 04:51:14 +0000 Subject: Cleanup some more state when switching part in BRA. svn-id: r50041 --- engines/parallaction/parallaction_br.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 5023a05d85..cd9b15381b 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -262,6 +262,10 @@ void Parallaction_br::cleanupGame() { _objectsNames = 0; _countersNames = 0; + _numLocations = 0; + _globalFlags = 0; + memset(_localFlags, 0, sizeof(_localFlags)); + memset(_locationNames, 0, sizeof(_locationNames)); memset(_zoneFlags, 0, sizeof(_zoneFlags)); } -- cgit v1.2.3 From 5328abe2f0b1afa33c360b098865de491410b677 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sat, 19 Jun 2010 04:51:31 +0000 Subject: Cleanup. Got rid of the legacy "location.part" string handling in BRA. svn-id: r50042 --- engines/parallaction/parallaction_br.cpp | 19 ++++--------------- 1 file changed, 4 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index cd9b15381b..153ea1541d 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -275,11 +275,7 @@ void Parallaction_br::changeLocation() { return; } - char location[200]; - strcpy(location, _newLocationName.c_str()); - - char *partStr = strrchr(location, '.'); - if (partStr || _nextPart != -1) { + if (_nextPart != -1) { cleanupGame(); // more cleanup needed for part changes (see also saveload) @@ -287,14 +283,7 @@ void Parallaction_br::changeLocation() { cleanInventory(true); strcpy(_characterName1, "null"); - if (partStr) { - int n = partStr - location; - location[n] = '\0'; - - _part = atoi(++partStr); - } else { - _part = _nextPart; - } + _part = _nextPart; if (getFeatures() & GF_DEMO) { assert(_part == 1); @@ -322,8 +311,8 @@ void Parallaction_br::changeLocation() { freeLocation(false); // load new location - strcpy(_location._name, location); - parseLocation(location); + strcpy(_location._name, _newLocationName.c_str()); + parseLocation(_location._name); if (_location._startPosition.x != -1000) { _char._ani->setFoot(_location._startPosition); -- cgit v1.2.3 From a7fa0649dfc71c79f496a86986413f35c8d36966 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 09:46:04 +0000 Subject: SCI: implemented checking of keyboard driver in case of SCI1EGA/EARLY, also renamed SCI_EVENT_JOYSTICK to SCI_EVENT_DIRECTION svn-id: r50045 --- engines/sci/engine/kevent.cpp | 8 +++----- engines/sci/event.cpp | 34 ++++++++++++++++++++++++++++++++++ engines/sci/event.h | 5 ++++- 3 files changed, 41 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index f516a9d4b1..e38550adee 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -203,12 +203,10 @@ reg_t kMapKeyToDir(EngineState *s, int argc, reg_t *argv) { } if (mover >= 0) { - // FIXME: changing point was actually inbetween SCI1EARLY, we need to find out when it happened - // and then find some method of finding out those specific games - if (getSciVersion() >= SCI_VERSION_1_MIDDLE) - writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_JOYSTICK); + if (g_sci->getEventManager()->getUsesNewKeyboardDirectionType()) + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_KEYBOARD | SCI_EVENT_DIRECTION); else - writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_JOYSTICK); + writeSelectorValue(segMan, obj, SELECTOR(type), SCI_EVENT_DIRECTION); writeSelectorValue(segMan, obj, SELECTOR(message), mover); return make_reg(0, 1); } else diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index eff7984d39..6c9e95a804 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -25,6 +25,7 @@ #include "common/system.h" #include "common/events.h" +#include "common/file.h" #include "sci/sci.h" #include "sci/event.h" @@ -35,11 +36,44 @@ namespace Sci { EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended), _modifierStates(0) { + + if (getSciVersion() >= SCI_VERSION_1_MIDDLE) { + _usesNewKeyboardDirectionType = true; + } else if (getSciVersion() <= SCI_VERSION_01) { + _usesNewKeyboardDirectionType = false; + } else { + // they changed this somewhere inbetween SCI1EGA/EARLY, so we need to check the size of the keyboard driver + _usesNewKeyboardDirectionType = false; + + Common::File keyboardDriver; + if (keyboardDriver.open("IBMKBD.DRV")) { + switch (keyboardDriver.size()) { + case 442: // SCI0 (PQ2) + case 446: // SCI0 (SQ3) + case 449: // SCI1EGA (QfG2) + break; + case 537: // SCI1 (SQ4) + case 564: // SCI1.1 (LB2) + case 758: // SCI1.1 (LB2cd) + case 760: // SCI1.1 (Pepper) + _usesNewKeyboardDirectionType = true; + break; + default: + error("Unsupported IBMKBD.DRV size (%d)", keyboardDriver.size()); + } + } else { + // We just default to OFF here in case the keyboard driver could not be found + warning("IBMKBD.DRV not found to distinguish usage of direction type"); + } + } } EventManager::~EventManager() { } +bool EventManager::getUsesNewKeyboardDirectionType() { + return _usesNewKeyboardDirectionType; +} struct ScancodeRow { int offset; diff --git a/engines/sci/event.h b/engines/sci/event.h index 314add7b2c..30098b0f6e 100644 --- a/engines/sci/event.h +++ b/engines/sci/event.h @@ -53,7 +53,7 @@ struct SciEvent { #define SCI_EVENT_MOUSE_PRESS (1<<0) #define SCI_EVENT_MOUSE_RELEASE (1<<1) #define SCI_EVENT_KEYBOARD (1<<2) -#define SCI_EVENT_JOYSTICK (1<<6) +#define SCI_EVENT_DIRECTION (1<<6) #define SCI_EVENT_SAID (1<<7) /*Fake values for other events*/ #define SCI_EVENT_ERROR (1<<10) @@ -115,6 +115,7 @@ public: ~EventManager(); SciEvent getSciEvent(unsigned int mask); + bool getUsesNewKeyboardDirectionType(); private: SciEvent getScummVMEvent(); @@ -122,6 +123,8 @@ private: const bool _fontIsExtended; int _modifierStates; Common::List _events; + + bool _usesNewKeyboardDirectionType; }; } // End of namespace Sci -- cgit v1.2.3 From 101218c1b6843692d82e992372e5ac8af81393d5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 10:28:41 +0000 Subject: SCI: added TODO for keyboard driver size check, maybe this whole stuff isn't needed at all svn-id: r50046 --- engines/sci/event.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 6c9e95a804..7931e8266b 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -42,6 +42,8 @@ EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended } else if (getSciVersion() <= SCI_VERSION_01) { _usesNewKeyboardDirectionType = false; } else { + // TODO: maybe this is even not needed at all and we can just use the old method for sci1early + // sq4 floppy doesn't have issues when using the old method although the keyboard driver is new // they changed this somewhere inbetween SCI1EGA/EARLY, so we need to check the size of the keyboard driver _usesNewKeyboardDirectionType = false; -- cgit v1.2.3 From 710f0257eb1cd1fda1f5ac340375b13ee6efabe9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 10:57:01 +0000 Subject: SCI: replacing the keyboard size check for direction type detection with checking for script 933 (pseudoMouse) instead - this is better because its working multiplatform svn-id: r50047 --- engines/sci/event.cpp | 30 +++++++----------------------- 1 file changed, 7 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/sci/event.cpp b/engines/sci/event.cpp index 7931e8266b..a100dda27c 100644 --- a/engines/sci/event.cpp +++ b/engines/sci/event.cpp @@ -42,31 +42,15 @@ EventManager::EventManager(bool fontIsExtended) : _fontIsExtended(fontIsExtended } else if (getSciVersion() <= SCI_VERSION_01) { _usesNewKeyboardDirectionType = false; } else { - // TODO: maybe this is even not needed at all and we can just use the old method for sci1early - // sq4 floppy doesn't have issues when using the old method although the keyboard driver is new - // they changed this somewhere inbetween SCI1EGA/EARLY, so we need to check the size of the keyboard driver + // they changed this somewhere inbetween SCI1EGA/EARLY _usesNewKeyboardDirectionType = false; - Common::File keyboardDriver; - if (keyboardDriver.open("IBMKBD.DRV")) { - switch (keyboardDriver.size()) { - case 442: // SCI0 (PQ2) - case 446: // SCI0 (SQ3) - case 449: // SCI1EGA (QfG2) - break; - case 537: // SCI1 (SQ4) - case 564: // SCI1.1 (LB2) - case 758: // SCI1.1 (LB2cd) - case 760: // SCI1.1 (Pepper) - _usesNewKeyboardDirectionType = true; - break; - default: - error("Unsupported IBMKBD.DRV size (%d)", keyboardDriver.size()); - } - } else { - // We just default to OFF here in case the keyboard driver could not be found - warning("IBMKBD.DRV not found to distinguish usage of direction type"); - } + // We are looking if script 933 exists, that one has the PseudoMouse class in it that handles it + // The good thing is that PseudoMouse seems to only exists in games that use the new method + if (g_sci->getResMan()->testResource(ResourceId(kResourceTypeScript, 933))) + _usesNewKeyboardDirectionType = true; + // Checking the keyboard driver size in here would also be a valid method, but the driver is only available + // in PC versions of the game } } -- cgit v1.2.3 From 0c93154eb90b58cf5618b45e5e63a91694196d93 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 19 Jun 2010 11:08:16 +0000 Subject: AGI: Fix detection of AGI Tetris and Caitlyn's Destiny svn-id: r50048 --- engines/agi/detection_tables.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index d4d5c0df76..a9caa538b1 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -578,7 +578,7 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE_F("AGI Mouse Demo 1.10", "f4ad396b496d6167635ad0b410312ab8", GF_AGIMOUSE|GF_AGIPAL), FANMADE("AGI Piano (v1.0)", "8778b3d89eb93c1d50a70ef06ef10310"), FANMADE("AGI Quest (v1.46-TJ0)", "1cf1a5307c1a0a405f5039354f679814"), - FANMADE_I("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a"), + GAME("tetris", "", "7a874e2db2162e7a4ce31c9130248d8a", 0x2917, GID_FANMADE), FANMADE_V("AGI Trek (Demo)", "c02882b8a8245b629c91caf7eb78eafe", 0x2440), FANMADE_F("AGI256 Demo", "79261ac143b2e2773b2753674733b0d5", GF_AGI256), FANMADE_F("AGI256-2 Demo", "3cad9b3aff1467cebf0c5c5b110985c5", GF_AGI256_2), @@ -605,8 +605,8 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Botz", "a8fabe4e807adfe5ec02bfec6d983695"), FANMADE("Brian's Quest (v1.0)", "0964aa79b9cdcff7f33a12b1d7e04b9c"), FANMADE("CPU-21 (v1.0)", "35b7cdb4d17e890e4c52018d96e9cbf4"), - FANMADE_I("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98"), - FANMADE_I("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8"), + GAME("caitlyn", "Demo", "5b8a3cdb2fc05469f8119d49f50fbe98", 0x2917, GID_FANMADE), + GAME("caitlyn", "", "818469c484cae6dad6f0e9a353f68bf8", 0x2917, GID_FANMADE), FANMADE("Car Driver (v1.1)", "2311611d2d36d20ccc9da806e6cba157"), FANMADE("Cloak of Darkness (v1.0)", "5ba6e18bf0b53be10db8f2f3831ee3e5"), FANMADE("Coco Coq (English) - Coco Coq In Grostesteing's Base (v.1.0.3)", "97631f8e710544a58bd6da9e780f9320"), -- cgit v1.2.3 From 32668b553fe69fc8cea5afc60d5f82abdc9a4fb8 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Sat, 19 Jun 2010 11:08:41 +0000 Subject: AGI: Get rid of GID_SQ0 svn-id: r50049 --- engines/agi/agi.h | 1 - engines/agi/detection_tables.h | 6 +++--- 2 files changed, 3 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.h b/engines/agi/agi.h index fb425b6b87..18f291d62c 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -119,7 +119,6 @@ enum AgiGameID { GID_XMASCARD, GID_FANMADE, GID_GETOUTTASQ, // Fanmade - GID_SQ0, // Fanmade GID_MICKEY, // PreAGI GID_WINNIE, // PreAGI GID_TROLL // PreAGI diff --git a/engines/agi/detection_tables.h b/engines/agi/detection_tables.h index a9caa538b1..711701f55a 100644 --- a/engines/agi/detection_tables.h +++ b/engines/agi/detection_tables.h @@ -777,9 +777,9 @@ static const AGIGameDescription gameDescriptions[] = { FANMADE("Snowboarding Demo (v1.0)", "24bb8f29f1eddb5c0a099705267c86e4"), FANMADE("Solar System Tour", "b5a3d0f392dfd76a6aa63f3d5f578403"), FANMADE("Sorceror's Appraisal", "fe62615557b3cb7b08dd60c9d35efef1"), - GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_SQ0), - GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_SQ0), - GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_SQ0, Common::kPlatformCoCo3), + GAME("sq0", "v1.03", "d2fd6f7404e86182458494e64375e590", 0x2917, GID_FANMADE), + GAME("sq0", "v1.04", "2ad9d1a4624a98571ee77dcc83f231b6", 0x2917, GID_FANMADE), + GAME_PS("sq0", "", "e1a8e4efcce86e1efcaa14633b9eb986", 762, 0x2440, GID_FANMADE, Common::kPlatformCoCo3), GAME("sqx", "v10.0 Feb 05", "c992ae2f8ab18360404efdf16fa9edd1", 0x2917, GID_FANMADE), GAME("sqx", "v10.0 Jul 18", "812edec45cefad559d190ffde2f9c910", 0x2917, GID_FANMADE), GAME_PS("sqx", "", "f0a59044475a5fa37c055d8c3eb4d1a7", 768, 0x2440, GID_FANMADE, Common::kPlatformCoCo3), -- cgit v1.2.3 From 26e4e0e345bbfb5b84a53a023b9b78207f859cc7 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 17:12:17 +0000 Subject: SCI: cleanup view decompression code svn-id: r50053 --- engines/sci/graphics/view.cpp | 131 +++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 66 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 6c0f6fda75..7c33f87a14 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -323,78 +323,41 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou memset(outPtr + pixelNo, pixel & 0x0F, MIN(runLength, pixelCount - pixelNo)); pixelNo += runLength; } - return; - } - - rlePtr = _resourceData + celInfo->offsetRLE; - if (!celInfo->offsetLiteral) { // no additional literal data - if (_resMan->isAmiga32color()) { - // decompression for amiga views - while (pixelNo < pixelCount) { - pixel = *rlePtr++; - if (pixel & 0x07) { // fill with color - runLength = pixel & 0x07; - pixel = pixel >> 3; - while (runLength-- && pixelNo < pixelCount) { - outPtr[pixelNo++] = pixel; - } - } else { // fill with transparent - runLength = pixel >> 3; - pixelNo += runLength; - } - } - return; - } else { - // decompression for data that has just one combined stream - while (pixelNo < pixelCount) { - pixel = *rlePtr++; - runLength = pixel & 0x3F; - switch (pixel & 0xC0) { - case 0: // copy bytes as-is - while (runLength-- && pixelNo < pixelCount) - outPtr[pixelNo++] = *rlePtr++; - break; - case 0x80: // fill with color - memset(outPtr + pixelNo, *rlePtr++, MIN(runLength, pixelCount - pixelNo)); - pixelNo += runLength; - break; - case 0xC0: // fill with transparent - pixelNo += runLength; - break; - } - } - return; - } } else { - literalPtr = _resourceData + celInfo->offsetLiteral; - if (celInfo->offsetRLE) { - if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { - // Crazy-Ass compression for SCI1.1+ Mac + // we skip over transparent pixels, so the buffer needs to be already filled with it + // also some RLE compressed cels are possibly ending with the last non-transparent pixel + // (is this even possible with the current code?) + memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount); + + rlePtr = _resourceData + celInfo->offsetRLE; + if (!celInfo->offsetLiteral) { // no additional literal data + if (_resMan->isAmiga32color()) { + // decompression for amiga views while (pixelNo < pixelCount) { - uint32 pixelLine = pixelNo; - runLength = *rlePtr++; - pixelNo += runLength; - runLength = *rlePtr++; - while (runLength-- && pixelNo < pixelCount) { - outPtr[pixelNo] = *literalPtr++; - if (outPtr[pixelNo] == 255) - outPtr[pixelNo] = 0; - pixelNo++; + pixel = *rlePtr++; + if (pixel & 0x07) { // fill with color + runLength = pixel & 0x07; + pixel = pixel >> 3; + while (runLength-- && pixelNo < pixelCount) { + outPtr[pixelNo++] = pixel; + } + } else { // fill with transparent + runLength = pixel >> 3; + pixelNo += runLength; } - pixelNo = pixelLine + celInfo->width; } } else { - // decompression for data that has separate rle and literal streams + // decompression for data that has just one combined stream while (pixelNo < pixelCount) { pixel = *rlePtr++; runLength = pixel & 0x3F; switch (pixel & 0xC0) { case 0: // copy bytes as-is while (runLength-- && pixelNo < pixelCount) - outPtr[pixelNo++] = *literalPtr++; + outPtr[pixelNo++] = *rlePtr++; break; case 0x80: // fill with color - memset(outPtr + pixelNo, *literalPtr++, MIN(runLength, pixelCount - pixelNo)); + memset(outPtr + pixelNo, *rlePtr++, MIN(runLength, pixelCount - pixelNo)); pixelNo += runLength; break; case 0xC0: // fill with transparent @@ -404,12 +367,50 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou } } } else { - // literal stream only, so no compression - memcpy(outPtr, literalPtr, pixelCount); + literalPtr = _resourceData + celInfo->offsetLiteral; + if (celInfo->offsetRLE) { + if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { + // Crazy-Ass compression for SCI1.1+ Mac + while (pixelNo < pixelCount) { + uint32 pixelLine = pixelNo; + runLength = *rlePtr++; + pixelNo += runLength; + runLength = *rlePtr++; + while (runLength-- && pixelNo < pixelCount) { + outPtr[pixelNo] = *literalPtr++; + if (outPtr[pixelNo] == 255) + outPtr[pixelNo] = 0; + pixelNo++; + } + pixelNo = pixelLine + celInfo->width; + } + } else { + // decompression for data that has separate rle and literal streams + while (pixelNo < pixelCount) { + pixel = *rlePtr++; + runLength = pixel & 0x3F; + switch (pixel & 0xC0) { + case 0: // copy bytes as-is + while (runLength-- && pixelNo < pixelCount) + outPtr[pixelNo++] = *literalPtr++; + break; + case 0x80: // fill with color + memset(outPtr + pixelNo, *literalPtr++, MIN(runLength, pixelCount - pixelNo)); + pixelNo += runLength; + break; + case 0xC0: // fill with transparent + pixelNo += runLength; + break; + } + } + } + } else { + // literal stream only, so no compression + memcpy(outPtr, literalPtr, pixelCount); + pixelNo = pixelCount; + } } - return; } - error("Unable to decompress view"); } byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { @@ -425,9 +426,7 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { _loop[loopNo].cel[celNo].rawBitmap = new byte[pixelCount]; byte *pBitmap = _loop[loopNo].cel[celNo].rawBitmap; - // Some RLE compressed cels end with the last non-transparent pixel, thats why we fill it up here - // FIXME: change this to fill the remaining bytes within unpackCel() - memset(pBitmap, _loop[loopNo].cel[celNo].clearKey, pixelCount); + // unpack the actual cel bitmap data unpackCel(loopNo, celNo, pBitmap, pixelCount); if (!_resMan->isVGA()) { -- cgit v1.2.3 From ab4e02422cda7ba436c667bf4a3758a4588f170a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 17:43:13 +0000 Subject: SCI: free channels for channel remapping on stop and pause, instead of dispose - fixes qfg3 demo going out of channels svn-id: r50054 --- engines/sci/sound/music.cpp | 29 ++++++++++++++++++----------- engines/sci/sound/music.h | 1 + 2 files changed, 19 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index f6a4d5beb4..96257b1f9d 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -250,6 +250,14 @@ int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { error("no free channels"); } +void SciMusic::freeChannels(MusicEntry *caller) { + // Remove used channels + for (int i = 0; i < 15; i++) { + if (_usedChannel[i] == caller) + _usedChannel[i] = 0; + } +} + void SciMusic::onTimer() { const MusicList::iterator end = _playList.end(); for (MusicList::iterator i = _playList.begin(); i != end; ++i) @@ -334,10 +342,12 @@ void SciMusic::soundStop(MusicEntry *pSnd) { if (pSnd->pStreamAud) _pMixer->stopHandle(pSnd->hCurrentAud); - _mutex.lock(); - if (pSnd->pMidiParser) + if (pSnd->pMidiParser) { + _mutex.lock(); pSnd->pMidiParser->stop(); - _mutex.unlock(); + freeChannels(pSnd); + _mutex.unlock(); + } } void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { @@ -379,11 +389,6 @@ void SciMusic::soundKill(MusicEntry *pSnd) { _mutex.lock(); uint sz = _playList.size(), i; - // Remove used channels - for (i = 0; i < 15; i++) { - if (_usedChannel[i] == pSnd) - _usedChannel[i] = 0; - } // Remove sound from playlist for (i = 0; i < sz; i++) { if (_playList[i] == pSnd) { @@ -404,10 +409,12 @@ void SciMusic::soundPause(MusicEntry *pSnd) { if (pSnd->pStreamAud) { _pMixer->pauseHandle(pSnd->hCurrentAud, true); } else { - _mutex.lock(); - if (pSnd->pMidiParser) + if (pSnd->pMidiParser) { + _mutex.lock(); pSnd->pMidiParser->pause(); - _mutex.unlock(); + freeChannels(pSnd); + _mutex.unlock(); + } } } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 8e68d3df92..cd6dcbc317 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -195,6 +195,7 @@ public: Common::Mutex _mutex; int16 tryToOwnChannel(MusicEntry *caller, int16 bestChannel); + void freeChannels(MusicEntry *caller); protected: void sortPlayList(); -- cgit v1.2.3 From 996bd693e0ad45d5d5d599b6d5e320c1f52afe8a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 19:04:35 +0000 Subject: SCI: resume when unable to locate base objects - fixes loading some saved games svn-id: r50055 --- engines/sci/engine/savegame.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index eba5e67cb6..fb79056e0c 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -776,7 +776,7 @@ void SegManager::reconstructScripts(EngineState *s) { if (getSciVersion() < SCI_VERSION_1_1) { if (!obj->initBaseObject(this, addr, false)) { - error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); //scr->scriptObjRemove(addr); } } -- cgit v1.2.3 From ed50ecd62d21e728480710e64aea79c5d132ac77 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 19:06:58 +0000 Subject: SCI: make channel remapping stop using channel 0 for mt32 - fixes playback accordingly (like lsl1 at the start) svn-id: r50056 --- engines/sci/sound/drivers/midi.cpp | 8 ++++++++ engines/sci/sound/drivers/mididriver.h | 1 + engines/sci/sound/music.cpp | 5 ++++- engines/sci/sound/music.h | 2 ++ 4 files changed, 15 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index b97564342c..625874eea1 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -55,6 +55,7 @@ public: bool hasRhythmChannel() const { return true; } byte getPlayId(); int getPolyphony() const { return kVoices; } + int getFirstChannel(); void setVolume(byte volume); int getVolume(); void setReverb(byte reverb); @@ -317,6 +318,13 @@ void MidiPlayer_Midi::send(uint32 b) { } } +// We return 1 for mt32, because if we remap channels to 0 for mt32, those won't get played at all +int MidiPlayer_Midi::getFirstChannel() { + if (_isMt32) + return 1; + return 0; +} + void MidiPlayer_Midi::setVolume(byte volume) { _masterVolume = volume; diff --git a/engines/sci/sound/drivers/mididriver.h b/engines/sci/sound/drivers/mididriver.h index 12d3e57f5d..58803db260 100644 --- a/engines/sci/sound/drivers/mididriver.h +++ b/engines/sci/sound/drivers/mididriver.h @@ -86,6 +86,7 @@ public: virtual byte getPlayId() = 0; virtual int getPolyphony() const = 0; + virtual int getFirstChannel() { return 0; }; virtual void setVolume(byte volume) { if(_driver) diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 96257b1f9d..6e12ac7409 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -103,6 +103,9 @@ void SciMusic::init() { } _bMultiMidi = ConfMan.getBool("multi_midi"); + + // Find out what the first possible channel is (used, when doing channel remapping) + _driverFirstChannel = _pMidiDrv->getFirstChannel(); } void SciMusic::clearPlayList() { @@ -241,7 +244,7 @@ int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { return bestChannel; } // otherwise look for unused channel - for (int channelNr = 0; channelNr < 15; channelNr++) { + for (int channelNr = _driverFirstChannel; channelNr < 15; channelNr++) { if (!_usedChannel[channelNr]) { _usedChannel[channelNr] = caller; return channelNr; diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index cd6dcbc317..36db9a04bf 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -216,6 +216,8 @@ private: bool _soundOn; byte _masterVolume; MusicEntry *_usedChannel[16]; + + int _driverFirstChannel; }; } // End of namespace Sci -- cgit v1.2.3 From 447f1270139890877ecdc32c06138f88525e1458 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 19:16:42 +0000 Subject: SCI: fixing uninitialized usage in MidiParser_SCI svn-id: r50057 --- engines/sci/sound/midiparser_sci.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 931919b2b5..71d363d172 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -73,9 +73,6 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _pSnd = psnd; _soundVersion = soundVersion; - if (_pSnd) - setVolume(psnd->volume); - for (int i = 0; i < 15; i++) { _channelUsed[i] = false; _channelRemap[i] = -1; @@ -84,6 +81,9 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally + if (_pSnd) + setVolume(psnd->volume); + if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection midiFilterChannels(channelFilterMask); -- cgit v1.2.3 From a845e8b859e215a24e68bfbc5990153faf733548 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 19:39:36 +0000 Subject: SCI: move setVolume down inside loadMusic so that it actually affects the used channels svn-id: r50058 --- engines/sci/sound/midiparser_sci.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 71d363d172..18eaba3de6 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -81,9 +81,6 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally - if (_pSnd) - setVolume(psnd->volume); - if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection midiFilterChannels(channelFilterMask); @@ -91,6 +88,9 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in midiMixChannels(); } + if (_pSnd) + setVolume(_pSnd->volume); + _num_tracks = 1; _tracks[0] = _mixedData; if (_pSnd) -- cgit v1.2.3 From 24459b5842e6cf8ef906e81c9b43c36c657f1119 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 19:47:22 +0000 Subject: SCI: reverting r50058 - we can't actually send to the channels at that time, because we do not own the channels at that point svn-id: r50059 --- engines/sci/sound/midiparser_sci.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 18eaba3de6..99468fe09c 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -81,6 +81,10 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally + // we can't do this later, because otherwise we really send to unmapped channels + if (_pSnd) + setVolume(_pSnd->volume); + if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection midiFilterChannels(channelFilterMask); @@ -88,9 +92,6 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in midiMixChannels(); } - if (_pSnd) - setVolume(_pSnd->volume); - _num_tracks = 1; _tracks[0] = _mixedData; if (_pSnd) -- cgit v1.2.3 From 089f5bba1491be81cebc495a7e5245fe045da323 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 20:00:32 +0000 Subject: SCI: stopping scripts from sending to unused channels manually (fixes sq1vga) svn-id: r50060 --- engines/sci/sound/midiparser_sci.cpp | 20 +++++++++++++++----- engines/sci/sound/midiparser_sci.h | 1 + engines/sci/sound/music.cpp | 2 +- 3 files changed, 17 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 99468fe09c..1cfaadd36d 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -144,6 +144,20 @@ void MidiParser_SCI::unloadMusic() { } } +// this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually +// used +void MidiParser_SCI::sendManuallyToDriver(uint32 b) { + byte midiChannel = b & 0xf; + + if (!_channelUsed[midiChannel]) { + // scripts trying to send to unused channel + // this happens at least in sq1vga right at the start, it's a script issue + return; + } + + sendToDriver(b); +} + void MidiParser_SCI::sendToDriver(uint32 b) { byte midiChannel = b & 0xf; @@ -161,11 +175,7 @@ void MidiParser_SCI::sendToDriver(uint32 b) { return; // Channel remapping int16 realChannel = _channelRemap[midiChannel]; - if (realChannel == -1) { - // FIXME: Happens in SQ1VGA when the game starts - warning("Attempt to send to uninitialized channel %d", midiChannel); - return; - } + assert(realChannel != -1); b = (b & 0xFFFFFFF0) | realChannel; _driver->send(b); diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index abedafdde0..31a3b923fb 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -80,6 +80,7 @@ public: void sendToDriver(byte status, byte firstOp, byte secondOp) { sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); } + void sendManuallyToDriver(uint32 b); protected: void parseNextEvent(EventInfo &info); diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 6e12ac7409..8499b6da59 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -463,7 +463,7 @@ void SciMusic::sendMidiCommand(uint32 cmd) { void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { if (pSnd->pMidiParser) - pSnd->pMidiParser->sendToDriver(cmd); + pSnd->pMidiParser->sendManuallyToDriver(cmd); else error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); } -- cgit v1.2.3 From f3b8a5927d16da3a35a55069a9fe9d9e6500a2f8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 20:23:55 +0000 Subject: SCI: fixing another uninitialized variable usage issue - also limiting reset velocity to used channels only, same is true for setting voice count svn-id: r50062 --- engines/sci/sound/midiparser_sci.cpp | 28 ++++++++++++++-------------- engines/sci/sound/midiparser_sci.h | 1 + engines/sci/sound/music.cpp | 5 +++-- 3 files changed, 18 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 1cfaadd36d..61e9d81392 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -81,10 +81,6 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally - // we can't do this later, because otherwise we really send to unmapped channels - if (_pSnd) - setVolume(_pSnd->volume); - if (channelFilterMask) { // SCI0 only has 1 data stream, but we need to filter out channels depending on music hardware selection midiFilterChannels(channelFilterMask); @@ -98,24 +94,28 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in setTrack(0); _loopTick = 0; + return true; +} + +void MidiParser_SCI::sendInitCommands() { if (_pSnd) { if (_soundVersion <= SCI_VERSION_0_LATE) { // Set initial voice count - for (int i = 0; i < 16; ++i) { + for (int i = 0; i < 15; ++i) { byte voiceCount = 0; - if (channelFilterMask & (1 << i)) - voiceCount = psnd->soundRes->getInitialVoiceCount(i); - _driver->send(0xB0 | i, 0x4B, voiceCount); + if (_channelUsed[i]) { + voiceCount = _pSnd->soundRes->getInitialVoiceCount(i); + _driver->send(0xB0 | i, 0x4B, voiceCount); + } } } - - // Send a velocity off signal to all channels - for (int i = 0; i < 16; ++i) { - _driver->send(0xB0 | i, 0x4E, 0); // Reset velocity - } } - return true; + // Send a velocity off signal to all channels + for (int i = 0; i < 15; ++i) { + if (_channelUsed[i]) + sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity + } } void MidiParser_SCI::unloadMusic() { diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 31a3b923fb..48de44555d 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -59,6 +59,7 @@ public: bool loadMusic(byte *, uint32) { return false; } + void sendInitCommands(); void unloadMusic(); void setVolume(byte volume); void stop() { diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 8499b6da59..8da0557a31 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -326,9 +326,10 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if (pSnd->pMidiParser) { pSnd->pMidiParser->tryToOwnChannels(); pSnd->pMidiParser->setVolume(pSnd->volume); - if (pSnd->status == kSoundStopped) + if (pSnd->status == kSoundStopped) { + pSnd->pMidiParser->sendInitCommands(); pSnd->pMidiParser->jumpToTick(0); - else + } else // Fast forward to the last position and perform associated events when loading pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); } -- cgit v1.2.3 From ef67a37b5498fd256533369f2c8e531887d2b6f6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 20:37:53 +0000 Subject: SCI: fixing last uninitialized variable issue in MidiParser_SCI (hopefully) svn-id: r50063 --- engines/sci/sound/midiparser_sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 61e9d81392..31d9d95116 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -73,7 +73,7 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _pSnd = psnd; _soundVersion = soundVersion; - for (int i = 0; i < 15; i++) { + for (int i = 0; i < 16; i++) { _channelUsed[i] = false; _channelRemap[i] = -1; _channelMuted[i] = false; -- cgit v1.2.3 From b0a36849daaf02ba01e2a0603569b20a608250e0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 21:15:58 +0000 Subject: SCI: locking _mutex inside SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) svn-id: r50065 --- engines/sci/sound/music.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 8da0557a31..688b88a910 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -463,6 +463,7 @@ void SciMusic::sendMidiCommand(uint32 cmd) { } void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { + Common::StackLock lock(_mutex); if (pSnd->pMidiParser) pSnd->pMidiParser->sendManuallyToDriver(cmd); else -- cgit v1.2.3 From 87132bd411c760812ef2b5b65c11115d689de52b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 19 Jun 2010 22:14:15 +0000 Subject: SCI: changing error to warning in ResMan::detectViewType() svn-id: r50067 --- engines/sci/resource.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index a4eff573ab..745cad7029 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1756,7 +1756,8 @@ ViewType ResourceManager::detectViewType() { } } - error("resMan: Couldn't find any views"); + // this may happen if there are serious system issues (or trying to add a broken game) + warning("resMan: Couldn't find any views"); return kViewUnknown; } -- cgit v1.2.3 From d6cd656f15aed3ac3b8428442f9397944e6b2c85 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Jun 2010 05:25:34 +0000 Subject: Added support for the alternate encoding for depth surfaces svn-id: r50069 --- engines/m4/mads_scene.cpp | 30 +++++++++++++++++++++--------- engines/m4/mads_scene.h | 2 +- 2 files changed, 22 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 43b39af0db..8a33424602 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -650,7 +650,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su int resSceneId = stream->readUint16LE(); assert(resSceneId == sceneNumber); artFileNum = stream->readUint16LE(); - drawStyle = stream->readUint16LE(); + depthStyle = stream->readUint16LE(); width = stream->readUint16LE(); height = stream->readUint16LE(); @@ -685,16 +685,15 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su if (!surface) { surface = new M4Surface(width, height); ssFlag = true; - } + } else if ((width != surface->width()) || (height != surface->height())) + surface->setSize(width, height); + int walkSize = gfxSize; - if (drawStyle == 2) { - width >>= 2; - walkSize = width * height; - } if (!depthSurface) { depthSurface = new M4Surface(width, height); dsFlag = true; - } + } else if ((width != depthSurface->width()) || (height != depthSurface->height())) + depthSurface->setSize(width, height); // For Rex Nebular, read in the scene's compressed walk surface information @@ -708,9 +707,22 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su byte *destP = depthSurface->getBasePtr(0, 0); const byte *srcP = walkData; byte runLength; + + // Run length encoded depth data while ((runLength = *srcP++) != 0) { - Common::set_to(destP, destP + runLength, *srcP++); - destP += runLength; + if (depthStyle == 2) { + // 2-bit depth pixels + byte byteVal = *srcP++; + for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) { + byte v = byteVal; + for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2) + *destP++ = v & 3; + } + } else { + // 8-bit depth pixels + Common::set_to(destP, destP + runLength, *srcP++); + destP += runLength; + } } free(walkData); diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index c4c6dedc0e..ef5cd312d7 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -39,7 +39,7 @@ class MadsSceneResources: public SceneResources { public: int sceneId; int artFileNum; - int drawStyle; + int depthStyle; int width; int height; Common::Array objects; -- cgit v1.2.3 From fcdb7807a456f5a6cb94932977a1b0e4f0e11089 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Jun 2010 07:04:58 +0000 Subject: Implemented explicit transparency index support - the previous hardcoded index of 0 wasn't correct, since some sprites need that index svn-id: r50070 --- engines/m4/console.cpp | 2 +- engines/m4/events.cpp | 3 ++- engines/m4/graphics.cpp | 2 +- engines/m4/graphics.h | 1 + engines/m4/mads_anim.cpp | 2 +- engines/m4/mads_menus.cpp | 12 +++++++----- engines/m4/mads_scene.cpp | 2 +- engines/m4/mads_views.cpp | 8 +++++--- engines/m4/sprite.cpp | 15 ++++++++------- engines/m4/sprite.h | 2 +- 10 files changed, 28 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/m4/console.cpp b/engines/m4/console.cpp index 4e14afdfaf..19fbf6e852 100644 --- a/engines/m4/console.cpp +++ b/engines/m4/console.cpp @@ -196,7 +196,7 @@ bool Console::cmdShowSprite(int argc, const char **argv) { if (y >= bg->height()) break; - spr->copyTo(bg, x, y, (int)spr->getTransparentColor()); + spr->copyTo(bg, x, y, (int)spr->getTransparencyIndex()); x += spr->width(); yMax = MAX(yMax, spr->height()); diff --git a/engines/m4/events.cpp b/engines/m4/events.cpp index 65378c5d6a..c66609844a 100644 --- a/engines/m4/events.cpp +++ b/engines/m4/events.cpp @@ -256,7 +256,8 @@ bool Mouse::setCursorNum(int cursorIndex) { _cursor = _cursorSprites->getFrame(cursorIndex); // Set the cursor to the sprite - CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), _cursor->xOffset, _cursor->yOffset, 0); + CursorMan.replaceCursor((const byte *)_cursor->getBasePtr(), _cursor->width(), _cursor->height(), + _cursor->xOffset, _cursor->yOffset, TRANSPARENT_COLOUR_INDEX); return true; } diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index d7a0c9edfc..b0bc8bbc0c 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -919,7 +919,7 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { byte *palIndexes = list->palIndexes(); for (int i = 0; i < width() * height(); ++i, ++p) { - if (!isTransparent || (*p != 0)) { + if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) { assert(*p < list->size()); *p = palIndexes[*p]; } diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 24c0edf223..96cd039e27 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -40,6 +40,7 @@ namespace M4 { #define MADS_SCREEN_HEIGHT 200 #define MADS_Y_OFFSET ((MADS_SCREEN_HEIGHT - MADS_SURFACE_HEIGHT) / 2) +#define TRANSPARENT_COLOUR_INDEX 0xFF struct BGR8 { uint8 b, g, r; diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index c2e9ea4eee..fb565a927c 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -547,7 +547,7 @@ void AnimviewView::updateState() { } void AnimviewView::readNextCommand() { -static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes **** +static bool tempFlag = false;//****DEBUG - Temporarily allow me to skip several intro scenes **** while (!_script->eos() && !_script->err()) { if (!tempFlag) { diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index 43b9031692..d7d9cf4150 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -163,7 +163,7 @@ bool RexMainMenuView::onEvent(M4EventType eventType, int32 param, int x, int y, if (_highlightedIndex != -1) { M4Sprite *spr = _menuItem->getFrame(_highlightedIndex); const Common::Point &pt = _menuItemPosList[_highlightedIndex]; - spr->copyTo(this, pt.x, row + pt.y, 0); + spr->copyTo(this, pt.x, row + pt.y, spr->getTransparencyIndex()); } } } else { @@ -211,10 +211,12 @@ void RexMainMenuView::updateState() { M4Sprite *spr = _menuItem->getFrame(0); itemSize = _menuItem->getFrame(0)->height(); spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, - _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), 0); + _menuItemPosList[_menuItemIndex - 1].y + row + (itemSize / 2) - (spr->height() / 2), + spr->getTransparencyIndex()); delete _menuItem; - copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0); + copyTo(_bgSurface, Common::Rect(0, row, width(), row + MADS_SURFACE_HEIGHT), 0, 0, + spr->getTransparencyIndex()); } // Get the next sprite set @@ -275,7 +277,7 @@ void RexMainMenuView::updateState() { _bgSurface->copyTo(this, 0, row); M4Sprite *spr = _menuItem->getFrame(_frameIndex); spr->copyTo(this, _menuItemPosList[_menuItemIndex - 1].x, _menuItemPosList[_menuItemIndex - 1].y + - row + (itemSize / 2) - (spr->height() / 2), 0); + row + (itemSize / 2) - (spr->height() / 2), spr->getTransparencyIndex()); } int RexMainMenuView::getHighlightedItem(int x, int y) { @@ -531,7 +533,7 @@ void DragonMainMenuView::updateState() { _itemPalData.push_back(palData); spr = _menuItem->getFrame(1); - spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), (int)spr->getTransparentColor()); + spr->copyTo(this, spr->xOffset - 140, spr->yOffset - spr->height(), spr->getTransparencyIndex()); _vm->_mouse->cursorOn(); } diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 8a33424602..7e45b5f1f7 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -927,7 +927,7 @@ void MadsInterfaceView::onRefresh(RectList *rects, M4Surface *destSurface) { // Display object sprite. Note that the frame number isn't used directly, because it would result // in too fast an animation M4Sprite *spr = _objectSprites->getFrame(_objectFrameNumber / INV_ANIM_FRAME_SPEED); - spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, 0); + spr->copyTo(destSurface, INVENTORY_X, INVENTORY_Y, TRANSPARENT_COLOUR_INDEX); if (!_madsVm->globals()->_config.invObjectsStill && !dialogVisible) { // If objects need to be animated, move to the next frame diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 5a7abcf484..a644e81d51 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -196,7 +196,8 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { // Minimalised drawing assert(slot.spriteListIndex < (int)_sprites.size()); M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - view->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, slot.scale, 0); + view->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, + slot.scale, spr->getTransparencyIndex()); } else { int xp, yp; M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1); @@ -211,10 +212,11 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { if (slot.depth > 1) { // Draw the frame with depth processing - view->copyFrom(spr, xp, yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, 100, 0); + view->copyFrom(spr, xp, yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, 100, + spr->getTransparencyIndex()); } else { // No depth, so simply draw the image - spr->copyTo(view, xp, yp + yOffset, 0); + spr->copyTo(view, xp, yp + yOffset, spr->getTransparencyIndex()); } } } diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 0ff4bec855..da043c695f 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -131,6 +131,9 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { byte cmd1, cmd2, count, pixel; if (newLine) { + if (outp < (lineStart + w)) + Common::set_to(outp, lineStart + w, TRANSPARENT_COLOUR_INDEX); + outp = lineStart + w; lineStart = outp; newLine = false; @@ -150,7 +153,7 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { } else { pixel = source->readByte(); while (count--) - *outp++ = (pixel == 0xFD) ? 0 : pixel; + *outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel; } } } else { @@ -162,19 +165,17 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { count = source->readByte(); pixel = source->readByte(); while (count--) - *outp++ = (pixel == 0xFD) ? 0 : pixel; + *outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel; } else { - *outp++ = (cmd2 == 0xFD) ? 0 : cmd2; + *outp++ = (cmd2 == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd2; } } } } } -byte M4Sprite::getTransparentColor() const { - // FIXME: We assume that the transparent color is the color of the - // top left pixel. - return *getBasePtr(0, 0); +byte M4Sprite::getTransparencyIndex() const { + return TRANSPARENT_COLOUR_INDEX; } } // End of namespace M4 diff --git a/engines/m4/sprite.h b/engines/m4/sprite.h index 49a96a6c4a..d4e5502efd 100644 --- a/engines/m4/sprite.h +++ b/engines/m4/sprite.h @@ -115,7 +115,7 @@ public: void loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int destY); void loadMadsSprite(Common::SeekableReadStream* source); - byte getTransparentColor() const; + byte getTransparencyIndex() const; protected: }; -- cgit v1.2.3 From 110e03c87b65330ef1ac105ddfca55bb1ac1d4ac Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 20 Jun 2010 07:06:22 +0000 Subject: Removed unused variables svn-id: r50071 --- engines/m4/mads_scene.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 7e45b5f1f7..a464438981 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -681,14 +681,12 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su // Initialise a copy of the surfaces if they weren't provided bool dsFlag = false, ssFlag = false; - int gfxSize = width * height; if (!surface) { surface = new M4Surface(width, height); ssFlag = true; } else if ((width != surface->width()) || (height != surface->height())) surface->setSize(width, height); - int walkSize = gfxSize; if (!depthSurface) { depthSurface = new M4Surface(width, height); dsFlag = true; -- cgit v1.2.3 From 41990883bf003ff075821bc484b605b1ba87c8ad Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 20 Jun 2010 09:51:11 +0000 Subject: Don't go into "menu input mode" unless the game currently allows the menus to be displayed. I hope this is the correct fix to keep Police Quest 1 from hanging if you press Escape while reading the newspaper in the briefing room. svn-id: r50072 --- engines/agi/cycle.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/agi/cycle.cpp b/engines/agi/cycle.cpp index ee55c783f1..c185c3efb3 100644 --- a/engines/agi/cycle.cpp +++ b/engines/agi/cycle.cpp @@ -178,6 +178,9 @@ void AgiEngine::updateTimer() { } void AgiEngine::newInputMode(InputMode mode) { + if (mode == INPUT_MENU && !getflag(fMenusWork) && !(getFeatures() & GF_MENUS)) + return; + _oldMode = _game.inputMode; _game.inputMode = mode; } -- cgit v1.2.3 From 81f64c9e3e8cacf106c36eff2f443f29ed1f50c3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 10:25:46 +0000 Subject: SCI: storing all manual midi commands now and actually sending them to driver during onTimer() - fixes mt32 emulation crashing during lsl5 piano scene svn-id: r50073 --- engines/sci/sound/midiparser_sci.cpp | 50 ++++++++++++++++++++++-------------- engines/sci/sound/midiparser_sci.h | 10 +++++++- engines/sci/sound/music.cpp | 4 ++- 3 files changed, 43 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 31d9d95116..640000235e 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -61,6 +61,8 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : _dataincToAdd = 0; _resetOnPause = false; _pSnd = 0; + + _manualCommandCount = 0; } MidiParser_SCI::~MidiParser_SCI() { @@ -105,7 +107,7 @@ void MidiParser_SCI::sendInitCommands() { byte voiceCount = 0; if (_channelUsed[i]) { voiceCount = _pSnd->soundRes->getInitialVoiceCount(i); - _driver->send(0xB0 | i, 0x4B, voiceCount); + sendToDriverQueue(0xB0 | i, 0x4B, voiceCount); } } } @@ -113,8 +115,7 @@ void MidiParser_SCI::sendInitCommands() { // Send a velocity off signal to all channels for (int i = 0; i < 15; ++i) { - if (_channelUsed[i]) - sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity + sendToDriverQueue(0xB0 | i, 0x4E, 0); // Reset velocity } } @@ -145,17 +146,33 @@ void MidiParser_SCI::unloadMusic() { } // this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually -// used -void MidiParser_SCI::sendManuallyToDriver(uint32 b) { +// used and actually store the command for getting really sent when being onTimer() +void MidiParser_SCI::sendToDriverQueue(uint32 b) { byte midiChannel = b & 0xf; if (!_channelUsed[midiChannel]) { - // scripts trying to send to unused channel - // this happens at least in sq1vga right at the start, it's a script issue + // trying to send to an unused channel + // this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue return; } - sendToDriver(b); + if (_manualCommandCount >= 200) + error("driver queue is full"); + _manualCommands[_manualCommandCount] = b; + _manualCommandCount++; +} + +// This sends the stored commands from queue to driver (is supposed to get called only during onTimer()) +// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get +// a crash during piano scene in lsl5) +void MidiParser_SCI::sendQueueToDriver() { + int curCommand = 0; + + while (curCommand < _manualCommandCount) { + sendToDriver(_manualCommands[curCommand]); + curCommand++; + } + _manualCommandCount = 0; } void MidiParser_SCI::sendToDriver(uint32 b) { @@ -375,9 +392,8 @@ void MidiParser_SCI::allNotesOff() { // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { - int16 realChannel = _channelRemap[j]; - if ((_active_notes[i] & (1 << j)) && realChannel != -1){ - _driver->send(0x80 | realChannel, i, 0); + if ((_active_notes[i] & (1 << j))){ + sendToDriverQueue(0x80 | j, i, 0); } } } @@ -385,7 +401,7 @@ void MidiParser_SCI::allNotesOff() { // Turn off all hanging notes for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { if (_hanging_notes[i].time_left) { - _driver->send(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); + sendToDriverQueue(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); _hanging_notes[i].time_left = 0; } } @@ -394,11 +410,8 @@ void MidiParser_SCI::allNotesOff() { // To be sure, send an "All Note Off" event (but not all MIDI devices // support this...). - for (i = 0; i < 16; ++i) { - int16 realChannel = _channelRemap[i]; - if (realChannel != -1) - _driver->send(0xB0 | realChannel, 0x7b, 0); // All notes off - } + for (i = 0; i < 16; ++i) + sendToDriverQueue(0xB0 | i, 0x7b, 0); // All notes off memset(_active_notes, 0, sizeof(_active_notes)); } @@ -659,8 +672,7 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_LATE: // sending volume change to all used channels for (int i = 0; i < 15; i++) - if (_channelUsed[i]) - sendToDriver(0xB0 + i, 7, _volume); + sendToDriverQueue(0xB0 + i, 7, _volume); break; default: diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 48de44555d..5abffdb3a1 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -81,7 +81,12 @@ public: void sendToDriver(byte status, byte firstOp, byte secondOp) { sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); } - void sendManuallyToDriver(uint32 b); + void sendToDriverQueue(uint32 b); + void sendToDriverQueue(byte status, byte firstOp, byte secondOp) { + sendToDriverQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); + } + + void sendQueueToDriver(); protected: void parseNextEvent(EventInfo &info); @@ -107,6 +112,9 @@ protected: bool _channelUsed[16]; int16 _channelRemap[16]; bool _channelMuted[16]; + + int _manualCommandCount; + uint32 _manualCommands[200]; }; } // End of namespace Sci diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 688b88a910..fbf37a78b1 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -465,7 +465,7 @@ void SciMusic::sendMidiCommand(uint32 cmd) { void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { Common::StackLock lock(_mutex); if (pSnd->pMidiParser) - pSnd->pMidiParser->sendManuallyToDriver(cmd); + pSnd->pMidiParser->sendToDriverQueue(cmd); else error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); } @@ -573,6 +573,8 @@ void MusicEntry::onTimer() { // Only process MIDI streams in this thread, not digital sound effects if (pMidiParser) { + // Process manual commands first + pMidiParser->sendQueueToDriver(); pMidiParser->onTimer(); ticker = (uint16)pMidiParser->getTick(); } -- cgit v1.2.3 From 36ca2ce421d1dfbf6517d6ea008bbd97b9f6ccb8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 12:21:57 +0000 Subject: SCI: some cleanup for kPalVary svn-id: r50074 --- engines/sci/graphics/palette.cpp | 13 +++++++------ engines/sci/graphics/palette.h | 4 ++-- 2 files changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 8af6b597d6..fbf3433c29 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -464,14 +464,14 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { // Saving/restoring // need to save start and target-palette, when palVaryOn = true -void GfxPalette::startPalVary(uint16 paletteId, uint16 ticks) { - kernelSetFromResource(paletteId, true); +void GfxPalette::startPalVary(GuiResourceId resourceId, uint16 ticks) { + kernelSetFromResource(resourceId, true); return; - if (_palVaryId >= 0) // another palvary is taking place, return + if (_palVaryResourceId >= 0) // another palvary is taking place, return return; - _palVaryId = paletteId; + _palVaryResourceId = resourceId; _palVaryStart = g_system->getMillis(); _palVaryEnd = _palVaryStart + ticks * 1000 / 60; g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60, this); @@ -486,10 +486,11 @@ void GfxPalette::togglePalVary(bool pause) { void GfxPalette::stopPalVary() { g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); - _palVaryId = -1; // invalidate the target palette // HACK: just set the target palette - kernelSetFromResource(_palVaryId, true); + kernelSetFromResource(_palVaryResourceId, true); + + _palVaryResourceId = -1; // invalidate the target palette } void GfxPalette::palVaryCallback(void *refCon) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index fead340090..265f36ad54 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -60,7 +60,7 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - void startPalVary(uint16 paletteId, uint16 ticks); + void startPalVary(GuiResourceId resourceId, uint16 ticks); void togglePalVary(bool pause); void stopPalVary(); @@ -72,7 +72,7 @@ private: GfxScreen *_screen; ResourceManager *_resMan; - int16 _palVaryId; + GuiResourceId _palVaryResourceId; uint32 _palVaryStart; uint32 _palVaryEnd; -- cgit v1.2.3 From daf1429ca22e887d49e761304e60b47f46e97bbf Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 12:38:08 +0000 Subject: SCI: implementing reading of parameters for kPalVary(init) for argc 4 and argc 5 svn-id: r50075 --- engines/sci/engine/kgraphics.cpp | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 6e0dab7e28..344d79b9d2 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -646,12 +646,14 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // Init GuiResourceId paletteId; - uint16 time; - if (argc == 3) { + uint16 ticks, paletteStop, paletteDirection; + if ((argc >= 3) && (argc <= 5)) { paletteId = argv[1].toUint16(); - time = argv[2].toUint16(); - g_sci->_gfxPalette->startPalVary(paletteId, time); - warning("kPalVary(init) called with paletteId = %d, time = %d", paletteId, time); + ticks = argv[2].toUint16(); + paletteStop = argc >= 4 ? argv[3].toUint16() : 64; + paletteDirection = argc >= 5 ? argv[4].toUint16() : 1; + g_sci->_gfxPalette->startPalVary(paletteId, ticks); + warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, paletteStop, paletteDirection); } else { warning("kPalVary(init) called with unsupported argc %d", argc); } -- cgit v1.2.3 From 871c9bdddeaee6756f5c8d943c2ff8ed337abd4d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 13:15:45 +0000 Subject: SCI: removing unneeded parameters inside SciPalette, cleanup of SciPalette svn-id: r50076 --- engines/sci/graphics/cursor.cpp | 2 +- engines/sci/graphics/palette.cpp | 62 ++++++++++++++++++++-------------------- engines/sci/graphics/palette.h | 4 +-- 3 files changed, 34 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 369549cf7b..db42dac3dd 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -120,7 +120,7 @@ void GfxCursor::kernelSetShape(GuiResourceId resourceId) { colorMapping[0] = 0; // Black is hardcoded colorMapping[1] = _screen->getColorWhite(); // White is also hardcoded colorMapping[2] = SCI_CURSOR_SCI0_TRANSPARENCYCOLOR; - colorMapping[3] = _palette->matchColor(&_palette->_sysPalette, 170, 170, 170); // Grey + colorMapping[3] = _palette->matchColor(170, 170, 170); // Grey // Seek to actual data resourceData += 4; diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index fbf3433c29..7fa76586ad 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -207,12 +207,12 @@ void GfxPalette::setEGA() { setOnScreen(); } -void GfxPalette::set(Palette *sciPal, bool force, bool forceRealMerge) { +void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { uint32 systime = _sysPalette.timestamp; - if (force || sciPal->timestamp != systime) { - _sysPaletteChanged |= merge(sciPal, &_sysPalette, force, forceRealMerge); - sciPal->timestamp = _sysPalette.timestamp; + if (force || newPalette->timestamp != systime) { + _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); + newPalette->timestamp = _sysPalette.timestamp; if (_sysPaletteChanged && _screen->_picNotValid == 0) { // && systime != _sysPalette.timestamp) { // Removed timestamp checking, because this shouldnt be needed anymore. I'm leaving it commented just in // case this causes regressions @@ -222,7 +222,7 @@ void GfxPalette::set(Palette *sciPal, bool force, bool forceRealMerge) { } } -bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge) { +bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { uint16 res; int i,j; bool paletteChanged = false; @@ -234,13 +234,13 @@ bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealM // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes for (i = 1; i < 255; i++) { if (pFrom->colors[i].used) { - if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) { - pTo->colors[i].r = pFrom->colors[i].r; - pTo->colors[i].g = pFrom->colors[i].g; - pTo->colors[i].b = pFrom->colors[i].b; + if ((pFrom->colors[i].r != _sysPalette.colors[i].r) || (pFrom->colors[i].g != _sysPalette.colors[i].g) || (pFrom->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = pFrom->colors[i].r; + _sysPalette.colors[i].g = pFrom->colors[i].g; + _sysPalette.colors[i].b = pFrom->colors[i].b; paletteChanged = true; } - pTo->colors[i].used = pFrom->colors[i].used; + _sysPalette.colors[i].used = pFrom->colors[i].used; pFrom->mapping[i] = i; } } @@ -250,12 +250,12 @@ bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealM if (!pFrom->colors[i].used)// color is not used - so skip it continue; // forced palette merging or dest color is not used yet - if (force || (!pTo->colors[i].used)) { - pTo->colors[i].used = pFrom->colors[i].used; - if ((pFrom->colors[i].r != pTo->colors[i].r) || (pFrom->colors[i].g != pTo->colors[i].g) || (pFrom->colors[i].b != pTo->colors[i].b)) { - pTo->colors[i].r = pFrom->colors[i].r; - pTo->colors[i].g = pFrom->colors[i].g; - pTo->colors[i].b = pFrom->colors[i].b; + if (force || (!_sysPalette.colors[i].used)) { + _sysPalette.colors[i].used = pFrom->colors[i].used; + if ((pFrom->colors[i].r != _sysPalette.colors[i].r) || (pFrom->colors[i].g != _sysPalette.colors[i].g) || (pFrom->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = pFrom->colors[i].r; + _sysPalette.colors[i].g = pFrom->colors[i].g; + _sysPalette.colors[i].b = pFrom->colors[i].b; paletteChanged = true; } pFrom->mapping[i] = i; @@ -264,23 +264,23 @@ bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealM // is the same color already at the same position? -> match it directly w/o lookup // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) - if ((pTo->colors[i].r == pFrom->colors[i].r) && (pTo->colors[i].g == pFrom->colors[i].g) && (pTo->colors[i].b == pFrom->colors[i].b)) { + if ((_sysPalette.colors[i].r == pFrom->colors[i].r) && (_sysPalette.colors[i].g == pFrom->colors[i].g) && (_sysPalette.colors[i].b == pFrom->colors[i].b)) { pFrom->mapping[i] = i; continue; } // check if exact color could be matched - res = matchColor(pTo, pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b); + res = matchColor(pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b); if (res & 0x8000) { // exact match was found pFrom->mapping[i] = res & 0xFF; continue; } // no exact match - see if there is an unused color for (j = 1; j < 256; j++) - if (!pTo->colors[j].used) { - pTo->colors[j].used = pFrom->colors[i].used; - pTo->colors[j].r = pFrom->colors[i].r; - pTo->colors[j].g = pFrom->colors[i].g; - pTo->colors[j].b = pFrom->colors[i].b; + if (!_sysPalette.colors[j].used) { + _sysPalette.colors[j].used = pFrom->colors[i].used; + _sysPalette.colors[j].r = pFrom->colors[i].r; + _sysPalette.colors[j].g = pFrom->colors[i].g; + _sysPalette.colors[j].b = pFrom->colors[i].b; pFrom->mapping[i] = j; paletteChanged = true; break; @@ -288,25 +288,25 @@ bool GfxPalette::merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealM // if still no luck - set an approximate color if (j == 256) { pFrom->mapping[i] = res & 0xFF; - pTo->colors[res & 0xFF].used |= 0x10; + _sysPalette.colors[res & 0xFF].used |= 0x10; } } } - pTo->timestamp = g_system->getMillis() * 60 / 1000; + _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; return paletteChanged; } -uint16 GfxPalette::matchColor(Palette *pPal, byte r, byte g, byte b) { +uint16 GfxPalette::matchColor(byte r, byte g, byte b) { byte found = 0xFF; int diff = 0x2FFFF, cdiff; int16 dr,dg,db; for (int i = 1; i < 255; i++) { - if ((!pPal->colors[i].used)) + if ((!_sysPalette.colors[i].used)) continue; - dr = pPal->colors[i].r - r; - dg = pPal->colors[i].g - g; - db = pPal->colors[i].b - b; + dr = _sysPalette.colors[i].r - r; + dg = _sysPalette.colors[i].g - g; + db = _sysPalette.colors[i].b - b; // minimum squares match cdiff = (dr*dr) + (dg*dg) + (db*db); // minimum sum match (Sierra's) @@ -372,7 +372,7 @@ void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 int } int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) { - return matchColor(&_sysPalette, r, g, b) & 0xFF; + return matchColor(r, g, b) & 0xFF; } // Returns true, if palette got changed diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 265f36ad54..b7767537a1 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -45,8 +45,8 @@ public: void modifyAmigaPalette(byte *data); void setEGA(); void set(Palette *sciPal, bool force, bool forceRealMerge = false); - bool merge(Palette *pFrom, Palette *pTo, bool force, bool forceRealMerge); - uint16 matchColor(Palette *pPal, byte r, byte g, byte b); + bool merge(Palette *pFrom, bool force, bool forceRealMerge); + uint16 matchColor(byte r, byte g, byte b); void getSys(Palette *pal); void setOnScreen(); -- cgit v1.2.3 From 30f6e7824bad89293db3a43b6d67657862a03c51 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 13:25:08 +0000 Subject: SCI: update sys palette timestamp only on kDrawPic in SCI1.1, fixes intro of island of dr. brain svn-id: r50077 --- engines/sci/graphics/paint16.cpp | 4 ++++ engines/sci/graphics/palette.cpp | 10 +++++++++- engines/sci/graphics/palette.h | 2 ++ 3 files changed, 15 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index f9ee3c3ae3..63e7d30ca0 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -75,6 +75,10 @@ void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mi picture->draw(animationNr, mirroredFlag, addToFlag, paletteId); delete picture; + + // We update our sys palette timestamp here (SCI1.1 only) + if (getSciVersion() == SCI_VERSION_1_1) + _palette->increaseSysTimestamp(); } // This one is the only one that updates screen! diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 7fa76586ad..447ad23ebe 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -292,10 +292,18 @@ bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { } } } - _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; + + // We don't update the timestamp here for SCI1.1, it's only updated on kDrawPic calls + if (getSciVersion() < SCI_VERSION_1_1) + _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; return paletteChanged; } +// This is used for SCI1.1 and called from kDrawPic. We only update sysPalette timestamp this way for SCI1.1 +void GfxPalette::increaseSysTimestamp() { + _sysPalette.timestamp++; +} + uint16 GfxPalette::matchColor(byte r, byte g, byte b) { byte found = 0xFF; int diff = 0x2FFFF, cdiff; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index b7767537a1..53eb97e6a1 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -51,6 +51,8 @@ public: void setOnScreen(); + void increaseSysTimestamp(); + bool kernelSetFromResource(GuiResourceId resourceId, bool force); void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag); void kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag); -- cgit v1.2.3 From d2a3f59bfb5d27c5524a4bd59a789378f7bd09e6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 13:30:40 +0000 Subject: SCI: update timestamp like before for inbetween SCI1.1 games svn-id: r50078 --- engines/sci/graphics/palette.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 447ad23ebe..9058680c46 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -244,6 +244,9 @@ bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { pFrom->mapping[i] = i; } } + // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls + return paletteChanged; + } else { // colors 0 (black) and 255 (white) are not affected by merging for (i = 1 ; i < 255; i++) { @@ -293,15 +296,15 @@ bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { } } - // We don't update the timestamp here for SCI1.1, it's only updated on kDrawPic calls - if (getSciVersion() < SCI_VERSION_1_1) + if (!forceRealMerge) _sysPalette.timestamp = g_system->getMillis() * 60 / 1000; return paletteChanged; } // This is used for SCI1.1 and called from kDrawPic. We only update sysPalette timestamp this way for SCI1.1 void GfxPalette::increaseSysTimestamp() { - _sysPalette.timestamp++; + if (!_alwaysForceRealMerge) // Don't do this on inbetween SCI1.1 games + _sysPalette.timestamp++; } uint16 GfxPalette::matchColor(byte r, byte g, byte b) { -- cgit v1.2.3 From 15ae4d8f595346dffde8be6b186fc696f28c8900 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 13:38:24 +0000 Subject: SCI: fix r50078, we need to update timestamp for inbetween SCI1.1 games, but not on kPortrait palette changes svn-id: r50079 --- engines/sci/graphics/palette.cpp | 56 +++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 9058680c46..56e2ff67a2 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -222,26 +222,24 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } -bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { +bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { uint16 res; int i,j; bool paletteChanged = false; - // for Laura Bow 2 demo - forceRealMerge |= _alwaysForceRealMerge; - - if ((!forceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { + if ((!forceRealMerge) && (!_alwaysForceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes + // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo) for (i = 1; i < 255; i++) { - if (pFrom->colors[i].used) { - if ((pFrom->colors[i].r != _sysPalette.colors[i].r) || (pFrom->colors[i].g != _sysPalette.colors[i].g) || (pFrom->colors[i].b != _sysPalette.colors[i].b)) { - _sysPalette.colors[i].r = pFrom->colors[i].r; - _sysPalette.colors[i].g = pFrom->colors[i].g; - _sysPalette.colors[i].b = pFrom->colors[i].b; + if (newPalette->colors[i].used) { + if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = newPalette->colors[i].r; + _sysPalette.colors[i].g = newPalette->colors[i].g; + _sysPalette.colors[i].b = newPalette->colors[i].b; paletteChanged = true; } - _sysPalette.colors[i].used = pFrom->colors[i].used; - pFrom->mapping[i] = i; + _sysPalette.colors[i].used = newPalette->colors[i].used; + newPalette->mapping[i] = i; } } // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls @@ -250,47 +248,47 @@ bool GfxPalette::merge(Palette *pFrom, bool force, bool forceRealMerge) { } else { // colors 0 (black) and 255 (white) are not affected by merging for (i = 1 ; i < 255; i++) { - if (!pFrom->colors[i].used)// color is not used - so skip it + if (!newPalette->colors[i].used)// color is not used - so skip it continue; // forced palette merging or dest color is not used yet if (force || (!_sysPalette.colors[i].used)) { - _sysPalette.colors[i].used = pFrom->colors[i].used; - if ((pFrom->colors[i].r != _sysPalette.colors[i].r) || (pFrom->colors[i].g != _sysPalette.colors[i].g) || (pFrom->colors[i].b != _sysPalette.colors[i].b)) { - _sysPalette.colors[i].r = pFrom->colors[i].r; - _sysPalette.colors[i].g = pFrom->colors[i].g; - _sysPalette.colors[i].b = pFrom->colors[i].b; + _sysPalette.colors[i].used = newPalette->colors[i].used; + if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = newPalette->colors[i].r; + _sysPalette.colors[i].g = newPalette->colors[i].g; + _sysPalette.colors[i].b = newPalette->colors[i].b; paletteChanged = true; } - pFrom->mapping[i] = i; + newPalette->mapping[i] = i; continue; } // is the same color already at the same position? -> match it directly w/o lookup // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) - if ((_sysPalette.colors[i].r == pFrom->colors[i].r) && (_sysPalette.colors[i].g == pFrom->colors[i].g) && (_sysPalette.colors[i].b == pFrom->colors[i].b)) { - pFrom->mapping[i] = i; + if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) { + newPalette->mapping[i] = i; continue; } // check if exact color could be matched - res = matchColor(pFrom->colors[i].r, pFrom->colors[i].g, pFrom->colors[i].b); + res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); if (res & 0x8000) { // exact match was found - pFrom->mapping[i] = res & 0xFF; + newPalette->mapping[i] = res & 0xFF; continue; } // no exact match - see if there is an unused color for (j = 1; j < 256; j++) if (!_sysPalette.colors[j].used) { - _sysPalette.colors[j].used = pFrom->colors[i].used; - _sysPalette.colors[j].r = pFrom->colors[i].r; - _sysPalette.colors[j].g = pFrom->colors[i].g; - _sysPalette.colors[j].b = pFrom->colors[i].b; - pFrom->mapping[i] = j; + _sysPalette.colors[j].used = newPalette->colors[i].used; + _sysPalette.colors[j].r = newPalette->colors[i].r; + _sysPalette.colors[j].g = newPalette->colors[i].g; + _sysPalette.colors[j].b = newPalette->colors[i].b; + newPalette->mapping[i] = j; paletteChanged = true; break; } // if still no luck - set an approximate color if (j == 256) { - pFrom->mapping[i] = res & 0xFF; + newPalette->mapping[i] = res & 0xFF; _sysPalette.colors[res & 0xFF].used |= 0x10; } } -- cgit v1.2.3 From 7ce739f51b1556e211bffc3f82617013afe23cb8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 15:01:31 +0000 Subject: SCI: kPalVary - cleanup and some more code svn-id: r50081 --- engines/sci/engine/kgraphics.cpp | 6 +++--- engines/sci/graphics/animate.cpp | 4 ++++ engines/sci/graphics/palette.cpp | 40 +++++++++++++++++++++++++++++----------- engines/sci/graphics/palette.h | 13 +++++++++---- 4 files changed, 45 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 344d79b9d2..da0f533709 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -652,7 +652,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { ticks = argv[2].toUint16(); paletteStop = argc >= 4 ? argv[3].toUint16() : 64; paletteDirection = argc >= 5 ? argv[4].toUint16() : 1; - g_sci->_gfxPalette->startPalVary(paletteId, ticks); + g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks); warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, paletteStop, paletteDirection); } else { warning("kPalVary(init) called with unsupported argc %d", argc); @@ -670,7 +670,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } case 3: { // DeInit if (argc == 1) { - g_sci->_gfxPalette->stopPalVary(); + g_sci->_gfxPalette->kernelPalVaryDeinit(); warning("kPalVary(deinit)"); } else { warning("kPalVary(deinit) called with unsupported argc %d", argc); @@ -690,7 +690,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { bool pauseState; if (argc == 2) { pauseState = argv[1].isNull() ? false : true; - g_sci->_gfxPalette->togglePalVary(pauseState); + g_sci->_gfxPalette->kernelPalVaryToggle(pauseState); warning("kPalVary(pause) called with state = %d", pauseState); } else { warning("kPalVary(pause) called with unsupported argc %d", argc); diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 06054f3a19..339132a76c 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -35,6 +35,7 @@ #include "sci/graphics/cursor.h" #include "sci/graphics/ports.h" #include "sci/graphics/paint16.h" +#include "sci/graphics/palette.h" #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/transitions.h" @@ -592,6 +593,9 @@ void GfxAnimate::animateShowPic() { void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv) { byte old_picNotValid = _screen->_picNotValid; + if (getSciVersion() >= SCI_VERSION_1_1) + _palette->palVaryUpdate(); + if (listReference.isNull()) { disposeLastCast(); if (_screen->_picNotValid) diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 56e2ff67a2..5a0a661a56 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -72,6 +72,8 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _alwaysForceRealMerge = true; else if (g_sci->getGameId() == "pq1sci") _alwaysForceRealMerge = true; + + palVaryInit(); } GfxPalette::~GfxPalette() { @@ -473,7 +475,7 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { // Saving/restoring // need to save start and target-palette, when palVaryOn = true -void GfxPalette::startPalVary(GuiResourceId resourceId, uint16 ticks) { +void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks) { kernelSetFromResource(resourceId, true); return; @@ -481,19 +483,23 @@ void GfxPalette::startPalVary(GuiResourceId resourceId, uint16 ticks) { return; _palVaryResourceId = resourceId; - _palVaryStart = g_system->getMillis(); - _palVaryEnd = _palVaryStart + ticks * 1000 / 60; - g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60, this); + _palVarySignal = 0; + // Call signal increase every [ticks] + g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); } -void GfxPalette::togglePalVary(bool pause) { +void GfxPalette::kernelPalVaryToggle(bool pause) { // this call is actually counting states, so calling this 3 times with true will require calling it later // 3 times with false to actually remove pause - - // TODO + if (pause) { + _palVaryPaused++; + } else { + if (_palVaryPaused) + _palVaryPaused--; + } } -void GfxPalette::stopPalVary() { +void GfxPalette::kernelPalVaryDeinit() { g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); // HACK: just set the target palette @@ -502,12 +508,24 @@ void GfxPalette::stopPalVary() { _palVaryResourceId = -1; // invalidate the target palette } +void GfxPalette::palVaryInit() { + _palVaryResourceId = -1; + _palVaryPaused = 0; + _palVarySignal = 0; +} + void GfxPalette::palVaryCallback(void *refCon) { - ((GfxPalette *)refCon)->doPalVary(); + ((GfxPalette *)refCon)->palVaryIncreaseSignal(); +} + +void GfxPalette::palVaryIncreaseSignal() { + if (!_palVaryPaused) + _palVarySignal++; } -void GfxPalette::doPalVary() { - // TODO: do palette transition here... +// Actually do the pal vary processing +void GfxPalette::palVaryUpdate() { + } } // End of namespace Sci diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 53eb97e6a1..af649015d5 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -62,21 +62,26 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - void startPalVary(GuiResourceId resourceId, uint16 ticks); - void togglePalVary(bool pause); - void stopPalVary(); + void kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks); + void kernelPalVaryToggle(bool pause); + void kernelPalVaryDeinit(); + void palVaryUpdate(); Palette _sysPalette; private: + void palVaryInit(); static void palVaryCallback(void *refCon); - void doPalVary(); + void palVaryIncreaseSignal(); GfxScreen *_screen; ResourceManager *_resMan; + GuiResourceId _palVaryResourceId; uint32 _palVaryStart; uint32 _palVaryEnd; + int _palVaryPaused; + int _palVarySignal; bool _sysPaletteChanged; bool _alwaysForceRealMerge; -- cgit v1.2.3 From b016c16300577ae29d5a78e5be532cef3d4e21ce Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 16:31:24 +0000 Subject: SCI: some kPalVary support - intro of island dr. brain works fine now svn-id: r50082 --- engines/sci/engine/kgraphics.cpp | 11 ++--- engines/sci/graphics/palette.cpp | 91 +++++++++++++++++++++++++++++++++------- engines/sci/graphics/palette.h | 18 ++++---- 3 files changed, 94 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index da0f533709..f011f0e2d6 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -646,14 +646,15 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { switch (operation) { case 0: { // Init GuiResourceId paletteId; - uint16 ticks, paletteStop, paletteDirection; + uint16 ticks, stepStop; + int16 direction; if ((argc >= 3) && (argc <= 5)) { paletteId = argv[1].toUint16(); ticks = argv[2].toUint16(); - paletteStop = argc >= 4 ? argv[3].toUint16() : 64; - paletteDirection = argc >= 5 ? argv[4].toUint16() : 1; - g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks); - warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, paletteStop, paletteDirection); + stepStop = argc >= 4 ? argv[3].toUint16() : 64; + direction = argc >= 5 ? argv[4].toUint16() : 1; + g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction); + warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, stepStop, direction); } else { warning("kPalVary(init) called with unsupported argc %d", argc); } diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 5a0a661a56..68483ac954 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -212,6 +212,10 @@ void GfxPalette::setEGA() { void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { uint32 systime = _sysPalette.timestamp; + // Pal-Vary is taking place -> abort merge + if (_palVaryResourceId != -1) + return; + if (force || newPalette->timestamp != systime) { _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); newPalette->timestamp = _sysPalette.timestamp; @@ -475,17 +479,36 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { // Saving/restoring // need to save start and target-palette, when palVaryOn = true -void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks) { - kernelSetFromResource(resourceId, true); - return; +void GfxPalette::palVaryInit() { + _palVaryResourceId = -1; + _palVaryPaused = 0; + _palVarySignal = 0; + _palVaryStep = 0; + _palVaryStepStop = 0; + _palVaryDirection = 0; +} - if (_palVaryResourceId >= 0) // another palvary is taking place, return +void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, int16 direction) { + //kernelSetFromResource(resourceId, true); + //return; + if (_palVaryResourceId != -1) // another palvary is taking place, return return; _palVaryResourceId = resourceId; - _palVarySignal = 0; - // Call signal increase every [ticks] - g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0); + if (palResource) { + // Load and initialize destination palette + createFromData(palResource->data, &_palVaryTargetPalette); + // Save current palette + memcpy(&_palVaryOriginPalette, &_sysPalette, sizeof(Palette)); + + _palVarySignal = 0; + _palVaryStep = 1; + _palVaryStepStop = stepStop; + _palVaryDirection = direction; + // Call signal increase every [ticks] + g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); + } } void GfxPalette::kernelPalVaryToggle(bool pause) { @@ -503,17 +526,11 @@ void GfxPalette::kernelPalVaryDeinit() { g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); // HACK: just set the target palette - kernelSetFromResource(_palVaryResourceId, true); + //kernelSetFromResource(_palVaryResourceId, true); _palVaryResourceId = -1; // invalidate the target palette } -void GfxPalette::palVaryInit() { - _palVaryResourceId = -1; - _palVaryPaused = 0; - _palVarySignal = 0; -} - void GfxPalette::palVaryCallback(void *refCon) { ((GfxPalette *)refCon)->palVaryIncreaseSignal(); } @@ -525,7 +542,53 @@ void GfxPalette::palVaryIncreaseSignal() { // Actually do the pal vary processing void GfxPalette::palVaryUpdate() { + if (_palVarySignal) { + palVaryProcess(_palVarySignal, true); + _palVarySignal = 0; + } +} + +// Processes pal vary updates +void GfxPalette::palVaryProcess(int signal, bool setPalette) { + int16 stepChange = signal * _palVaryDirection; + + _palVaryStep += stepChange; + if (stepChange > 0) { + if (_palVaryStep > _palVaryStepStop) + _palVaryStep = _palVaryStepStop; + } else { + if (_palVaryStep < _palVaryStepStop) { + if (!signal) + _palVaryStep = _palVaryStepStop; + } + } + // We don't need updates anymore, if we reached end-position + if (_palVaryStep == _palVaryStepStop) + g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); + + // Calculate inbetween palette + Sci::Color inbetween; + int16 color; + for (int colorNr = 1; colorNr < 255; colorNr++) { + inbetween.used = _sysPalette.colors[colorNr].used; + color = _palVaryTargetPalette.colors[colorNr].r - _palVaryOriginPalette.colors[colorNr].r; + inbetween.r = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].r; + color = _palVaryTargetPalette.colors[colorNr].g - _palVaryOriginPalette.colors[colorNr].g; + inbetween.g = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].g; + color = _palVaryTargetPalette.colors[colorNr].b - _palVaryOriginPalette.colors[colorNr].b; + inbetween.b = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].b; + + if (memcmp(&inbetween, &_sysPalette.colors[colorNr], sizeof(Sci::Color))) { + _sysPalette.colors[colorNr] = inbetween; + _sysPaletteChanged = true; + } + } + + if ((_sysPaletteChanged) && (setPalette) && (_screen->_picNotValid == 0)) { + setOnScreen(); + _sysPaletteChanged = false; + } } } // End of namespace Sci diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index af649015d5..861684ecb4 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -62,10 +62,11 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - void kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks); + void kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stopPercentage, int16 direction); void kernelPalVaryToggle(bool pause); void kernelPalVaryDeinit(); void palVaryUpdate(); + void palVaryProcess(int signal, bool setPalette); Palette _sysPalette; @@ -77,16 +78,19 @@ private: GfxScreen *_screen; ResourceManager *_resMan; - GuiResourceId _palVaryResourceId; - uint32 _palVaryStart; - uint32 _palVaryEnd; - int _palVaryPaused; - int _palVarySignal; - bool _sysPaletteChanged; bool _alwaysForceRealMerge; Common::Array _schedules; + + GuiResourceId _palVaryResourceId; + Palette _palVaryOriginPalette; + Palette _palVaryTargetPalette; + uint16 _palVaryStep; + uint16 _palVaryStepStop; + int16 _palVaryDirection; + int _palVaryPaused; + int _palVarySignal; }; } // End of namespace Sci -- cgit v1.2.3 From 8fcb14d235cc4dbfc25eb503d197ff5c2f268179 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 16:36:34 +0000 Subject: SCI: adding kPalVary update call to kFrameout - it's getting morning now in gabriel knight 1 svn-id: r50083 --- engines/sci/graphics/frameout.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index f16f1068a9..d8f7285887 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -37,6 +37,7 @@ #include "sci/graphics/view.h" #include "sci/graphics/screen.h" #include "sci/graphics/paint32.h" +#include "sci/graphics/palette.h" #include "sci/graphics/picture.h" #include "sci/graphics/frameout.h" @@ -121,6 +122,8 @@ void GfxFrameout::kernelFrameout() { FrameoutList itemList; FrameoutEntry *itemEntry; + _palette->palVaryUpdate(); + // Allocate enough space for all screen items itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); -- cgit v1.2.3 From e8262d989e31742f554d37c962254c6ac37a1a7f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 16:48:52 +0000 Subject: SCI: adding code for kPalVary ticks == 0 case, fixes pharkas svn-id: r50084 --- engines/sci/graphics/palette.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 68483ac954..812bbfb234 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -506,6 +506,11 @@ void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint1 _palVaryStep = 1; _palVaryStepStop = stepStop; _palVaryDirection = direction; + if (!ticks) { + // if no ticks are given, jump directly to destination + _palVaryDirection = stepStop; + ticks = 1; + } // Call signal increase every [ticks] g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); } -- cgit v1.2.3 From 7ecff0a300e2e8a809818472160121743971e17a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 17:08:39 +0000 Subject: SCI: implementing kPalVary(2) svn-id: r50085 --- engines/sci/engine/kgraphics.cpp | 17 +++++++++++------ engines/sci/graphics/palette.cpp | 16 +++++++++++++--- engines/sci/graphics/palette.h | 5 +++-- 3 files changed, 27 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index f011f0e2d6..2ec2cdb4c3 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -653,7 +653,8 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { ticks = argv[2].toUint16(); stepStop = argc >= 4 ? argv[3].toUint16() : 64; direction = argc >= 5 ? argv[4].toUint16() : 1; - g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction); + if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction)) + return SIGNAL_REG; warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, stepStop, direction); } else { warning("kPalVary(init) called with unsupported argc %d", argc); @@ -664,9 +665,13 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } - case 2: { // Unknown - // Called in QFG4 demo (1 parameter) - warning("kPalVary(2) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + case 2: { // Get Current Step + if (argc == 1) { + int16 currentStep = g_sci->_gfxPalette->kernelPalVaryGetCurrentStep(); + return make_reg(0, currentStep); + } else { + warning("kPalVary(GetCurrentStep) called with unsupported argc %d", argc); + } break; } case 3: { // DeInit @@ -687,11 +692,11 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(5) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } - case 6: { // Pause + case 6: { // Pause/Resume bool pauseState; if (argc == 2) { pauseState = argv[1].isNull() ? false : true; - g_sci->_gfxPalette->kernelPalVaryToggle(pauseState); + g_sci->_gfxPalette->kernelPalVaryPause(pauseState); warning("kPalVary(pause) called with state = %d", pauseState); } else { warning("kPalVary(pause) called with unsupported argc %d", argc); diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 812bbfb234..f4222fabdd 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -488,11 +488,11 @@ void GfxPalette::palVaryInit() { _palVaryDirection = 0; } -void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, int16 direction) { +bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, int16 direction) { //kernelSetFromResource(resourceId, true); //return; if (_palVaryResourceId != -1) // another palvary is taking place, return - return; + return false; _palVaryResourceId = resourceId; Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0); @@ -513,10 +513,20 @@ void GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint1 } // Call signal increase every [ticks] g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); + return true; } + return false; } -void GfxPalette::kernelPalVaryToggle(bool pause) { +int16 GfxPalette::kernelPalVaryGetCurrentStep() { + if (_palVaryDirection >= 0) + return _palVaryStep; + return -_palVaryStep; +} + +void GfxPalette::kernelPalVaryPause(bool pause) { + if (_palVaryResourceId == -1) + return; // this call is actually counting states, so calling this 3 times with true will require calling it later // 3 times with false to actually remove pause if (pause) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 861684ecb4..7ea231f13b 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -62,8 +62,9 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - void kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stopPercentage, int16 direction); - void kernelPalVaryToggle(bool pause); + bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stopPercentage, int16 direction); + int16 kernelPalVaryGetCurrentStep(); + void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); void palVaryUpdate(); void palVaryProcess(int signal, bool setPalette); -- cgit v1.2.3 From bb1358ae3b224d8cdb1a870778e75334a691cf13 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 17:14:58 +0000 Subject: SCI: adding info about kPalVary(8) being SCI32 exclusive svn-id: r50086 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 2ec2cdb4c3..090af4fb1f 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -703,7 +703,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } break; } - case 8: { // Unknown + case 8: { // Unknown (seems to be SCI32 exclusive) // Called in PQ4 (1 parameter) warning("kPalVary(8) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; -- cgit v1.2.3 From ff785325ad3527394cec06fbd9dc331854e97f30 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 20 Jun 2010 17:17:46 +0000 Subject: Sort planes in kFrameOut by priority and keep plane/item priority separate as they represent two different things. Fixes various SCI32 graphical glitches. Most (all?) remaining glitches are because we don't yet handle kSignalFixedPriority. svn-id: r50087 --- engines/sci/graphics/frameout.cpp | 145 ++++++++++++++++++-------------------- engines/sci/graphics/frameout.h | 6 +- 2 files changed, 74 insertions(+), 77 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index d8f7285887..8fa4f417b0 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -47,7 +47,6 @@ GfxFrameout::GfxFrameout(SegManager *segMan, ResourceManager *resMan, GfxCoordAd : _segMan(segMan), _resMan(resMan), _cache(cache), _screen(screen), _palette(palette), _paint32(paint32) { _coordAdjuster = (GfxCoordAdjuster32 *)coordAdjuster; - _highPlanePri = 0; } GfxFrameout::~GfxFrameout() { @@ -55,30 +54,20 @@ GfxFrameout::~GfxFrameout() { void GfxFrameout::kernelAddPlane(reg_t object) { _planes.push_back(object); - int16 planePri = readSelectorValue(_segMan, object, SELECTOR(priority)) & 0xFFFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; + sortPlanes(); } void GfxFrameout::kernelUpdatePlane(reg_t object) { + sortPlanes(); } void GfxFrameout::kernelDeletePlane(reg_t object) { - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - if (_planes[planeNr] == object) { - _planes.remove_at(planeNr); - break; + for (Common::List::iterator it = _planes.begin(); it != _planes.end(); it++) { + if (object == *it) { + _planes.erase(it); + return; } } - - // Recalculate highPlanePri - _highPlanePri = 0; - - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - int16 planePri = readSelectorValue(_segMan, _planes[planeNr], SELECTOR(priority)) & 0xFFFF; - if (planePri > _highPlanePri) - _highPlanePri = planePri; - } } void GfxFrameout::kernelAddScreenItem(reg_t object) { @@ -96,70 +85,77 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) { } int16 GfxFrameout::kernelGetHighPlanePri() { - return _highPlanePri; + sortPlanes(); + reg_t object = _planes.back(); + return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back(), SELECTOR(priority)); } bool sortHelper(const FrameoutEntry* entry1, const FrameoutEntry* entry2) { return (entry1->priority == entry2->priority) ? (entry1->y < entry2->y) : (entry1->priority < entry2->priority); } -void GfxFrameout::kernelFrameout() { - int16 itemCount = 0; - reg_t planeObject; - GuiResourceId planePictureNr; - GfxPicture *planePicture = 0; - int16 planePictureCels = 0; - int16 planePictureCel; - int16 planePriority; - Common::Rect planeRect; - int16 planeResY, planeResX; - byte planeBack; - - reg_t itemObject; - reg_t itemPlane; - - FrameoutEntry *itemData; - FrameoutList itemList; - FrameoutEntry *itemEntry; +bool planeSortHelper(const reg_t entry1, const reg_t entry2) { + SegManager *segMan = g_sci->getEngineState()->_segMan; - _palette->palVaryUpdate(); + uint16 plane1Priority = readSelectorValue(segMan, entry1, SELECTOR(priority)); + uint16 plane2Priority = readSelectorValue(segMan, entry2, SELECTOR(priority)); - // Allocate enough space for all screen items - itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + if (plane1Priority == 0xffff) + return true; - for (uint32 planeNr = 0; planeNr < _planes.size(); planeNr++) { - planeObject = _planes[planeNr]; + if (plane2Priority == 0xffff) + return false; - // Remove any invalid planes - if (!_segMan->isObject(planeObject)) { - _planes.remove_at(planeNr); - planeNr--; - continue; - } + return plane1Priority < plane2Priority; +} + +void GfxFrameout::sortPlanes() { + // First, remove any invalid planes + for (Common::List::iterator it = _planes.begin(); it != _planes.end();) { + if (!_segMan->isObject(*it)) + it = _planes.erase(it); + else + it++; + } + + // Sort the rest of them + Common::sort(_planes.begin(), _planes.end(), planeSortHelper); +} - planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); +void GfxFrameout::kernelFrameout() { + _palette->palVaryUpdate(); - if (planePriority == -1) // Plane currently not meant to be shown + // Allocate enough space for all screen items + FrameoutEntry *itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + + for (Common::List::iterator it = _planes.begin(); it != _planes.end(); it++) { + reg_t planeObject = *it; + uint16 planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); + + if (planePriority == 0xffff) // Plane currently not meant to be shown continue; + Common::Rect planeRect; planeRect.top = readSelectorValue(_segMan, planeObject, SELECTOR(top)); planeRect.left = readSelectorValue(_segMan, planeObject, SELECTOR(left)); planeRect.bottom = readSelectorValue(_segMan, planeObject, SELECTOR(bottom)); planeRect.right = readSelectorValue(_segMan, planeObject, SELECTOR(right)); - planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY)); - planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX)); + int16 planeResY = readSelectorValue(_segMan, planeObject, SELECTOR(resY)); + int16 planeResX = readSelectorValue(_segMan, planeObject, SELECTOR(resX)); planeRect.top = (planeRect.top * _screen->getHeight()) / planeResY; planeRect.left = (planeRect.left * _screen->getWidth()) / planeResX; planeRect.bottom = (planeRect.bottom * _screen->getHeight()) / planeResY; planeRect.right = (planeRect.right * _screen->getWidth()) / planeResX; - planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back)); - if (planeBack) { + byte planeBack = readSelectorValue(_segMan, planeObject, SELECTOR(back)); + if (planeBack) _paint32->fillRect(planeRect, planeBack); - } - planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture)); + GuiResourceId planePictureNr = readSelectorValue(_segMan, planeObject, SELECTOR(picture)); + GfxPicture *planePicture = 0; + int16 planePictureCels = 0; + if ((planePictureNr != 0xFFFF) && (planePictureNr != 0xFFFE)) { planePicture = new GfxPicture(_resMan, _coordAdjuster, 0, _screen, _palette, planePictureNr, false); planePictureCels = planePicture->getSci32celCount(); @@ -168,10 +164,12 @@ void GfxFrameout::kernelFrameout() { } // Fill our itemlist for this plane - itemCount = 0; - itemEntry = itemData; + int16 itemCount = 0; + FrameoutEntry *itemEntry = itemData; + FrameoutList itemList; + for (uint32 itemNr = 0; itemNr < _screenItems.size(); itemNr++) { - itemObject = _screenItems[itemNr]; + reg_t itemObject = _screenItems[itemNr]; // Remove any invalid items if (!_segMan->isObject(itemObject)) { @@ -180,7 +178,7 @@ void GfxFrameout::kernelFrameout() { continue; } - itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane)); + reg_t itemPlane = readSelector(_segMan, itemObject, SELECTOR(plane)); if (planeObject == itemPlane) { // Found an item on current plane itemEntry->viewId = readSelectorValue(_segMan, itemObject, SELECTOR(view)); @@ -200,8 +198,9 @@ void GfxFrameout::kernelFrameout() { itemEntry->y += planeRect.top; itemEntry->x += planeRect.left; - if (itemEntry->priority == 0) - itemEntry->priority = itemEntry->y; + if (!(itemEntry->signal & 0x0010)) { // kSignalFixedPriority + // TODO: Change priority of this item + } itemList.push_back(itemEntry); itemEntry++; @@ -213,12 +212,10 @@ void GfxFrameout::kernelFrameout() { Common::sort(itemList.begin(), itemList.end(), sortHelper); // Now display itemlist - planePictureCel = 0; - + int16 planePictureCel = 0; itemEntry = itemData; - FrameoutList::iterator listIterator = itemList.begin(); - FrameoutList::iterator listEnd = itemList.end(); - while (listIterator != listEnd) { + + for (FrameoutList::iterator listIterator = itemList.begin(); listIterator != itemList.end(); listIterator++) { itemEntry = *listIterator; if (planePicture) { while ((planePictureCel <= itemEntry->priority) && (planePictureCel < planePictureCels)) { @@ -226,23 +223,20 @@ void GfxFrameout::kernelFrameout() { planePictureCel++; } } + if (itemEntry->viewId != 0xFFFF) { GfxView *view = _cache->getView(itemEntry->viewId); - if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) { + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, &itemEntry->celRect); - } else + else view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, &itemEntry->celRect); - if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) { - listIterator++; + if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) continue; - } - if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) { - listIterator++; + if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) continue; - } Common::Rect clipRect; clipRect = itemEntry->celRect; @@ -282,8 +276,8 @@ void GfxFrameout::kernelFrameout() { } } } - listIterator++; } + if (planePicture) { while (planePictureCel < planePictureCels) { planePicture->drawSci32Vga(planePictureCel); @@ -293,6 +287,7 @@ void GfxFrameout::kernelFrameout() { planePicture = 0; } } + free(itemData); _screen->copyToScreen(); } diff --git a/engines/sci/graphics/frameout.h b/engines/sci/graphics/frameout.h index 8015b9879f..e4568ad602 100644 --- a/engines/sci/graphics/frameout.h +++ b/engines/sci/graphics/frameout.h @@ -41,6 +41,7 @@ struct FrameoutEntry { int16 scaleY; Common::Rect celRect; }; + typedef Common::List FrameoutList; class GfxCache; @@ -74,8 +75,9 @@ private: GfxPaint32 *_paint32; Common::Array _screenItems; - Common::Array _planes; - int16 _highPlanePri; + Common::List _planes; + + void sortPlanes(); }; } // End of namespace Sci -- cgit v1.2.3 From 3c6639eb86e8328af84c190878b09c331fe4c1ac Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 18:20:05 +0000 Subject: SCI: implemented kPalVary(reverse) for pharkas, although there is a bug somewhere, not working 100% svn-id: r50089 --- engines/sci/engine/kgraphics.cpp | 19 ++++++++++++---- engines/sci/engine/message.cpp | 2 +- engines/sci/graphics/palette.cpp | 47 ++++++++++++++++++++++++++++------------ engines/sci/graphics/palette.h | 9 +++++--- 4 files changed, 55 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 090af4fb1f..1c69afc48a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -647,7 +647,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { case 0: { // Init GuiResourceId paletteId; uint16 ticks, stepStop; - int16 direction; + uint16 direction; if ((argc >= 3) && (argc <= 5)) { paletteId = argv[1].toUint16(); ticks = argv[2].toUint16(); @@ -661,9 +661,20 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } break; } - case 1: { // Unknown - warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); - break; + case 1: { // Reverse + int16 ticks, stepStop, direction; + + if ((argc >= 1) && (argc <= 4)) { + ticks = argc >= 2 ? argv[1].toUint16() : -1; + stepStop = argc >= 3 ? argv[2].toUint16() : 0; + direction = argc >= 4 ? argv[3].toSint16() : -1; + + int16 result = g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction); + warning("kPalVary(reverse) called with ticks = %d, stop = %d, direction = %d", ticks, stepStop, direction); + return make_reg(0, result); + } else { + warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + } } case 2: { // Get Current Step if (argc == 1) { diff --git a/engines/sci/engine/message.cpp b/engines/sci/engine/message.cpp index a4bde9b582..18e60eb521 100644 --- a/engines/sci/engine/message.cpp +++ b/engines/sci/engine/message.cpp @@ -380,7 +380,7 @@ void MessageState::outputString(reg_t buf, const Common::String &str) { if ((unsigned)buffer_r.maxSize >= str.size() + 1) { _segMan->strcpy(buf, str.c_str()); } else { - error("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); + warning("Message: buffer %04x:%04x invalid or too small to hold the following text of %i bytes: '%s'", PRINT_REG(buf), str.size() + 1, str.c_str()); // Set buffer to empty string if possible if (buffer_r.maxSize > 0) diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index f4222fabdd..94e847014f 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -486,9 +486,16 @@ void GfxPalette::palVaryInit() { _palVaryStep = 0; _palVaryStepStop = 0; _palVaryDirection = 0; + _palVaryTicks = 0; } -bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, int16 direction) { +void GfxPalette::palVaryInstallTimer() { + int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1; + // Call signal increase every [ticks] + g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); +} + +bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction) { //kernelSetFromResource(resourceId, true); //return; if (_palVaryResourceId != -1) // another palvary is taking place, return @@ -503,21 +510,36 @@ bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint1 memcpy(&_palVaryOriginPalette, &_sysPalette, sizeof(Palette)); _palVarySignal = 0; + _palVaryTicks = ticks; _palVaryStep = 1; _palVaryStepStop = stepStop; _palVaryDirection = direction; - if (!ticks) { - // if no ticks are given, jump directly to destination + // if no ticks are given, jump directly to destination + if (!_palVaryTicks) _palVaryDirection = stepStop; - ticks = 1; - } - // Call signal increase every [ticks] - g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); + palVaryInstallTimer(); return true; } return false; } +int16 GfxPalette::kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction) { + if (_palVaryResourceId == -1) + return 0; + + if (_palVaryStep > 64) + _palVaryStep = 64; + if (ticks != -1) + _palVaryTicks = ticks; + _palVaryStepStop = stepStop; + _palVaryDirection = direction != -1 ? -direction : -_palVaryDirection; + + if (!_palVaryTicks) + _palVaryDirection = _palVaryStepStop - _palVaryStep; + palVaryInstallTimer(); + return kernelPalVaryGetCurrentStep(); +} + int16 GfxPalette::kernelPalVaryGetCurrentStep() { if (_palVaryDirection >= 0) return _palVaryStep; @@ -540,9 +562,6 @@ void GfxPalette::kernelPalVaryPause(bool pause) { void GfxPalette::kernelPalVaryDeinit() { g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); - // HACK: just set the target palette - //kernelSetFromResource(_palVaryResourceId, true); - _palVaryResourceId = -1; // invalidate the target palette } @@ -573,7 +592,7 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) { _palVaryStep = _palVaryStepStop; } else { if (_palVaryStep < _palVaryStepStop) { - if (!signal) + if (signal) _palVaryStep = _palVaryStepStop; } } @@ -588,11 +607,11 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) { for (int colorNr = 1; colorNr < 255; colorNr++) { inbetween.used = _sysPalette.colors[colorNr].used; color = _palVaryTargetPalette.colors[colorNr].r - _palVaryOriginPalette.colors[colorNr].r; - inbetween.r = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].r; + inbetween.r = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].r; color = _palVaryTargetPalette.colors[colorNr].g - _palVaryOriginPalette.colors[colorNr].g; - inbetween.g = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].g; + inbetween.g = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].g; color = _palVaryTargetPalette.colors[colorNr].b - _palVaryOriginPalette.colors[colorNr].b; - inbetween.b = ((color * _palVaryStep) >> 6) + _palVaryOriginPalette.colors[colorNr].b; + inbetween.b = ((color * _palVaryStep) / 64) + _palVaryOriginPalette.colors[colorNr].b; if (memcmp(&inbetween, &_sysPalette.colors[colorNr], sizeof(Sci::Color))) { _sysPalette.colors[colorNr] = inbetween; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 7ea231f13b..5fcf1a0412 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -62,7 +62,8 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); - bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stopPercentage, int16 direction); + bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction); + int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction); int16 kernelPalVaryGetCurrentStep(); void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); @@ -73,6 +74,7 @@ public: private: void palVaryInit(); + void palVaryInstallTimer(); static void palVaryCallback(void *refCon); void palVaryIncreaseSignal(); @@ -87,9 +89,10 @@ private: GuiResourceId _palVaryResourceId; Palette _palVaryOriginPalette; Palette _palVaryTargetPalette; - uint16 _palVaryStep; - uint16 _palVaryStepStop; + int16 _palVaryStep; + int16 _palVaryStepStop; int16 _palVaryDirection; + uint16 _palVaryTicks; int _palVaryPaused; int _palVarySignal; }; -- cgit v1.2.3 From 05e2bbcc333afd73a5671980a90f70e0e0fb9506 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 18:22:49 +0000 Subject: SCI: dont display string set by kSetQuitStr svn-id: r50090 --- engines/sci/engine/kstring.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 5dd3910e3e..1927a79eea 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -565,7 +565,7 @@ reg_t kMessage(EngineState *s, int argc, reg_t *argv) { reg_t kSetQuitStr(EngineState *s, int argc, reg_t *argv) { Common::String quitStr = s->_segMan->getString(argv[0]); - debug("Setting quit string to '%s'", quitStr.c_str()); + //debug("Setting quit string to '%s'", quitStr.c_str()); return s->r_acc; } -- cgit v1.2.3 From d37a25cfee6832e7b92abaa693531e496b83a3c2 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 19:18:33 +0000 Subject: SCI: cleanup of SciPalette svn-id: r50091 --- engines/sci/graphics/palette.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 94e847014f..abe6043f29 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -342,8 +342,6 @@ void GfxPalette::getSys(Palette *pal) { } void GfxPalette::setOnScreen() { -// if (pal != &_sysPalette) -// memcpy(&_sysPalette,pal,sizeof(Palette)); // We dont change palette at all times for amiga if (_resMan->isAmiga32color()) return; @@ -355,7 +353,7 @@ void GfxPalette::setOnScreen() { } bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) { - Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0); + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); Palette palette; if (palResource) { @@ -496,13 +494,11 @@ void GfxPalette::palVaryInstallTimer() { } bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction) { - //kernelSetFromResource(resourceId, true); - //return; if (_palVaryResourceId != -1) // another palvary is taking place, return return false; _palVaryResourceId = resourceId; - Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), 0); + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (palResource) { // Load and initialize destination palette createFromData(palResource->data, &_palVaryTargetPalette); -- cgit v1.2.3 From a22e294ca674a2e879b31eff877fc30d256965d7 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 19:39:08 +0000 Subject: SCI: displaying debug warning again for kPalVary(init) svn-id: r50092 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 1c69afc48a..ca2bec39d7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -653,9 +653,9 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { ticks = argv[2].toUint16(); stepStop = argc >= 4 ? argv[3].toUint16() : 64; direction = argc >= 5 ? argv[4].toUint16() : 1; + warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, stepStop, direction); if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction)) return SIGNAL_REG; - warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, stepStop, direction); } else { warning("kPalVary(init) called with unsupported argc %d", argc); } -- cgit v1.2.3 From 3a9217dd5a2b1f9376f65111f8b975c07d50a9ad Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 20:05:00 +0000 Subject: SCI: disable palvary when reverse is fully done - fixes palette getting stuck in pharkas (the broken palette in there is actually not caused by palvary, it was just overwritten before by view palette updates and those dont occur when palvary is active) svn-id: r50093 --- engines/sci/graphics/palette.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index abe6043f29..3ff6c4dc54 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -596,6 +596,8 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) { // We don't need updates anymore, if we reached end-position if (_palVaryStep == _palVaryStepStop) g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); + if (_palVaryStep == 0) + _palVaryResourceId = -1; // Calculate inbetween palette Sci::Color inbetween; -- cgit v1.2.3 From 66b9eaac34d3eefc12cf6dcbacf2eb8192e0de81 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 20:09:07 +0000 Subject: SCI: adding timestamp update for frameout, fixes gk1 windows main menu svn-id: r50094 --- engines/sci/graphics/frameout.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 8fa4f417b0..545121c2b8 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -161,6 +161,7 @@ void GfxFrameout::kernelFrameout() { planePictureCels = planePicture->getSci32celCount(); _coordAdjuster->pictureSetDisplayArea(planeRect); + _palette->increaseSysTimestamp(); } // Fill our itemlist for this plane -- cgit v1.2.3 From 4a83b2c5f6a0b43c25d8870168baca9a76eee103 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 20:52:31 +0000 Subject: SCI: properly implement kPalVary functionality within kDrawPic and transitions, so pharkas finally works w/o palette corruption svn-id: r50099 --- engines/sci/graphics/frameout.cpp | 2 +- engines/sci/graphics/paint16.cpp | 5 ++- engines/sci/graphics/palette.cpp | 77 +++++++++++++++++++++++++----------- engines/sci/graphics/palette.h | 5 ++- engines/sci/graphics/transitions.cpp | 2 + 5 files changed, 63 insertions(+), 28 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 545121c2b8..05c2a1b7ad 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -161,7 +161,7 @@ void GfxFrameout::kernelFrameout() { planePictureCels = planePicture->getSci32celCount(); _coordAdjuster->pictureSetDisplayArea(planeRect); - _palette->increaseSysTimestamp(); + _palette->drewPicture(planePictureNr); } // Fill our itemlist for this plane diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 63e7d30ca0..4cf3cc16e5 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -76,9 +76,10 @@ void GfxPaint16::drawPicture(GuiResourceId pictureId, int16 animationNr, bool mi picture->draw(animationNr, mirroredFlag, addToFlag, paletteId); delete picture; - // We update our sys palette timestamp here (SCI1.1 only) + // We make a call to SciPalette here, for increasing sys timestamp and also loading targetpalette, if palvary active + // (SCI1.1 only) if (getSciVersion() == SCI_VERSION_1_1) - _palette->increaseSysTimestamp(); + _palette->drewPicture(pictureId); } // This one is the only one that updates screen! diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 3ff6c4dc54..c9fb42b48d 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -212,13 +212,16 @@ void GfxPalette::setEGA() { void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { uint32 systime = _sysPalette.timestamp; - // Pal-Vary is taking place -> abort merge - if (_palVaryResourceId != -1) - return; - if (force || newPalette->timestamp != systime) { _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); newPalette->timestamp = _sysPalette.timestamp; + + if (_palVaryResourceId != -1) { + // Pal-vary currently active, we don't set at any time, but also insert into origin palette + insert(newPalette, &_palVaryOriginPalette); + return; + } + if (_sysPaletteChanged && _screen->_picNotValid == 0) { // && systime != _sysPalette.timestamp) { // Removed timestamp checking, because this shouldnt be needed anymore. I'm leaving it commented just in // case this causes regressions @@ -228,6 +231,24 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { } } +bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { + bool paletteChanged = false; + + for (int i = 1; i < 255; i++) { + if (newPalette->colors[i].used) { + if ((newPalette->colors[i].r != destPalette->colors[i].r) || (newPalette->colors[i].g != destPalette->colors[i].g) || (newPalette->colors[i].b != destPalette->colors[i].b)) { + destPalette->colors[i].r = newPalette->colors[i].r; + destPalette->colors[i].g = newPalette->colors[i].g; + destPalette->colors[i].b = newPalette->colors[i].b; + paletteChanged = true; + } + destPalette->colors[i].used = newPalette->colors[i].used; + newPalette->mapping[i] = i; + } + } + return paletteChanged; +} + bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { uint16 res; int i,j; @@ -236,20 +257,9 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { if ((!forceRealMerge) && (!_alwaysForceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo) - for (i = 1; i < 255; i++) { - if (newPalette->colors[i].used) { - if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { - _sysPalette.colors[i].r = newPalette->colors[i].r; - _sysPalette.colors[i].g = newPalette->colors[i].g; - _sysPalette.colors[i].b = newPalette->colors[i].b; - paletteChanged = true; - } - _sysPalette.colors[i].used = newPalette->colors[i].used; - newPalette->mapping[i] = i; - } - } + // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls - return paletteChanged; + return insert(newPalette, &_sysPalette); } else { // colors 0 (black) and 255 (white) are not affected by merging @@ -305,10 +315,15 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { return paletteChanged; } -// This is used for SCI1.1 and called from kDrawPic. We only update sysPalette timestamp this way for SCI1.1 -void GfxPalette::increaseSysTimestamp() { +// This is called for SCI1.1, when kDrawPic got done. We update sysPalette timestamp this way for SCI1.1 and also load +// target-palette, if palvary is active +void GfxPalette::drewPicture(GuiResourceId pictureId) { if (!_alwaysForceRealMerge) // Don't do this on inbetween SCI1.1 games _sysPalette.timestamp++; + + if (_palVaryResourceId != -1) { + palVaryLoadTargetPalette(pictureId); + } } uint16 GfxPalette::matchColor(byte r, byte g, byte b) { @@ -487,6 +502,17 @@ void GfxPalette::palVaryInit() { _palVaryTicks = 0; } +bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { + _palVaryResourceId = resourceId; + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); + if (palResource) { + // Load and initialize destination palette + createFromData(palResource->data, &_palVaryTargetPalette); + return true; + } + return false; +} + void GfxPalette::palVaryInstallTimer() { int16 ticks = _palVaryTicks > 0 ? _palVaryTicks : 1; // Call signal increase every [ticks] @@ -497,11 +523,7 @@ bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint1 if (_palVaryResourceId != -1) // another palvary is taking place, return return false; - _palVaryResourceId = resourceId; - Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); - if (palResource) { - // Load and initialize destination palette - createFromData(palResource->data, &_palVaryTargetPalette); + if (palVaryLoadTargetPalette(resourceId)) { // Save current palette memcpy(&_palVaryOriginPalette, &_sysPalette, sizeof(Palette)); @@ -578,6 +600,13 @@ void GfxPalette::palVaryUpdate() { } } +void GfxPalette::palVaryPrepareForTransition() { + if (_palVaryResourceId != -1) { + // Before doing transitions, we have to prepare palette + palVaryProcess(0, false); + } +} + // Processes pal vary updates void GfxPalette::palVaryProcess(int signal, bool setPalette) { int16 stepChange = signal * _palVaryDirection; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 5fcf1a0412..af193e4b62 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -45,13 +45,14 @@ public: void modifyAmigaPalette(byte *data); void setEGA(); void set(Palette *sciPal, bool force, bool forceRealMerge = false); + bool insert(Palette *newPaette, Palette *destPalette); bool merge(Palette *pFrom, bool force, bool forceRealMerge); uint16 matchColor(byte r, byte g, byte b); void getSys(Palette *pal); void setOnScreen(); - void increaseSysTimestamp(); + void drewPicture(GuiResourceId pictureId); bool kernelSetFromResource(GuiResourceId resourceId, bool force); void kernelSetFlag(uint16 fromColor, uint16 toColor, uint16 flag); @@ -68,6 +69,7 @@ public: void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); void palVaryUpdate(); + void palVaryPrepareForTransition(); void palVaryProcess(int signal, bool setPalette); Palette _sysPalette; @@ -75,6 +77,7 @@ public: private: void palVaryInit(); void palVaryInstallTimer(); + bool palVaryLoadTargetPalette(GuiResourceId resourceId); static void palVaryCallback(void *refCon); void palVaryIncreaseSignal(); diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 9f8d4d1164..9f37aa016d 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -167,6 +167,8 @@ void GfxTransitions::doit(Common::Rect picRect) { } } + _palette->palVaryPrepareForTransition(); + // Now we do the actual transition to the new screen doTransition(_number, false); -- cgit v1.2.3 From 6f195ae5a4c862fede87126e2587b0fdc2952827 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 21:12:15 +0000 Subject: SCI: implemented kPalVary(changeTicks) svn-id: r50100 --- engines/sci/engine/kgraphics.cpp | 17 +++++++++++------ engines/sci/graphics/palette.cpp | 16 ++++++++++++++-- engines/sci/graphics/palette.h | 2 ++ 3 files changed, 27 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index ca2bec39d7..0b2f37f690 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -673,7 +673,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(reverse) called with ticks = %d, stop = %d, direction = %d", ticks, stepStop, direction); return make_reg(0, result); } else { - warning("kPalVary(1) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + warning("kPalVary(reverse) called with parameter %d (argc %d)", argv[1].toUint16(), argc); } } case 2: { // Get Current Step @@ -694,13 +694,18 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } break; } - case 4: { // Unknown - warning("kPalVary(4) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + case 4: { // Change Target + // seems to be 1 parameter, we should find a game that is using this feature before implementing it + warning("kPalVary(changeTarget) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } - case 5: { // Unknown - // Called in xmas 1992 demo (2 parameters) - warning("kPalVary(5) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + case 5: { // Change ticks + if (argc == 2) { + uint16 ticks = argv[1].toUint16(); + g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); + } else { + warning("kPalVary(changeTicks) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + } break; } case 6: { // Pause/Resume diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index c9fb42b48d..228e5dfced 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -519,6 +519,10 @@ void GfxPalette::palVaryInstallTimer() { g_sci->getTimerManager()->installTimerProc(&palVaryCallback, 1000000 / 60 * ticks, this); } +void GfxPalette::palVaryRemoveTimer() { + g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); +} + bool GfxPalette::kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction) { if (_palVaryResourceId != -1) // another palvary is taking place, return return false; @@ -564,6 +568,14 @@ int16 GfxPalette::kernelPalVaryGetCurrentStep() { return -_palVaryStep; } +void GfxPalette::kernelPalVaryChangeTicks(uint16 ticks) { + _palVaryTicks = ticks; + if (_palVaryStep - _palVaryStepStop) { + palVaryRemoveTimer(); + palVaryInstallTimer(); + } +} + void GfxPalette::kernelPalVaryPause(bool pause) { if (_palVaryResourceId == -1) return; @@ -578,7 +590,7 @@ void GfxPalette::kernelPalVaryPause(bool pause) { } void GfxPalette::kernelPalVaryDeinit() { - g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); + palVaryRemoveTimer(); _palVaryResourceId = -1; // invalidate the target palette } @@ -624,7 +636,7 @@ void GfxPalette::palVaryProcess(int signal, bool setPalette) { // We don't need updates anymore, if we reached end-position if (_palVaryStep == _palVaryStepStop) - g_sci->getTimerManager()->removeTimerProc(&palVaryCallback); + palVaryRemoveTimer(); if (_palVaryStep == 0) _palVaryResourceId = -1; diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index af193e4b62..021096873b 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -66,6 +66,7 @@ public: bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction); int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction); int16 kernelPalVaryGetCurrentStep(); + void kernelPalVaryChangeTicks(uint16 ticks); void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); void palVaryUpdate(); @@ -77,6 +78,7 @@ public: private: void palVaryInit(); void palVaryInstallTimer(); + void palVaryRemoveTimer(); bool palVaryLoadTargetPalette(GuiResourceId resourceId); static void palVaryCallback(void *refCon); void palVaryIncreaseSignal(); -- cgit v1.2.3 From 7694993bef7a1c60e7e6413b09d54d2808bb699b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 20 Jun 2010 21:14:46 +0000 Subject: SCI: fixed typo svn-id: r50101 --- engines/sci/graphics/transitions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 9f37aa016d..27cda249d0 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -194,7 +194,7 @@ void GfxTransitions::doTransition(int16 number, bool blackoutFlag) { verticalRollFromCenter(blackoutFlag); break; case SCI_TRANSITIONS_VERTICALROLL_TOCENTER: - verticalRollFromCenter(blackoutFlag); + verticalRollToCenter(blackoutFlag); break; case SCI_TRANSITIONS_HORIZONTALROLL_FROMCENTER: horizontalRollFromCenter(blackoutFlag); -- cgit v1.2.3 From 72534afea9696316c61c2b647f87638a34c2f57e Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 20 Jun 2010 22:30:20 +0000 Subject: Ignore the broken 65535x.map file in the QFG4 demo, mistakenly picked up when checking for patches. Audio now works there. svn-id: r50102 --- engines/sci/resource.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 745cad7029..acb7d46127 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1246,6 +1246,11 @@ void ResourceManager::readResourcePatches() { for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) { bool bAdd = false; name = (*x)->getName(); + + // HACK: Skip broken map in QFG4 Demo + if (name.equalsIgnoreCase("65535x.map")) + continue; + // SCI1 scheme if (isdigit(name[0])) { resourceNr = atoi(name.c_str()); -- cgit v1.2.3 From 473ae1c11efd6833fd0a9172b9fc54ee6ef66211 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 20 Jun 2010 23:41:54 +0000 Subject: Cleaner fix for the QFG4 demo audio map problem. svn-id: r50104 --- engines/sci/resource.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index acb7d46127..718c675db1 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1247,14 +1247,11 @@ void ResourceManager::readResourcePatches() { bool bAdd = false; name = (*x)->getName(); - // HACK: Skip broken map in QFG4 Demo - if (name.equalsIgnoreCase("65535x.map")) - continue; - // SCI1 scheme if (isdigit(name[0])) { - resourceNr = atoi(name.c_str()); - bAdd = true; + char *end = 0; + resourceNr = strtol(name.c_str(), &end, 10); + bAdd = (*end == '.'); // Ensure the next character is the period } else { // SCI0 scheme int resname_len = strlen(szResType); -- cgit v1.2.3 From 98196b8af672ecbf42738487e659fe905163819a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 10:14:04 +0000 Subject: SCI: GfxPalette::kernelSetIntensity() now also triggers throttler - somewhat "fixes" lb2cd when selecting play game svn-id: r50108 --- engines/sci/graphics/palette.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 228e5dfced..bcf84095dc 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -395,8 +395,10 @@ void GfxPalette::kernelUnsetFlag(uint16 fromColor, uint16 toColor, uint16 flag) void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 intensity, bool setPalette) { memset(&_sysPalette.intensity[0] + fromColor, intensity, toColor - fromColor); - if (setPalette) + if (setPalette) { setOnScreen(); + g_sci->getEngineState()->_throttleTrigger = true; + } } int16 GfxPalette::kernelFindColor(uint16 r, uint16 g, uint16 b) { -- cgit v1.2.3 From 8fce6600904e2094de6488e01540fca1433b1530 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 10:40:48 +0000 Subject: SCI: also set throttle trigger on kPalette(animate) svn-id: r50109 --- engines/sci/graphics/palette.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index bcf84095dc..d256227ea8 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -429,6 +429,8 @@ bool GfxPalette::kernelAnimate(byte fromColor, byte toColor, int speed) { scheduleCount++; } + g_sci->getEngineState()->_throttleTrigger = true; + for (scheduleNr = 0; scheduleNr < scheduleCount; scheduleNr++) { if (_schedules[scheduleNr].from == fromColor) { if (_schedules[scheduleNr].schedule <= now) { -- cgit v1.2.3 From cfcf53bec0f566d8fc20c5ba75ccdc00ba62ee86 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 10:51:14 +0000 Subject: SCI: fix regression of r50073, allNotesOff() now directly sends to driver again. If we send to queue, queue will never actually get processed and even if it was, the channels wouldnt be mapped anymore anyway svn-id: r50110 --- engines/sci/sound/midiparser_sci.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 640000235e..734b2fdda9 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -389,19 +389,23 @@ void MidiParser_SCI::allNotesOff() { int i, j; + // Note: we send to driver here directly, because in this case we would free previously mapped channels + // and onTimer() wouldn't send them to driver anymore afterwards anyway + // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { - if ((_active_notes[i] & (1 << j))){ - sendToDriverQueue(0x80 | j, i, 0); + if ((_active_notes[i] & (1 << j)) && (_channelRemap[j] != -1)){ + sendToDriver(0x80 | j, i, 0); } } } // Turn off all hanging notes for (i = 0; i < ARRAYSIZE(_hanging_notes); i++) { - if (_hanging_notes[i].time_left) { - sendToDriverQueue(0x80 | _hanging_notes[i].channel, _hanging_notes[i].note, 0); + byte midiChannel = _hanging_notes[i].channel; + if ((_hanging_notes[i].time_left) && (_channelRemap[midiChannel] != -1)) { + sendToDriver(0x80 | midiChannel, _hanging_notes[i].note, 0); _hanging_notes[i].time_left = 0; } } @@ -410,8 +414,10 @@ void MidiParser_SCI::allNotesOff() { // To be sure, send an "All Note Off" event (but not all MIDI devices // support this...). - for (i = 0; i < 16; ++i) - sendToDriverQueue(0xB0 | i, 0x7b, 0); // All notes off + for (i = 0; i < 16; ++i) { + if (_channelRemap[i] != -1) + sendToDriver(0xB0 | i, 0x7b, 0); // All notes off + } memset(_active_notes, 0, sizeof(_active_notes)); } -- cgit v1.2.3 From faef4ab349df5cd206fe2e5dfc666f76be3b60ec Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 Jun 2010 14:44:18 +0000 Subject: Check against the signature of Groovie v2 cursors with MKID_BE, makes it easier to see what it's doing. svn-id: r50114 --- engines/groovie/cursor.cpp | 13 +++++-------- 1 file changed, 5 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/groovie/cursor.cpp b/engines/groovie/cursor.cpp index 3f304c7859..2d0a2df245 100644 --- a/engines/groovie/cursor.cpp +++ b/engines/groovie/cursor.cpp @@ -403,18 +403,15 @@ GrvCursorMan_v2::GrvCursorMan_v2(OSystem *system) : // Open the icons file Common::File iconsFile; - if (!iconsFile.open("icons.ph")) { + if (!iconsFile.open("icons.ph")) error("Groovie::Cursor: Couldn't open icons.ph"); - return; - } // Verify the signature - uint32 tmp32 = iconsFile.readUint32LE(); + uint32 tmp32 = iconsFile.readUint32BE(); uint16 tmp16 = iconsFile.readUint16LE(); - if (tmp32 != 0x6e6f6369 || tmp16 != 1) { - error("Groovie::Cursor: icons.ph signature failed: %04X %d", tmp32, tmp16); - return; - } + if (tmp32 != MKID_BE('icon') || tmp16 != 1) + error("Groovie::Cursor: icons.ph signature failed: %s %d", tag2str(tmp32), tmp16); + // Read the number of icons uint16 nicons = iconsFile.readUint16LE(); -- cgit v1.2.3 From 4a4fcb19dd85cd8f3ffc63ef44f033d21b50744e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 15:05:48 +0000 Subject: SCI: added fixme about r50110/r50073 svn-id: r50115 --- engines/sci/sound/midiparser_sci.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 734b2fdda9..9a6be1e1df 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -392,6 +392,9 @@ void MidiParser_SCI::allNotesOff() { // Note: we send to driver here directly, because in this case we would free previously mapped channels // and onTimer() wouldn't send them to driver anymore afterwards anyway + // FIXME: the common midiparser/driver code doesn't really like getting called from various threads + // but we don't have an option here... i guess midiparser/driver code should be made thread-safe + // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { -- cgit v1.2.3 From 9ecbffe11aee736c0a3783358fb2640b0d6f5237 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 Jun 2010 15:51:04 +0000 Subject: Add a workaround for a MUMG script bug, MUMG now works again. svn-id: r50117 --- engines/sci/engine/vm.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 706d2ceb22..7f2ed436e8 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -161,6 +161,11 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in error("%s. [VM] Access would be outside even of the stack (%d); access denied", txt.c_str(), total_offset); return false; } else { + // WORKAROUND: Mixed-Up Mother Goose tries to use an invalid parameter in Event::new(). + // Just skip around it here so we don't error out in validate_arithmetic. + if (g_sci->getGameId() == "mothergoose" && getSciVersion() <= SCI_VERSION_1_1 && type == VAR_PARAM && index == 1) + return false; + debugC(2, kDebugLevelVM, "%s", txt.c_str()); debugC(2, kDebugLevelVM, "[VM] Access within stack boundaries; access granted."); return true; -- cgit v1.2.3 From 0ab7a16e452f5244d37dc0426f62b5b05d12f032 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 Jun 2010 19:07:41 +0000 Subject: Fix the Hoyle 4 (Hoyle Classic) demo's top offset. It currently errors out later from lacking a selector (static selector problem). svn-id: r50118 --- engines/sci/detection_tables.h | 8 ++++++++ engines/sci/graphics/ports.cpp | 2 +- 2 files changed, 9 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 2ac76578fe..bad7ccc5c3 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -752,8 +752,16 @@ static const struct ADGameDescription SciGameDescriptions[] = { {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + // Hoyle 4 - English DOS Demo + {"hoyle4", "Demo", { + {"resource.map", 0, "60f764020a6b788bbbe415dbc2ccb9f3", 931}, + {"resource.000", 0, "5fe3670e3ddcd4f85c10013b5453141a", 615522}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH }, + // Hoyle 4 - English DOS Demo // SCI interpreter version 1.001.200 (just a guess) + // Does anyone have this version? -clone2727 {"hoyle4", "Demo", { {"resource.map", 0, "662087cb383e52e3cc4ae7ecb10e20aa", 938}, {"resource.000", 0, "24c10844792c54d476d272213cbac300", 675252}, diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index a3135e7177..8ba7c57b62 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -88,7 +88,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort Common::String gameId = g_sci->getGameId(); - if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) + if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; openPort(_wmgrPort); -- cgit v1.2.3 From 38b172e8e5339c867fe66c69d9ef70d26c20ebf3 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Mon, 21 Jun 2010 19:32:25 +0000 Subject: Fixed some Cppcheck warnings. (There are plenty left, if anyone's wondering.) svn-id: r50120 --- engines/cruise/decompiler.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/cruise/decompiler.cpp b/engines/cruise/decompiler.cpp index ba4ade56a7..31d9dcef9b 100644 --- a/engines/cruise/decompiler.cpp +++ b/engines/cruise/decompiler.cpp @@ -760,8 +760,6 @@ int decompFunction() { char *var1; char *objIdxStr; char *ovlStr; - char varName[256]; - int i; var1 = popDecomp(); objIdxStr = popDecomp(); -- cgit v1.2.3 From 97dd94019cc668342ea52603891d706f3fbab5e3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 21 Jun 2010 20:17:59 +0000 Subject: When loading or restarting, stop script processing if the game is being loaded or is restarting and the stack position has changed (it's always changed when loading) - fixes the case where the VM is trying to parse an invalid script svn-id: r50121 --- engines/sci/engine/vm.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 7f2ed436e8..cc7f1a1be6 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -773,6 +773,9 @@ void run_vm(EngineState *s, bool restoring) { g_debugState.old_pc_offset = s->xs->addr.pc.offset; g_debugState.old_sp = s->xs->sp; + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return; // Stop processing + if (s->_executionStackPosChanged) { Script *scr; s->xs = &(s->_executionStack.back()); @@ -829,7 +832,7 @@ void run_vm(EngineState *s, bool restoring) { } if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) - return; // Emergency + return; // Stop processing // Debug if this has been requested: // TODO: re-implement sci_debug_flags -- cgit v1.2.3 From 9d5d9e13aea2e5c34ec237e735152427dd40b65c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 21 Jun 2010 21:25:13 +0000 Subject: Fixed the demo of Hoyle 4 by adding two selectors it needs "syncTime" and "syncCue". Usually, games that need them are CD talkie versions which have a selector vocabulary, but Hoyle 4 is an exception svn-id: r50122 --- engines/sci/engine/static_selectors.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index 0f558f2dc8..eca18f67fb 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -149,6 +149,19 @@ Common::StringArray Kernel::checkStaticSelectorNames() { names[slot] = selectorRemap->name; } } + + if (g_sci->getGameId() == "hoyle4") { + // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary. + // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each + // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need + // to set these two selectors, but we need for Hoyle... + if (names.size() < 276) + names.resize(276); + + names[274] = "syncTime"; + names[275] = "syncCue"; + } + #ifdef ENABLE_SCI32 } else { // SCI2+ -- cgit v1.2.3 From df569a6c822f3893c9daeee649fde7a974ee1cd2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 21 Jun 2010 21:32:56 +0000 Subject: AGI: Change AGI commands/opcodes to member methods svn-id: r50124 --- engines/agi/agi.cpp | 2 + engines/agi/agi.h | 191 ++++++++++++ engines/agi/op_cmd.cpp | 772 +++++++++++++++++++++++++------------------------ 3 files changed, 582 insertions(+), 383 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 0875646148..0f5d3ee2f0 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -569,6 +569,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _game.lastController = 0; for (int i = 0; i < MAX_DIRS; i++) _game.controllerOccured[i] = false; + + setupOpcodes(); } void AgiEngine::initialize() { diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 18f291d62c..02d3526f16 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -119,6 +119,7 @@ enum AgiGameID { GID_XMASCARD, GID_FANMADE, GID_GETOUTTASQ, // Fanmade + GID_SQ0, // Fanmade GID_MICKEY, // PreAGI GID_WINNIE, // PreAGI GID_TROLL // PreAGI @@ -1041,6 +1042,196 @@ private: bool _predictiveDialogRunning; public: char _predictiveResult[40]; + +private: + typedef void (AgiEngine::*AgiCommand)(uint8 *); + + AgiCommand _agiCommands[183]; + + void setupOpcodes(); + + void cmd_increment(uint8 *p); + void cmd_decrement(uint8 *p); + void cmd_assignn(uint8 *p); + void cmd_assignv(uint8 *p); + void cmd_addn(uint8 *p); + void cmd_addv(uint8 *p); + void cmd_subn(uint8 *p); + void cmd_subv(uint8 *p); // 0x08 + void cmd_lindirectv(uint8 *p); + void cmd_rindirect(uint8 *p); + void cmd_lindirectn(uint8 *p); + void cmd_set(uint8 *p); + void cmd_reset(uint8 *p); + void cmd_toggle(uint8 *p); + void cmd_set_v(uint8 *p); + void cmd_reset_v(uint8 *p); // 0x10 + void cmd_toggle_v(uint8 *p); + void cmd_new_room(uint8 *p); + void cmd_new_room_f(uint8 *p); + void cmd_load_logic(uint8 *p); + void cmd_load_logic_f(uint8 *p); + void cmd_call(uint8 *p); + void cmd_call_f(uint8 *p); + void cmd_load_pic(uint8 *p); // 0x18 + void cmd_draw_pic(uint8 *p); + void cmd_show_pic(uint8 *p); + void cmd_discard_pic(uint8 *p); + void cmd_overlay_pic(uint8 *p); + void cmd_show_pri_screen(uint8 *p); + void cmd_load_view(uint8 *p); + void cmd_load_view_f(uint8 *p); + void cmd_discard_view(uint8 *p); // 0x20 + void cmd_animate_obj(uint8 *p); + void cmd_unanimate_all(uint8 *p); + void cmd_draw(uint8 *p); + void cmd_erase(uint8 *p); + void cmd_position(uint8 *p); + void cmd_position_f(uint8 *p); + void cmd_get_posn(uint8 *p); + void cmd_reposition(uint8 *p); // 0x28 + void cmd_set_view(uint8 *p); + void cmd_set_view_f(uint8 *p); + void cmd_set_loop(uint8 *p); + void cmd_set_loop_f(uint8 *p); + void cmd_fix_loop(uint8 *p); + void cmd_release_loop(uint8 *p); + void cmd_set_cel(uint8 *p); + void cmd_set_cel_f(uint8 *p); // 0x30 + void cmd_last_cel(uint8 *p); + void cmd_current_cel(uint8 *p); + void cmd_current_loop(uint8 *p); + void cmd_current_view(uint8 *p); + void cmd_number_of_loops(uint8 *p); + void cmd_set_priority(uint8 *p); + void cmd_set_priority_f(uint8 *p); + void cmd_release_priority(uint8 *p); // 0x38 + void cmd_get_priority(uint8 *p); + void cmd_stop_update(uint8 *p); + void cmd_start_update(uint8 *p); + void cmd_force_update(uint8 *p); + void cmd_ignore_horizon(uint8 *p); + void cmd_observe_horizon(uint8 *p); + void cmd_set_horizon(uint8 *p); + void cmd_object_on_water(uint8 *p); // 0x40 + void cmd_object_on_land(uint8 *p); + void cmd_object_on_anything(uint8 *p); + void cmd_ignore_objs(uint8 *p); + void cmd_observe_objs(uint8 *p); + void cmd_distance(uint8 *p); + void cmd_stop_cycling(uint8 *p); + void cmd_start_cycling(uint8 *p); + void cmd_normal_cycle(uint8 *p); // 0x48 + void cmd_end_of_loop(uint8 *p); + void cmd_reverse_cycle(uint8 *p); + void cmd_reverse_loop(uint8 *p); + void cmd_cycle_time(uint8 *p); + void cmd_stop_motion(uint8 *p); + void cmd_start_motion(uint8 *p); + void cmd_step_size(uint8 *p); + void cmd_step_time(uint8 *p); // 0x50 + void cmd_move_obj(uint8 *p); + void cmd_move_obj_f(uint8 *p); + void cmd_follow_ego(uint8 *p); + void cmd_wander(uint8 *p); + void cmd_normal_motion(uint8 *p); + void cmd_set_dir(uint8 *p); + void cmd_get_dir(uint8 *p); + void cmd_ignore_blocks(uint8 *p); // 0x58 + void cmd_observe_blocks(uint8 *p); + void cmd_block(uint8 *p); + void cmd_unblock(uint8 *p); + void cmd_get(uint8 *p); + void cmd_get_f(uint8 *p); + void cmd_drop(uint8 *p); + void cmd_put(uint8 *p); + void cmd_put_f(uint8 *p); // 0x60 + void cmd_get_room_f(uint8 *p); + void cmd_load_sound(uint8 *p); + void cmd_sound(uint8 *p); + void cmd_stop_sound(uint8 *p); + void cmd_print(uint8 *p); + void cmd_print_f(uint8 *p); + void cmd_display(uint8 *p); + void cmd_display_f(uint8 *p); // 0x68 + void cmd_clear_lines(uint8 *p); + void cmd_text_screen(uint8 *p); + void cmd_graphics(uint8 *p); + void cmd_set_cursor_char(uint8 *p); + void cmd_set_text_attribute(uint8 *p); + void cmd_shake_screen(uint8 *p); + void cmd_configure_screen(uint8 *p); + void cmd_status_line_on(uint8 *p); // 0x70 + void cmd_status_line_off(uint8 *p); + void cmd_set_string(uint8 *p); + void cmd_get_string(uint8 *p); + void cmd_word_to_string(uint8 *p); + void cmd_parse(uint8 *p); + void cmd_get_num(uint8 *p); + void cmd_prevent_input(uint8 *p); + void cmd_accept_input(uint8 *p); // 0x78 + void cmd_set_key(uint8 *p); + void cmd_add_to_pic(uint8 *p); + void cmd_add_to_pic_f(uint8 *p); + void cmd_status(uint8 *p); + void cmd_save_game(uint8 *p); + void cmd_load_game(uint8 *p); + void cmd_init_disk(uint8 *p); + void cmd_restart_game(uint8 *p); // 0x80 + void cmd_show_obj(uint8 *p); + void cmd_random(uint8 *p); + void cmd_program_control(uint8 *p); + void cmd_player_control(uint8 *p); + void cmd_obj_status_f(uint8 *p); + void cmd_quit(uint8 *p); + void cmd_show_mem(uint8 *p); + void cmd_pause(uint8 *p); // 0x88 + void cmd_echo_line(uint8 *p); + void cmd_cancel_line(uint8 *p); + void cmd_init_joy(uint8 *p); + void cmd_toggle_monitor(uint8 *p); + void cmd_version(uint8 *p); + void cmd_script_size(uint8 *p); + void cmd_set_game_id(uint8 *p); + void cmd_log(uint8 *p); // 0x90 + void cmd_set_scan_start(uint8 *p); + void cmd_reset_scan_start(uint8 *p); + void cmd_reposition_to(uint8 *p); + void cmd_reposition_to_f(uint8 *p); + void cmd_trace_on(uint8 *p); + void cmd_trace_info(uint8 *p); + void cmd_print_at(uint8 *p); + void cmd_print_at_v(uint8 *p); // 0x98 + //void cmd_discard_view(uint8 *p); // Opcode repeated from 0x20 ? + void cmd_clear_text_rect(uint8 *p); + void cmd_set_upper_left(uint8 *p); + void cmd_set_menu(uint8 *p); + void cmd_set_menu_item(uint8 *p); + void cmd_submit_menu(uint8 *p); + void cmd_enable_item(uint8 *p); + void cmd_disable_item(uint8 *p); // 0xa0 + void cmd_menu_input(uint8 *p); + void cmd_show_obj_v(uint8 *p); + void cmd_open_dialogue(uint8 *p); + void cmd_close_dialogue(uint8 *p); + void cmd_mul_n(uint8 *p); + void cmd_mul_v(uint8 *p); + void cmd_div_n(uint8 *p); + void cmd_div_v(uint8 *p); // 0xa8 + void cmd_close_window(uint8 *p); + void cmd_set_simple(uint8 *p); + void cmd_push_script(uint8 *p); + void cmd_pop_script(uint8 *p); + void cmd_hold_key(uint8 *p); + void cmd_set_pri_base(uint8 *p); + void cmd_discard_sound(uint8 *p); + void cmd_hide_mouse(uint8 *p); // 0xb0 + void cmd_allow_menu(uint8 *p); + void cmd_show_mouse(uint8 *p); + void cmd_fence_mouse(uint8 *p); + void cmd_mouse_posn(uint8 *p); + void cmd_release_key(uint8 *p); + void cmd_adj_ego_move_to_x_y(uint8 *p); }; } // End of namespace Agi diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index 9728ed9b42..e18b35d35d 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -35,6 +35,8 @@ namespace Agi { +#define g_agi this + #define p0 (p[0]) #define p1 (p[1]) #define p2 (p[2]) @@ -43,34 +45,33 @@ namespace Agi { #define p5 (p[5]) #define p6 (p[6]) -#define game g_agi->_game -#define g_sprites g_agi->_sprites -#define g_sound g_agi->_sound -#define g_gfx g_agi->_gfx -#define g_picture g_agi->_picture +#define game _game +#define g_sprites _sprites +#define g_sound _sound +#define g_gfx _gfx +#define g_picture _picture #define ip curLogic->cIP -#define vt game.viewTable[p0] -#define vt_v game.viewTable[game.vars[p0]] +#define vt _game.viewTable[p0] +#define vt_v _game.viewTable[_game.vars[p0]] static struct AgiLogic *curLogic; int timerHack; // Workaround for timer loop in MH1 -#define _v game.vars -#define cmd(x) static void cmd_##x (AgiEngine *g_agi, uint8 *p) +#define _v _game.vars -cmd(increment) { +void AgiEngine::cmd_increment(uint8 *p) { if (_v[p0] != 0xff) ++_v[p0]; } -cmd(decrement) { +void AgiEngine::cmd_decrement(uint8 *p) { if (_v[p0] != 0) --_v[p0]; } -cmd(assignn) { +void AgiEngine::cmd_assignn(uint8 *p) { _v[p0] = p1; // WORKAROUND for a bug in fan game "Get outta SQ" @@ -84,83 +85,83 @@ cmd(assignn) { _v[p0] = 8; } -cmd(addn) { +void AgiEngine::cmd_addn(uint8 *p) { _v[p0] += p1; } -cmd(subn) { +void AgiEngine::cmd_subn(uint8 *p) { _v[p0] -= p1; } -cmd(assignv) { +void AgiEngine::cmd_assignv(uint8 *p) { _v[p0] = _v[p1]; } -cmd(addv) { +void AgiEngine::cmd_addv(uint8 *p) { _v[p0] += _v[p1]; } -cmd(subv) { +void AgiEngine::cmd_subv(uint8 *p) { _v[p0] -= _v[p1]; } -cmd(mul_n) { +void AgiEngine::cmd_mul_n(uint8 *p) { _v[p0] *= p1; } -cmd(mul_v) { +void AgiEngine::cmd_mul_v(uint8 *p) { _v[p0] *= _v[p1]; } -cmd(div_n) { +void AgiEngine::cmd_div_n(uint8 *p) { _v[p0] /= p1; } -cmd(div_v) { +void AgiEngine::cmd_div_v(uint8 *p) { _v[p0] /= _v[p1]; } -cmd(random) { +void AgiEngine::cmd_random(uint8 *p) { _v[p2] = g_agi->_rnd->getRandomNumber(p1 - p0) + p0; } -cmd(lindirectn) { +void AgiEngine::cmd_lindirectn(uint8 *p) { _v[_v[p0]] = p1; } -cmd(lindirectv) { +void AgiEngine::cmd_lindirectv(uint8 *p) { _v[_v[p0]] = _v[p1]; } -cmd(rindirect) { +void AgiEngine::cmd_rindirect(uint8 *p) { _v[p0] = _v[_v[p1]]; } -cmd(set) { +void AgiEngine::cmd_set(uint8 *p) { g_agi->setflag(*p, true); } -cmd(reset) { +void AgiEngine::cmd_reset(uint8 *p) { g_agi->setflag(*p, false); } -cmd(toggle) { +void AgiEngine::cmd_toggle(uint8 *p) { g_agi->setflag(*p, !g_agi->getflag(*p)); } -cmd(set_v) { +void AgiEngine::cmd_set_v(uint8 *p) { g_agi->setflag(_v[p0], true); } -cmd(reset_v) { +void AgiEngine::cmd_reset_v(uint8 *p) { g_agi->setflag(_v[p0], false); } -cmd(toggle_v) { +void AgiEngine::cmd_toggle_v(uint8 *p) { g_agi->setflag(_v[p0], !g_agi->getflag(_v[p0])); } -cmd(new_room) { +void AgiEngine::cmd_new_room(uint8 *p) { g_agi->newRoom(p0); // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush. @@ -176,79 +177,79 @@ cmd(new_room) { game.keypress = 0; } -cmd(new_room_f) { +void AgiEngine::cmd_new_room_f(uint8 *p) { g_agi->newRoom(_v[p0]); } -cmd(load_view) { +void AgiEngine::cmd_load_view(uint8 *p) { g_agi->agiLoadResource(rVIEW, p0); } -cmd(load_logic) { +void AgiEngine::cmd_load_logic(uint8 *p) { g_agi->agiLoadResource(rLOGIC, p0); } -cmd(load_sound) { +void AgiEngine::cmd_load_sound(uint8 *p) { g_agi->agiLoadResource(rSOUND, p0); } -cmd(load_view_f) { +void AgiEngine::cmd_load_view_f(uint8 *p) { g_agi->agiLoadResource(rVIEW, _v[p0]); } -cmd(load_logic_f) { +void AgiEngine::cmd_load_logic_f(uint8 *p) { g_agi->agiLoadResource(rLOGIC, _v[p0]); } -cmd(discard_view) { +void AgiEngine::cmd_discard_view(uint8 *p) { g_agi->agiUnloadResource(rVIEW, p0); } -cmd(object_on_anything) { +void AgiEngine::cmd_object_on_anything(uint8 *p) { vt.flags &= ~(ON_WATER | ON_LAND); } -cmd(object_on_land) { +void AgiEngine::cmd_object_on_land(uint8 *p) { vt.flags |= ON_LAND; } -cmd(object_on_water) { +void AgiEngine::cmd_object_on_water(uint8 *p) { vt.flags |= ON_WATER; } -cmd(observe_horizon) { +void AgiEngine::cmd_observe_horizon(uint8 *p) { vt.flags &= ~IGNORE_HORIZON; } -cmd(ignore_horizon) { +void AgiEngine::cmd_ignore_horizon(uint8 *p) { vt.flags |= IGNORE_HORIZON; } -cmd(observe_objs) { +void AgiEngine::cmd_observe_objs(uint8 *p) { vt.flags &= ~IGNORE_OBJECTS; } -cmd(ignore_objs) { +void AgiEngine::cmd_ignore_objs(uint8 *p) { vt.flags |= IGNORE_OBJECTS; } -cmd(observe_blocks) { +void AgiEngine::cmd_observe_blocks(uint8 *p) { vt.flags &= ~IGNORE_BLOCKS; } -cmd(ignore_blocks) { +void AgiEngine::cmd_ignore_blocks(uint8 *p) { vt.flags |= IGNORE_BLOCKS; } -cmd(set_horizon) { +void AgiEngine::cmd_set_horizon(uint8 *p) { game.horizon = p0; } -cmd(get_priority) { +void AgiEngine::cmd_get_priority(uint8 *p) { _v[p1] = vt.priority; } -cmd(set_priority) { +void AgiEngine::cmd_set_priority(uint8 *p) { vt.flags |= FIXED_PRIORITY; vt.priority = p1; @@ -271,242 +272,242 @@ cmd(set_priority) { } } -cmd(set_priority_f) { +void AgiEngine::cmd_set_priority_f(uint8 *p) { vt.flags |= FIXED_PRIORITY; vt.priority = _v[p1]; } -cmd(release_priority) { +void AgiEngine::cmd_release_priority(uint8 *p) { vt.flags &= ~FIXED_PRIORITY; } -cmd(set_upper_left) { // do nothing (AGI 2.917) +void AgiEngine::cmd_set_upper_left(uint8 *p) { // do nothing (AGI 2.917) } -cmd(start_update) { +void AgiEngine::cmd_start_update(uint8 *p) { g_agi->startUpdate(&vt); } -cmd(stop_update) { +void AgiEngine::cmd_stop_update(uint8 *p) { g_agi->stopUpdate(&vt); } -cmd(current_view) { +void AgiEngine::cmd_current_view(uint8 *p) { _v[p1] = vt.currentView; } -cmd(current_cel) { +void AgiEngine::cmd_current_cel(uint8 *p) { _v[p1] = vt.currentCel; debugC(4, kDebugLevelScripts, "v%d=%d", p1, _v[p1]); } -cmd(current_loop) { +void AgiEngine::cmd_current_loop(uint8 *p) { _v[p1] = vt.currentLoop; } -cmd(last_cel) { +void AgiEngine::cmd_last_cel(uint8 *p) { _v[p1] = vt.loopData->numCels - 1; } -cmd(set_cel) { +void AgiEngine::cmd_set_cel(uint8 *p) { g_agi->setCel(&vt, p1); vt.flags &= ~DONTUPDATE; } -cmd(set_cel_f) { +void AgiEngine::cmd_set_cel_f(uint8 *p) { g_agi->setCel(&vt, _v[p1]); vt.flags &= ~DONTUPDATE; } -cmd(set_view) { +void AgiEngine::cmd_set_view(uint8 *p) { g_agi->setView(&vt, p1); } -cmd(set_view_f) { +void AgiEngine::cmd_set_view_f(uint8 *p) { g_agi->setView(&vt, _v[p1]); } -cmd(set_loop) { +void AgiEngine::cmd_set_loop(uint8 *p) { g_agi->setLoop(&vt, p1); } -cmd(set_loop_f) { +void AgiEngine::cmd_set_loop_f(uint8 *p) { g_agi->setLoop(&vt, _v[p1]); } -cmd(number_of_loops) { +void AgiEngine::cmd_number_of_loops(uint8 *p) { _v[p1] = vt.numLoops; } -cmd(fix_loop) { +void AgiEngine::cmd_fix_loop(uint8 *p) { vt.flags |= FIX_LOOP; } -cmd(release_loop) { +void AgiEngine::cmd_release_loop(uint8 *p) { vt.flags &= ~FIX_LOOP; } -cmd(step_size) { +void AgiEngine::cmd_step_size(uint8 *p) { vt.stepSize = _v[p1]; } -cmd(step_time) { +void AgiEngine::cmd_step_time(uint8 *p) { vt.stepTime = vt.stepTimeCount = _v[p1]; } -cmd(cycle_time) { +void AgiEngine::cmd_cycle_time(uint8 *p) { vt.cycleTime = vt.cycleTimeCount = _v[p1]; } -cmd(stop_cycling) { +void AgiEngine::cmd_stop_cycling(uint8 *p) { vt.flags &= ~CYCLING; } -cmd(start_cycling) { +void AgiEngine::cmd_start_cycling(uint8 *p) { vt.flags |= CYCLING; } -cmd(normal_cycle) { +void AgiEngine::cmd_normal_cycle(uint8 *p) { vt.cycle = CYCLE_NORMAL; vt.flags |= CYCLING; } -cmd(reverse_cycle) { +void AgiEngine::cmd_reverse_cycle(uint8 *p) { vt.cycle = CYCLE_REVERSE; vt.flags |= CYCLING; } -cmd(set_dir) { +void AgiEngine::cmd_set_dir(uint8 *p) { vt.direction = _v[p1]; } -cmd(get_dir) { +void AgiEngine::cmd_get_dir(uint8 *p) { _v[p1] = vt.direction; } -cmd(get_room_f) { +void AgiEngine::cmd_get_room_f(uint8 *p) { _v[p1] = g_agi->objectGetLocation(_v[p0]); } -cmd(put) { +void AgiEngine::cmd_put(uint8 *p) { g_agi->objectSetLocation(p0, _v[p1]); } -cmd(put_f) { +void AgiEngine::cmd_put_f(uint8 *p) { g_agi->objectSetLocation(_v[p0], _v[p1]); } -cmd(drop) { +void AgiEngine::cmd_drop(uint8 *p) { g_agi->objectSetLocation(p0, 0); } -cmd(get) { +void AgiEngine::cmd_get(uint8 *p) { g_agi->objectSetLocation(p0, EGO_OWNED); } -cmd(get_f) { +void AgiEngine::cmd_get_f(uint8 *p) { g_agi->objectSetLocation(_v[p0], EGO_OWNED); } -cmd(word_to_string) { +void AgiEngine::cmd_word_to_string(uint8 *p) { strcpy(game.strings[p0], game.egoWords[p1].word); } -cmd(open_dialogue) { +void AgiEngine::cmd_open_dialogue(uint8 *p) { game.hasWindow = true; } -cmd(close_dialogue) { +void AgiEngine::cmd_close_dialogue(uint8 *p) { game.hasWindow = false; } -cmd(close_window) { +void AgiEngine::cmd_close_window(uint8 *p) { g_agi->closeWindow(); } -cmd(status_line_on) { +void AgiEngine::cmd_status_line_on(uint8 *p) { game.statusLine = true; g_agi->writeStatus(); } -cmd(status_line_off) { +void AgiEngine::cmd_status_line_off(uint8 *p) { game.statusLine = false; g_agi->writeStatus(); } -cmd(show_obj) { +void AgiEngine::cmd_show_obj(uint8 *p) { g_sprites->showObj(p0); } -cmd(show_obj_v) { +void AgiEngine::cmd_show_obj_v(uint8 *p) { g_sprites->showObj(_v[p0]); } -cmd(sound) { +void AgiEngine::cmd_sound(uint8 *p) { g_sound->startSound(p0, p1); } -cmd(stop_sound) { +void AgiEngine::cmd_stop_sound(uint8 *p) { g_sound->stopSound(); } -cmd(menu_input) { +void AgiEngine::cmd_menu_input(uint8 *p) { g_agi->newInputMode(INPUT_MENU); } -cmd(enable_item) { +void AgiEngine::cmd_enable_item(uint8 *p) { g_agi->_menu->setItem(p0, true); } -cmd(disable_item) { +void AgiEngine::cmd_disable_item(uint8 *p) { g_agi->_menu->setItem(p0, false); } -cmd(submit_menu) { +void AgiEngine::cmd_submit_menu(uint8 *p) { g_agi->_menu->submit(); } -cmd(set_scan_start) { +void AgiEngine::cmd_set_scan_start(uint8 *p) { curLogic->sIP = curLogic->cIP; } -cmd(reset_scan_start) { +void AgiEngine::cmd_reset_scan_start(uint8 *p) { curLogic->sIP = 2; } -cmd(save_game) { +void AgiEngine::cmd_save_game(uint8 *p) { game.simpleSave ? g_agi->saveGameSimple() : g_agi->saveGameDialog(); } -cmd(load_game) { +void AgiEngine::cmd_load_game(uint8 *p) { assert(1); game.simpleSave ? g_agi->loadGameSimple() : g_agi->loadGameDialog(); } -cmd(init_disk) { // do nothing +void AgiEngine::cmd_init_disk(uint8 *p) { // do nothing } -cmd(log) { // do nothing +void AgiEngine::cmd_log(uint8 *p) { // do nothing } -cmd(trace_on) { // do nothing +void AgiEngine::cmd_trace_on(uint8 *p) { // do nothing } -cmd(trace_info) { // do nothing +void AgiEngine::cmd_trace_info(uint8 *p) { // do nothing } -cmd(show_mem) { +void AgiEngine::cmd_show_mem(uint8 *p) { g_agi->messageBox("Enough memory"); } -cmd(init_joy) { // do nothing +void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing } -cmd(script_size) { +void AgiEngine::cmd_script_size(uint8 *p) { report("script.size(%d)\n", p0); } -cmd(cancel_line) { +void AgiEngine::cmd_cancel_line(uint8 *p) { g_agi->_game.inputBuffer[0] = 0; g_agi->writePrompt(); } @@ -521,7 +522,7 @@ cmd(cancel_line) { // 4051 (When ego is stationary), // 471 (When walking on the first screen's bridge), // 71 (When walking around, using the mouse or the keyboard). -cmd(obj_status_f) { +void AgiEngine::cmd_obj_status_f(uint8 *p) { const char *cycleDesc; // Object's cycle description line const char *motionDesc; // Object's motion description line char msg[256]; // The whole object status message @@ -593,22 +594,22 @@ cmd(obj_status_f) { // unk_174: Change priority table (used in KQ4) -- j5 // unk_177: Disable menus completely -- j5 // unk_181: Deactivate keypressed control (default control of ego) -cmd(set_simple) { +void AgiEngine::cmd_set_simple(uint8 *p) { if (!(g_agi->getFeatures() & (GF_AGI256 | GF_AGI256_2))) { game.simpleSave = true; } else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures. - // Load the picture. Similar to cmd(load_pic). + // Load the picture. Similar to void AgiEngine::cmd_load_pic(uint8 *p). g_sprites->eraseBoth(); g_agi->agiLoadResource(rPICTURE, _v[p0]); - // Draw the picture. Similar to cmd(draw_pic). + // Draw the picture. Similar to void AgiEngine::cmd_draw_pic(uint8 *p). g_picture->decodePicture(_v[p0], false, true); g_sprites->blitBoth(); game.pictureShown = 0; - // Show the picture. Similar to cmd(show_pic). + // Show the picture. Similar to void AgiEngine::cmd_show_pic(uint8 *p). g_agi->setflag(fOutputMode, false); - cmd_close_window(g_agi, NULL); + g_agi->closeWindow(); g_picture->showPic(); game.pictureShown = 1; @@ -617,25 +618,25 @@ cmd(set_simple) { } } -cmd(pop_script) { +void AgiEngine::cmd_pop_script(uint8 *p) { if (g_agi->getVersion() >= 0x2915) { report("pop.script\n"); } } -cmd(hold_key) { +void AgiEngine::cmd_hold_key(uint8 *p) { if (g_agi->getVersion() >= 0x3098) { g_agi->_egoHoldKey = true; } } -cmd(discard_sound) { +void AgiEngine::cmd_discard_sound(uint8 *p) { if (g_agi->getVersion() >= 0x2936) { report("discard.sound\n"); } } -cmd(hide_mouse) { +void AgiEngine::cmd_hide_mouse(uint8 *p) { // WORKAROUND: Turns off current movement that's being caused with the mouse. // This fixes problems with too many popup boxes appearing in the Amiga // Gold Rush's copy protection failure scene (i.e. the hanging scene, logic.192). @@ -648,29 +649,29 @@ cmd(hide_mouse) { g_system->showMouse(false); } -cmd(allow_menu) { +void AgiEngine::cmd_allow_menu(uint8 *p) { if (g_agi->getVersion() >= 0x3098) { g_agi->setflag(fMenusWork, ((p0 != 0) ? true : false)); } } -cmd(show_mouse) { +void AgiEngine::cmd_show_mouse(uint8 *p) { g_system->showMouse(true); } -cmd(fence_mouse) { +void AgiEngine::cmd_fence_mouse(uint8 *p) { g_agi->_game.mouseFence.moveTo(p0, p1); g_agi->_game.mouseFence.setWidth(p2 - p0); g_agi->_game.mouseFence.setHeight(p3 - p1); } -cmd(release_key) { +void AgiEngine::cmd_release_key(uint8 *p) { if (g_agi->getVersion() >= 0x3098) { g_agi->_egoHoldKey = false; } } -cmd(adj_ego_move_to_x_y) { +void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) { int8 x, y; switch (logicNamesCmd[182].numArgs) { @@ -708,7 +709,7 @@ cmd(adj_ego_move_to_x_y) { } } -cmd(parse) { +void AgiEngine::cmd_parse(uint8 *p) { _v[vWordNotFound] = 0; g_agi->setflag(fEnteredCli, false); g_agi->setflag(fSaidAcceptedInput, false); @@ -716,7 +717,7 @@ cmd(parse) { g_agi->dictionaryWords(g_agi->agiSprintf(game.strings[p0])); } -cmd(call) { +void AgiEngine::cmd_call(uint8 *p) { int oldCIP; int oldLognum; @@ -732,11 +733,11 @@ cmd(call) { curLogic->cIP = oldCIP; } -cmd(call_f) { - cmd_call(g_agi, &_v[p0]); +void AgiEngine::cmd_call_f(uint8 *p) { + cmd_call(&_v[p0]); } -cmd(draw_pic) { +void AgiEngine::cmd_draw_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== draw pic %d ===", _v[p0]); g_sprites->eraseBoth(); g_picture->decodePicture(_v[p0], true); @@ -764,30 +765,30 @@ cmd(draw_pic) { g_agi->pause(kPausePicture); } -cmd(show_pic) { +void AgiEngine::cmd_show_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== show pic ==="); g_agi->setflag(fOutputMode, false); - cmd_close_window(g_agi, NULL); + g_agi->closeWindow(); g_picture->showPic(); game.pictureShown = 1; debugC(6, kDebugLevelScripts, "--- end of show pic ---"); } -cmd(load_pic) { +void AgiEngine::cmd_load_pic(uint8 *p) { g_sprites->eraseBoth(); g_agi->agiLoadResource(rPICTURE, _v[p0]); g_sprites->blitBoth(); g_sprites->commitBoth(); } -cmd(discard_pic) { +void AgiEngine::cmd_discard_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "--- discard pic ---"); // do nothing } -cmd(overlay_pic) { +void AgiEngine::cmd_overlay_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "--- overlay pic ---"); g_sprites->eraseBoth(); @@ -800,7 +801,7 @@ cmd(overlay_pic) { g_agi->pause(kPausePicture); } -cmd(show_pri_screen) { +void AgiEngine::cmd_show_pri_screen(uint8 *p) { g_agi->_debug.priority = 1; g_sprites->eraseBoth(); g_picture->showPic(); @@ -814,7 +815,7 @@ cmd(show_pri_screen) { g_sprites->blitBoth(); } -cmd(animate_obj) { +void AgiEngine::cmd_animate_obj(uint8 *p) { if (vt.flags & ANIMATED) return; @@ -825,14 +826,14 @@ cmd(animate_obj) { vt.direction = 0; } -cmd(unanimate_all) { +void AgiEngine::cmd_unanimate_all(uint8 *p) { int i; for (i = 0; i < MAX_VIEWTABLE; i++) game.viewTable[i].flags &= ~(ANIMATED | DRAWN); } -cmd(draw) { +void AgiEngine::cmd_draw(uint8 *p) { if (vt.flags & DRAWN) return; @@ -876,7 +877,7 @@ cmd(draw) { debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags); } -cmd(erase) { +void AgiEngine::cmd_erase(uint8 *p) { if (~vt.flags & DRAWN) return; @@ -901,7 +902,7 @@ cmd(erase) { g_sprites->commitBlock(x1, y1, x2, y2, true); } -cmd(position) { +void AgiEngine::cmd_position(uint8 *p) { vt.xPos = vt.xPos2 = p1; vt.yPos = vt.yPos2 = p2; @@ -922,7 +923,7 @@ cmd(position) { g_agi->clipViewCoordinates(&vt); } -cmd(position_f) { +void AgiEngine::cmd_position_f(uint8 *p) { vt.xPos = vt.xPos2 = _v[p1]; vt.yPos = vt.yPos2 = _v[p2]; @@ -933,12 +934,12 @@ cmd(position_f) { g_agi->clipViewCoordinates(&vt); } -cmd(get_posn) { +void AgiEngine::cmd_get_posn(uint8 *p) { game.vars[p1] = (unsigned char)vt.xPos; game.vars[p2] = (unsigned char)vt.yPos; } -cmd(reposition) { +void AgiEngine::cmd_reposition(uint8 *p) { int dx = (int8) _v[p1], dy = (int8) _v[p2]; debugC(4, kDebugLevelScripts, "dx=%d, dy=%d", dx, dy); @@ -957,35 +958,35 @@ cmd(reposition) { g_agi->fixPosition(p0); } -cmd(reposition_to) { +void AgiEngine::cmd_reposition_to(uint8 *p) { vt.xPos = p1; vt.yPos = p2; vt.flags |= UPDATE_POS; g_agi->fixPosition(p0); } -cmd(reposition_to_f) { +void AgiEngine::cmd_reposition_to_f(uint8 *p) { vt.xPos = _v[p1]; vt.yPos = _v[p2]; vt.flags |= UPDATE_POS; g_agi->fixPosition(p0); } -cmd(add_to_pic) { +void AgiEngine::cmd_add_to_pic(uint8 *p) { g_sprites->addToPic(p0, p1, p2, p3, p4, p5, p6); } -cmd(add_to_pic_f) { +void AgiEngine::cmd_add_to_pic_f(uint8 *p) { g_sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]); } -cmd(force_update) { +void AgiEngine::cmd_force_update(uint8 *p) { g_sprites->eraseBoth(); g_sprites->blitBoth(); g_sprites->commitBoth(); } -cmd(reverse_loop) { +void AgiEngine::cmd_reverse_loop(uint8 *p) { debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1); vt.cycle = CYCLE_REV_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); @@ -993,7 +994,7 @@ cmd(reverse_loop) { g_agi->setflag(p1, false); } -cmd(end_of_loop) { +void AgiEngine::cmd_end_of_loop(uint8 *p) { debugC(4, kDebugLevelScripts, "o%d, f%d", p0, p1); vt.cycle = CYCLE_END_OF_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); @@ -1001,7 +1002,7 @@ cmd(end_of_loop) { g_agi->setflag(p1, false); } -cmd(block) { +void AgiEngine::cmd_block(uint8 *p) { debugC(4, kDebugLevelScripts, "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3); game.block.active = true; game.block.x1 = p0; @@ -1010,15 +1011,15 @@ cmd(block) { game.block.y2 = p3; } -cmd(unblock) { +void AgiEngine::cmd_unblock(uint8 *p) { game.block.active = false; } -cmd(normal_motion) { +void AgiEngine::cmd_normal_motion(uint8 *p) { vt.motion = MOTION_NORMAL; } -cmd(stop_motion) { +void AgiEngine::cmd_stop_motion(uint8 *p) { vt.direction = 0; vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only @@ -1027,7 +1028,7 @@ cmd(stop_motion) { } } -cmd(start_motion) { +void AgiEngine::cmd_start_motion(uint8 *p) { vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only _v[vEgoDir] = 0; @@ -1035,16 +1036,16 @@ cmd(start_motion) { } } -cmd(player_control) { +void AgiEngine::cmd_player_control(uint8 *p) { game.playerControl = true; game.viewTable[0].motion = MOTION_NORMAL; } -cmd(program_control) { +void AgiEngine::cmd_program_control(uint8 *p) { game.playerControl = false; } -cmd(follow_ego) { +void AgiEngine::cmd_follow_ego(uint8 *p) { vt.motion = MOTION_FOLLOW_EGO; vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize; vt.parm2 = p2; @@ -1053,7 +1054,7 @@ cmd(follow_ego) { vt.flags |= UPDATE; } -cmd(move_obj) { +void AgiEngine::cmd_move_obj(uint8 *p) { // _D (_D_WARN "o=%d, x=%d, y=%d, s=%d, f=%d", p0, p1, p2, p3, p4); vt.motion = MOTION_MOVE_OBJ; @@ -1076,7 +1077,7 @@ cmd(move_obj) { g_agi->moveObj(&vt); } -cmd(move_obj_f) { +void AgiEngine::cmd_move_obj_f(uint8 *p) { vt.motion = MOTION_MOVE_OBJ; vt.parm1 = _v[p1]; vt.parm2 = _v[p2]; @@ -1097,7 +1098,7 @@ cmd(move_obj_f) { g_agi->moveObj(&vt); } -cmd(wander) { +void AgiEngine::cmd_wander(uint8 *p) { if (p0 == 0) game.playerControl = false; @@ -1105,7 +1106,7 @@ cmd(wander) { vt.flags |= UPDATE; } -cmd(set_game_id) { +void AgiEngine::cmd_set_game_id(uint8 *p) { if (curLogic->texts && (p0 - 1) <= curLogic->numTexts) strncpy(game.id, curLogic->texts[p0 - 1], 8); else @@ -1114,7 +1115,7 @@ cmd(set_game_id) { report("Game ID: \"%s\"\n", game.id); } -cmd(pause) { +void AgiEngine::cmd_pause(uint8 *p) { int tmp = game.clockEnabled; const char *b[] = { "Continue", NULL }; const char *b_ru[] = { "\x8f\xe0\xae\xa4\xae\xab\xa6\xa8\xe2\xec", NULL }; @@ -1132,21 +1133,21 @@ cmd(pause) { game.clockEnabled = tmp; } -cmd(set_menu) { +void AgiEngine::cmd_set_menu(uint8 *p) { debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); if (curLogic->texts != NULL && p0 <= curLogic->numTexts) g_agi->_menu->add(curLogic->texts[p0 - 1]); } -cmd(set_menu_item) { +void AgiEngine::cmd_set_menu_item(uint8 *p) { debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); if (curLogic->texts != NULL && p0 <= curLogic->numTexts) g_agi->_menu->addItem(curLogic->texts[p0 - 1], p1); } -cmd(version) { +void AgiEngine::cmd_version(uint8 *p) { char verMsg[64]; char ver2Msg[] = "\n" @@ -1186,13 +1187,13 @@ cmd(version) { g_agi->messageBox(msg); } -cmd(configure_screen) { +void AgiEngine::cmd_configure_screen(uint8 *p) { game.lineMinPrint = p0; game.lineUserInput = p1; game.lineStatus = p2; } -cmd(text_screen) { +void AgiEngine::cmd_text_screen(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to text mode"); game.gfxMode = false; @@ -1204,7 +1205,7 @@ cmd(text_screen) { g_gfx->clearScreen(game.colorBg); } -cmd(graphics) { +void AgiEngine::cmd_graphics(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to graphics mode"); if (!game.gfxMode) { @@ -1216,7 +1217,7 @@ cmd(graphics) { } } -cmd(set_text_attribute) { +void AgiEngine::cmd_set_text_attribute(uint8 *p) { game.colorFg = p0; game.colorBg = p1; @@ -1228,11 +1229,11 @@ cmd(set_text_attribute) { } } -cmd(status) { +void AgiEngine::cmd_status(uint8 *p) { g_agi->inventory(); } -cmd(quit) { +void AgiEngine::cmd_quit(uint8 *p) { const char *buttons[] = { "Quit", "Continue", NULL }; g_sound->stopSound(); @@ -1246,7 +1247,7 @@ cmd(quit) { } } -cmd(restart_game) { +void AgiEngine::cmd_restart_game(uint8 *p) { const char *buttons[] = { "Restart", "Continue", NULL }; int sel; @@ -1261,7 +1262,7 @@ cmd(restart_game) { } } -cmd(distance) { +void AgiEngine::cmd_distance(uint8 *p) { int16 x1, y1, x2, y2, d; VtEntry *v0 = &game.viewTable[p0]; VtEntry *v1 = &game.viewTable[p1]; @@ -1312,7 +1313,7 @@ cmd(distance) { _v[p2] = (unsigned char)d; } -cmd(accept_input) { +void AgiEngine::cmd_accept_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal"); g_agi->newInputMode(INPUT_NORMAL); @@ -1320,7 +1321,7 @@ cmd(accept_input) { g_agi->writePrompt(); } -cmd(prevent_input) { +void AgiEngine::cmd_prevent_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input"); g_agi->newInputMode(INPUT_NONE); @@ -1329,7 +1330,7 @@ cmd(prevent_input) { g_agi->clearPrompt(); } -cmd(get_string) { +void AgiEngine::cmd_get_string(uint8 *p) { int tex, row, col; debugC(4, kDebugLevelScripts, "%d %d %d %d %d", p0, p1, p2, p3, p4); @@ -1362,7 +1363,7 @@ cmd(get_string) { } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); } -cmd(get_num) { +void AgiEngine::cmd_get_num(uint8 *p) { debugC(4, kDebugLevelScripts, "%d %d", p0, p1); g_agi->newInputMode(INPUT_GETSTRING); @@ -1389,7 +1390,7 @@ cmd(get_num) { g_agi->flushLines(22, 22); } -cmd(set_cursor_char) { +void AgiEngine::cmd_set_cursor_char(uint8 *p) { if (curLogic->texts != NULL && (p0 - 1) <= curLogic->numTexts) { game.cursorChar = *curLogic->texts[p0 - 1]; } else { @@ -1398,7 +1399,7 @@ cmd(set_cursor_char) { } } -cmd(set_key) { +void AgiEngine::cmd_set_key(uint8 *p) { int key; if (game.lastController >= MAX_CONTROLLERS) { @@ -1417,14 +1418,14 @@ cmd(set_key) { game.controllerOccured[p2] = false; } -cmd(set_string) { +void AgiEngine::cmd_set_string(uint8 *p) { // CM: to avoid crash in Groza (str = 150) if (p0 > MAX_STRINGS) return; strcpy(game.strings[p0], curLogic->texts[p1 - 1]); } -cmd(display) { +void AgiEngine::cmd_display(uint8 *p) { int len = 40; char *s = g_agi->wordWrapString(curLogic->texts[p2 - 1], &len); @@ -1434,11 +1435,11 @@ cmd(display) { free(s); } -cmd(display_f) { +void AgiEngine::cmd_display_f(uint8 *p) { g_agi->printText(curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, game.colorFg, game.colorBg); } -cmd(clear_text_rect) { +void AgiEngine::cmd_clear_text_rect(uint8 *p) { int c, x1, y1, x2, y2; if ((c = p4) != 0) @@ -1463,17 +1464,17 @@ cmd(clear_text_rect) { g_gfx->flushBlock(x1, y1, x2, y2); } -cmd(toggle_monitor) { +void AgiEngine::cmd_toggle_monitor(uint8 *p) { report("toggle.monitor\n"); } -cmd(echo_line) { +void AgiEngine::cmd_echo_line(uint8 *p) { strcpy((char *)game.inputBuffer, (const char *)game.echoBuffer); game.cursorPos = strlen((char *)game.inputBuffer); game.hasPrompt = 0; } -cmd(clear_lines) { +void AgiEngine::cmd_clear_lines(uint8 *p) { uint8 l; // Residence 44 calls clear.lines(24,0,0), see Sarien bug #558423 @@ -1487,19 +1488,19 @@ cmd(clear_lines) { g_agi->flushLines(p0, l); } -cmd(print) { +void AgiEngine::cmd_print(uint8 *p) { int n = p0 < 1 ? 1 : p0; g_agi->print(curLogic->texts[n - 1], 0, 0, 0); } -cmd(print_f) { +void AgiEngine::cmd_print_f(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; g_agi->print(curLogic->texts[n - 1], 0, 0, 0); } -cmd(print_at) { +void AgiEngine::cmd_print_at(uint8 *p) { int n = p0 < 1 ? 1 : p0; debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3); @@ -1507,13 +1508,13 @@ cmd(print_at) { g_agi->print(curLogic->texts[n - 1], p1, p2, p3); } -cmd(print_at_v) { +void AgiEngine::cmd_print_at_v(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; g_agi->print(curLogic->texts[n - 1], p1, p2, p3); } -cmd(push_script) { +void AgiEngine::cmd_push_script(uint8 *p) { // We run AGIMOUSE always as a side effect if (g_agi->getFeatures() & GF_AGIMOUSE || 1) { game.vars[27] = g_agi->_mouse.button; @@ -1526,7 +1527,7 @@ cmd(push_script) { } } -cmd(set_pri_base) { +void AgiEngine::cmd_set_pri_base(uint8 *p) { int i, x, pri; report("Priority base set to %d\n", p0); @@ -1542,12 +1543,12 @@ cmd(set_pri_base) { } } -cmd(mouse_posn) { +void AgiEngine::cmd_mouse_posn(uint8 *p) { _v[p0] = WIN_TO_PIC_X(g_agi->_mouse.x); _v[p1] = WIN_TO_PIC_Y(g_agi->_mouse.y); } -cmd(shake_screen) { +void AgiEngine::cmd_shake_screen(uint8 *p) { int i; // AGIPAL uses shake.screen values between 100 and 109 to set the palette @@ -1580,191 +1581,196 @@ cmd(shake_screen) { game.inputEnabled = originalValue; } -static void (*agiCommand[183])(AgiEngine *, uint8 *) = { - NULL, // 0x00 - cmd_increment, - cmd_decrement, - cmd_assignn, - cmd_assignv, - cmd_addn, - cmd_addv, - cmd_subn, - cmd_subv, // 0x08 - cmd_lindirectv, - cmd_rindirect, - cmd_lindirectn, - cmd_set, - cmd_reset, - cmd_toggle, - cmd_set_v, - cmd_reset_v, // 0x10 - cmd_toggle_v, - cmd_new_room, - cmd_new_room_f, - cmd_load_logic, - cmd_load_logic_f, - cmd_call, - cmd_call_f, - cmd_load_pic, // 0x18 - cmd_draw_pic, - cmd_show_pic, - cmd_discard_pic, - cmd_overlay_pic, - cmd_show_pri_screen, - cmd_load_view, - cmd_load_view_f, - cmd_discard_view, // 0x20 - cmd_animate_obj, - cmd_unanimate_all, - cmd_draw, - cmd_erase, - cmd_position, - cmd_position_f, - cmd_get_posn, - cmd_reposition, // 0x28 - cmd_set_view, - cmd_set_view_f, - cmd_set_loop, - cmd_set_loop_f, - cmd_fix_loop, - cmd_release_loop, - cmd_set_cel, - cmd_set_cel_f, // 0x30 - cmd_last_cel, - cmd_current_cel, - cmd_current_loop, - cmd_current_view, - cmd_number_of_loops, - cmd_set_priority, - cmd_set_priority_f, - cmd_release_priority, // 0x38 - cmd_get_priority, - cmd_stop_update, - cmd_start_update, - cmd_force_update, - cmd_ignore_horizon, - cmd_observe_horizon, - cmd_set_horizon, - cmd_object_on_water, // 0x40 - cmd_object_on_land, - cmd_object_on_anything, - cmd_ignore_objs, - cmd_observe_objs, - cmd_distance, - cmd_stop_cycling, - cmd_start_cycling, - cmd_normal_cycle, // 0x48 - cmd_end_of_loop, - cmd_reverse_cycle, - cmd_reverse_loop, - cmd_cycle_time, - cmd_stop_motion, - cmd_start_motion, - cmd_step_size, - cmd_step_time, // 0x50 - cmd_move_obj, - cmd_move_obj_f, - cmd_follow_ego, - cmd_wander, - cmd_normal_motion, - cmd_set_dir, - cmd_get_dir, - cmd_ignore_blocks, // 0x58 - cmd_observe_blocks, - cmd_block, - cmd_unblock, - cmd_get, - cmd_get_f, - cmd_drop, - cmd_put, - cmd_put_f, // 0x60 - cmd_get_room_f, - cmd_load_sound, - cmd_sound, - cmd_stop_sound, - cmd_print, - cmd_print_f, - cmd_display, - cmd_display_f, // 0x68 - cmd_clear_lines, - cmd_text_screen, - cmd_graphics, - cmd_set_cursor_char, - cmd_set_text_attribute, - cmd_shake_screen, - cmd_configure_screen, - cmd_status_line_on, // 0x70 - cmd_status_line_off, - cmd_set_string, - cmd_get_string, - cmd_word_to_string, - cmd_parse, - cmd_get_num, - cmd_prevent_input, - cmd_accept_input, // 0x78 - cmd_set_key, - cmd_add_to_pic, - cmd_add_to_pic_f, - cmd_status, - cmd_save_game, - cmd_load_game, - cmd_init_disk, - cmd_restart_game, // 0x80 - cmd_show_obj, - cmd_random, - cmd_program_control, - cmd_player_control, - cmd_obj_status_f, - cmd_quit, - cmd_show_mem, - cmd_pause, // 0x88 - cmd_echo_line, - cmd_cancel_line, - cmd_init_joy, - cmd_toggle_monitor, - cmd_version, - cmd_script_size, - cmd_set_game_id, - cmd_log, // 0x90 - cmd_set_scan_start, - cmd_reset_scan_start, - cmd_reposition_to, - cmd_reposition_to_f, - cmd_trace_on, - cmd_trace_info, - cmd_print_at, - cmd_print_at_v, // 0x98 - cmd_discard_view, - cmd_clear_text_rect, - cmd_set_upper_left, - cmd_set_menu, - cmd_set_menu_item, - cmd_submit_menu, - cmd_enable_item, - cmd_disable_item, // 0xa0 - cmd_menu_input, - cmd_show_obj_v, - cmd_open_dialogue, - cmd_close_dialogue, - cmd_mul_n, - cmd_mul_v, - cmd_div_n, - cmd_div_v, // 0xa8 - cmd_close_window, - cmd_set_simple, - cmd_push_script, - cmd_pop_script, - cmd_hold_key, - cmd_set_pri_base, - cmd_discard_sound, - cmd_hide_mouse, // 0xb0 - cmd_allow_menu, - cmd_show_mouse, - cmd_fence_mouse, - cmd_mouse_posn, - cmd_release_key, - cmd_adj_ego_move_to_x_y -}; +void AgiEngine::setupOpcodes() { + AgiCommand tmp[] = { + NULL, // 0x00 + &AgiEngine::cmd_increment, + &AgiEngine::cmd_decrement, + &AgiEngine::cmd_assignn, + &AgiEngine::cmd_assignv, + &AgiEngine::cmd_addn, + &AgiEngine::cmd_addv, + &AgiEngine::cmd_subn, + &AgiEngine::cmd_subv, // 0x08 + &AgiEngine::cmd_lindirectv, + &AgiEngine::cmd_rindirect, + &AgiEngine::cmd_lindirectn, + &AgiEngine::cmd_set, + &AgiEngine::cmd_reset, + &AgiEngine::cmd_toggle, + &AgiEngine::cmd_set_v, + &AgiEngine::cmd_reset_v, // 0x10 + &AgiEngine::cmd_toggle_v, + &AgiEngine::cmd_new_room, + &AgiEngine::cmd_new_room_f, + &AgiEngine::cmd_load_logic, + &AgiEngine::cmd_load_logic_f, + &AgiEngine::cmd_call, + &AgiEngine::cmd_call_f, + &AgiEngine::cmd_load_pic, // 0x18 + &AgiEngine::cmd_draw_pic, + &AgiEngine::cmd_show_pic, + &AgiEngine::cmd_discard_pic, + &AgiEngine::cmd_overlay_pic, + &AgiEngine::cmd_show_pri_screen, + &AgiEngine::cmd_load_view, + &AgiEngine::cmd_load_view_f, + &AgiEngine::cmd_discard_view, // 0x20 + &AgiEngine::cmd_animate_obj, + &AgiEngine::cmd_unanimate_all, + &AgiEngine::cmd_draw, + &AgiEngine::cmd_erase, + &AgiEngine::cmd_position, + &AgiEngine::cmd_position_f, + &AgiEngine::cmd_get_posn, + &AgiEngine::cmd_reposition, // 0x28 + &AgiEngine::cmd_set_view, + &AgiEngine::cmd_set_view_f, + &AgiEngine::cmd_set_loop, + &AgiEngine::cmd_set_loop_f, + &AgiEngine::cmd_fix_loop, + &AgiEngine::cmd_release_loop, + &AgiEngine::cmd_set_cel, + &AgiEngine::cmd_set_cel_f, // 0x30 + &AgiEngine::cmd_last_cel, + &AgiEngine::cmd_current_cel, + &AgiEngine::cmd_current_loop, + &AgiEngine::cmd_current_view, + &AgiEngine::cmd_number_of_loops, + &AgiEngine::cmd_set_priority, + &AgiEngine::cmd_set_priority_f, + &AgiEngine::cmd_release_priority, // 0x38 + &AgiEngine::cmd_get_priority, + &AgiEngine::cmd_stop_update, + &AgiEngine::cmd_start_update, + &AgiEngine::cmd_force_update, + &AgiEngine::cmd_ignore_horizon, + &AgiEngine::cmd_observe_horizon, + &AgiEngine::cmd_set_horizon, + &AgiEngine::cmd_object_on_water, // 0x40 + &AgiEngine::cmd_object_on_land, + &AgiEngine::cmd_object_on_anything, + &AgiEngine::cmd_ignore_objs, + &AgiEngine::cmd_observe_objs, + &AgiEngine::cmd_distance, + &AgiEngine::cmd_stop_cycling, + &AgiEngine::cmd_start_cycling, + &AgiEngine::cmd_normal_cycle, // 0x48 + &AgiEngine::cmd_end_of_loop, + &AgiEngine::cmd_reverse_cycle, + &AgiEngine::cmd_reverse_loop, + &AgiEngine::cmd_cycle_time, + &AgiEngine::cmd_stop_motion, + &AgiEngine::cmd_start_motion, + &AgiEngine::cmd_step_size, + &AgiEngine::cmd_step_time, // 0x50 + &AgiEngine::cmd_move_obj, + &AgiEngine::cmd_move_obj_f, + &AgiEngine::cmd_follow_ego, + &AgiEngine::cmd_wander, + &AgiEngine::cmd_normal_motion, + &AgiEngine::cmd_set_dir, + &AgiEngine::cmd_get_dir, + &AgiEngine::cmd_ignore_blocks, // 0x58 + &AgiEngine::cmd_observe_blocks, + &AgiEngine::cmd_block, + &AgiEngine::cmd_unblock, + &AgiEngine::cmd_get, + &AgiEngine::cmd_get_f, + &AgiEngine::cmd_drop, + &AgiEngine::cmd_put, + &AgiEngine::cmd_put_f, // 0x60 + &AgiEngine::cmd_get_room_f, + &AgiEngine::cmd_load_sound, + &AgiEngine::cmd_sound, + &AgiEngine::cmd_stop_sound, + &AgiEngine::cmd_print, + &AgiEngine::cmd_print_f, + &AgiEngine::cmd_display, + &AgiEngine::cmd_display_f, // 0x68 + &AgiEngine::cmd_clear_lines, + &AgiEngine::cmd_text_screen, + &AgiEngine::cmd_graphics, + &AgiEngine::cmd_set_cursor_char, + &AgiEngine::cmd_set_text_attribute, + &AgiEngine::cmd_shake_screen, + &AgiEngine::cmd_configure_screen, + &AgiEngine::cmd_status_line_on, // 0x70 + &AgiEngine::cmd_status_line_off, + &AgiEngine::cmd_set_string, + &AgiEngine::cmd_get_string, + &AgiEngine::cmd_word_to_string, + &AgiEngine::cmd_parse, + &AgiEngine::cmd_get_num, + &AgiEngine::cmd_prevent_input, + &AgiEngine::cmd_accept_input, // 0x78 + &AgiEngine::cmd_set_key, + &AgiEngine::cmd_add_to_pic, + &AgiEngine::cmd_add_to_pic_f, + &AgiEngine::cmd_status, + &AgiEngine::cmd_save_game, + &AgiEngine::cmd_load_game, + &AgiEngine::cmd_init_disk, + &AgiEngine::cmd_restart_game, // 0x80 + &AgiEngine::cmd_show_obj, + &AgiEngine::cmd_random, + &AgiEngine::cmd_program_control, + &AgiEngine::cmd_player_control, + &AgiEngine::cmd_obj_status_f, + &AgiEngine::cmd_quit, + &AgiEngine::cmd_show_mem, + &AgiEngine::cmd_pause, // 0x88 + &AgiEngine::cmd_echo_line, + &AgiEngine::cmd_cancel_line, + &AgiEngine::cmd_init_joy, + &AgiEngine::cmd_toggle_monitor, + &AgiEngine::cmd_version, + &AgiEngine::cmd_script_size, + &AgiEngine::cmd_set_game_id, + &AgiEngine::cmd_log, // 0x90 + &AgiEngine::cmd_set_scan_start, + &AgiEngine::cmd_reset_scan_start, + &AgiEngine::cmd_reposition_to, + &AgiEngine::cmd_reposition_to_f, + &AgiEngine::cmd_trace_on, + &AgiEngine::cmd_trace_info, + &AgiEngine::cmd_print_at, + &AgiEngine::cmd_print_at_v, // 0x98 + &AgiEngine::cmd_discard_view, // Opcode repeated from 0x20 ? + &AgiEngine::cmd_clear_text_rect, + &AgiEngine::cmd_set_upper_left, + &AgiEngine::cmd_set_menu, + &AgiEngine::cmd_set_menu_item, + &AgiEngine::cmd_submit_menu, + &AgiEngine::cmd_enable_item, + &AgiEngine::cmd_disable_item, // 0xa0 + &AgiEngine::cmd_menu_input, + &AgiEngine::cmd_show_obj_v, + &AgiEngine::cmd_open_dialogue, + &AgiEngine::cmd_close_dialogue, + &AgiEngine::cmd_mul_n, + &AgiEngine::cmd_mul_v, + &AgiEngine::cmd_div_n, + &AgiEngine::cmd_div_v, // 0xa8 + &AgiEngine::cmd_close_window, + &AgiEngine::cmd_set_simple, + &AgiEngine::cmd_push_script, + &AgiEngine::cmd_pop_script, + &AgiEngine::cmd_hold_key, + &AgiEngine::cmd_set_pri_base, + &AgiEngine::cmd_discard_sound, + &AgiEngine::cmd_hide_mouse, // 0xb0 + &AgiEngine::cmd_allow_menu, + &AgiEngine::cmd_show_mouse, + &AgiEngine::cmd_fence_mouse, + &AgiEngine::cmd_mouse_posn, + &AgiEngine::cmd_release_key, + &AgiEngine::cmd_adj_ego_move_to_x_y + }; + assert(ARRAYSIZE(_agiCommands) == ARRAYSIZE(tmp)); + for (int i = 0; i < ARRAYSIZE(tmp); ++i) + _agiCommands[i] = tmp[i]; +} /** * Execute a logic script @@ -1850,7 +1856,7 @@ int AgiEngine::runLogic(int n) { debugC(2, kDebugLevelScripts, "%s%s(%d %d %d)", st, logicNamesCmd[op].name, p[0], p[1], p[2]); - agiCommand[op](this, p); + (this->*_agiCommands[op])(p); ip += num; } @@ -1866,7 +1872,7 @@ int AgiEngine::runLogic(int n) { void AgiEngine::executeAgiCommand(uint8 op, uint8 *p) { debugC(2, kDebugLevelScripts, "%s(%d %d %d)", logicNamesCmd[op].name, p[0], p[1], p[2]); - agiCommand[op] (this, p); + (this->*_agiCommands[op])(p); } } // End of namespace Agi -- cgit v1.2.3 From e7da62763ecb26a35b2a4624226a8ee2bf79a853 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 21 Jun 2010 21:33:22 +0000 Subject: AGI: Turn timerHack and curLogic into AgiEngine members; get rid of some #defines svn-id: r50125 --- engines/agi/agi.cpp | 2 + engines/agi/agi.h | 2 + engines/agi/op_cmd.cpp | 642 ++++++++++++++++++++++++------------------------ engines/agi/op_test.cpp | 14 +- 4 files changed, 325 insertions(+), 335 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 0f5d3ee2f0..333b674379 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -571,6 +571,8 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _game.controllerOccured[i] = false; setupOpcodes(); + _curLogic = NULL; + _timerHack = 0; } void AgiEngine::initialize() { diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 02d3526f16..a67775cec6 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -1047,6 +1047,8 @@ private: typedef void (AgiEngine::*AgiCommand)(uint8 *); AgiCommand _agiCommands[183]; + AgiLogic *_curLogic; + int _timerHack; // Workaround for timer loop in MH1 logic 153 void setupOpcodes(); diff --git a/engines/agi/op_cmd.cpp b/engines/agi/op_cmd.cpp index e18b35d35d..072ab0114f 100644 --- a/engines/agi/op_cmd.cpp +++ b/engines/agi/op_cmd.cpp @@ -35,8 +35,6 @@ namespace Agi { -#define g_agi this - #define p0 (p[0]) #define p1 (p[1]) #define p2 (p[2]) @@ -45,20 +43,10 @@ namespace Agi { #define p5 (p[5]) #define p6 (p[6]) -#define game _game -#define g_sprites _sprites -#define g_sound _sound -#define g_gfx _gfx -#define g_picture _picture - -#define ip curLogic->cIP +#define ip _curLogic->cIP #define vt _game.viewTable[p0] #define vt_v _game.viewTable[_game.vars[p0]] -static struct AgiLogic *curLogic; - -int timerHack; // Workaround for timer loop in MH1 - #define _v _game.vars void AgiEngine::cmd_increment(uint8 *p) { @@ -74,14 +62,14 @@ void AgiEngine::cmd_decrement(uint8 *p) { void AgiEngine::cmd_assignn(uint8 *p) { _v[p0] = p1; - // WORKAROUND for a bug in fan game "Get outta SQ" + // WORKAROUND for a bug in fan _game "Get outta SQ" // Total number of points is stored in variable 7, which - // is then incorrectly assigned to 0. Thus, when the game + // is then incorrectly assigned to 0. Thus, when the _game // is restarted, "Points 0 of 0" is shown. We set the // variable to the correct value here // Fixes bug #1942476 - "AGI: Fan(Get Outta SQ) - Score // is lost on restart" - if (g_agi->getGameID() == GID_GETOUTTASQ && p0 == 7) + if (getGameID() == GID_GETOUTTASQ && p0 == 7) _v[p0] = 8; } @@ -122,7 +110,7 @@ void AgiEngine::cmd_div_v(uint8 *p) { } void AgiEngine::cmd_random(uint8 *p) { - _v[p2] = g_agi->_rnd->getRandomNumber(p1 - p0) + p0; + _v[p2] = _rnd->getRandomNumber(p1 - p0) + p0; } void AgiEngine::cmd_lindirectn(uint8 *p) { @@ -138,71 +126,71 @@ void AgiEngine::cmd_rindirect(uint8 *p) { } void AgiEngine::cmd_set(uint8 *p) { - g_agi->setflag(*p, true); + setflag(*p, true); } void AgiEngine::cmd_reset(uint8 *p) { - g_agi->setflag(*p, false); + setflag(*p, false); } void AgiEngine::cmd_toggle(uint8 *p) { - g_agi->setflag(*p, !g_agi->getflag(*p)); + setflag(*p, !getflag(*p)); } void AgiEngine::cmd_set_v(uint8 *p) { - g_agi->setflag(_v[p0], true); + setflag(_v[p0], true); } void AgiEngine::cmd_reset_v(uint8 *p) { - g_agi->setflag(_v[p0], false); + setflag(_v[p0], false); } void AgiEngine::cmd_toggle_v(uint8 *p) { - g_agi->setflag(_v[p0], !g_agi->getflag(_v[p0])); + setflag(_v[p0], !getflag(_v[p0])); } void AgiEngine::cmd_new_room(uint8 *p) { - g_agi->newRoom(p0); + newRoom(p0); // WORKAROUND: Works around intro skipping bug (#1737343) in Gold Rush. // Intro was skipped because the enter-keypress finalizing the entering // of the copy protection string (Copy protection is in logic.128) was // left over to the intro scene (Starts with room 73 i.e. logic.073). // The intro scene checks for any keys pressed and if it finds any it - // jumps to the game's start (Room 1 i.e. logic.001). We clear the + // jumps to the _game's start (Room 1 i.e. logic.001). We clear the // keyboard buffer when the intro sequence's first room (Room 73) is // loaded so that no keys from the copy protection scene can be left - // over to cause the intro to skip to the game's start. - if (g_agi->getGameID() == GID_GOLDRUSH && p0 == 73) - game.keypress = 0; + // over to cause the intro to skip to the _game's start. + if (getGameID() == GID_GOLDRUSH && p0 == 73) + _game.keypress = 0; } void AgiEngine::cmd_new_room_f(uint8 *p) { - g_agi->newRoom(_v[p0]); + newRoom(_v[p0]); } void AgiEngine::cmd_load_view(uint8 *p) { - g_agi->agiLoadResource(rVIEW, p0); + agiLoadResource(rVIEW, p0); } void AgiEngine::cmd_load_logic(uint8 *p) { - g_agi->agiLoadResource(rLOGIC, p0); + agiLoadResource(rLOGIC, p0); } void AgiEngine::cmd_load_sound(uint8 *p) { - g_agi->agiLoadResource(rSOUND, p0); + agiLoadResource(rSOUND, p0); } void AgiEngine::cmd_load_view_f(uint8 *p) { - g_agi->agiLoadResource(rVIEW, _v[p0]); + agiLoadResource(rVIEW, _v[p0]); } void AgiEngine::cmd_load_logic_f(uint8 *p) { - g_agi->agiLoadResource(rLOGIC, _v[p0]); + agiLoadResource(rLOGIC, _v[p0]); } void AgiEngine::cmd_discard_view(uint8 *p) { - g_agi->agiUnloadResource(rVIEW, p0); + agiUnloadResource(rVIEW, p0); } void AgiEngine::cmd_object_on_anything(uint8 *p) { @@ -242,7 +230,7 @@ void AgiEngine::cmd_ignore_blocks(uint8 *p) { } void AgiEngine::cmd_set_horizon(uint8 *p) { - game.horizon = p0; + _game.horizon = p0; } void AgiEngine::cmd_get_priority(uint8 *p) { @@ -260,15 +248,15 @@ void AgiEngine::cmd_set_priority(uint8 *p) { // It seems that in this scene, ego's priority is set to 8, but the priority of // the last dwarf with the soup bowls (view 152) is also set to 8, which causes // the dwarf to be drawn behind ego - // With this workaround, when the game scripts set the priority of view 152 + // With this workaround, when the _game scripts set the priority of view 152 // (seventh dwarf with soup bowls), ego's priority is set to 7 - // The game script itself sets priotity 8 for ego before she starts walking, + // The _game script itself sets priotity 8 for ego before she starts walking, // and then releases the fixed priority set on ego after ego is seated // Therefore, this workaround only affects that specific part of this scene // Ego is set to object 19 by script 54 - if (g_agi->getGameID() == GID_KQ4 && vt.currentView == 152) { - game.viewTable[19].flags |= FIXED_PRIORITY; - game.viewTable[19].priority = 7; + if (getGameID() == GID_KQ4 && vt.currentView == 152) { + _game.viewTable[19].flags |= FIXED_PRIORITY; + _game.viewTable[19].priority = 7; } } @@ -285,11 +273,11 @@ void AgiEngine::cmd_set_upper_left(uint8 *p) { // do nothing (AGI 2.917) } void AgiEngine::cmd_start_update(uint8 *p) { - g_agi->startUpdate(&vt); + startUpdate(&vt); } void AgiEngine::cmd_stop_update(uint8 *p) { - g_agi->stopUpdate(&vt); + stopUpdate(&vt); } void AgiEngine::cmd_current_view(uint8 *p) { @@ -310,29 +298,29 @@ void AgiEngine::cmd_last_cel(uint8 *p) { } void AgiEngine::cmd_set_cel(uint8 *p) { - g_agi->setCel(&vt, p1); + setCel(&vt, p1); vt.flags &= ~DONTUPDATE; } void AgiEngine::cmd_set_cel_f(uint8 *p) { - g_agi->setCel(&vt, _v[p1]); + setCel(&vt, _v[p1]); vt.flags &= ~DONTUPDATE; } void AgiEngine::cmd_set_view(uint8 *p) { - g_agi->setView(&vt, p1); + setView(&vt, p1); } void AgiEngine::cmd_set_view_f(uint8 *p) { - g_agi->setView(&vt, _v[p1]); + setView(&vt, _v[p1]); } void AgiEngine::cmd_set_loop(uint8 *p) { - g_agi->setLoop(&vt, p1); + setLoop(&vt, p1); } void AgiEngine::cmd_set_loop_f(uint8 *p) { - g_agi->setLoop(&vt, _v[p1]); + setLoop(&vt, _v[p1]); } void AgiEngine::cmd_number_of_loops(uint8 *p) { @@ -386,102 +374,102 @@ void AgiEngine::cmd_get_dir(uint8 *p) { } void AgiEngine::cmd_get_room_f(uint8 *p) { - _v[p1] = g_agi->objectGetLocation(_v[p0]); + _v[p1] = objectGetLocation(_v[p0]); } void AgiEngine::cmd_put(uint8 *p) { - g_agi->objectSetLocation(p0, _v[p1]); + objectSetLocation(p0, _v[p1]); } void AgiEngine::cmd_put_f(uint8 *p) { - g_agi->objectSetLocation(_v[p0], _v[p1]); + objectSetLocation(_v[p0], _v[p1]); } void AgiEngine::cmd_drop(uint8 *p) { - g_agi->objectSetLocation(p0, 0); + objectSetLocation(p0, 0); } void AgiEngine::cmd_get(uint8 *p) { - g_agi->objectSetLocation(p0, EGO_OWNED); + objectSetLocation(p0, EGO_OWNED); } void AgiEngine::cmd_get_f(uint8 *p) { - g_agi->objectSetLocation(_v[p0], EGO_OWNED); + objectSetLocation(_v[p0], EGO_OWNED); } void AgiEngine::cmd_word_to_string(uint8 *p) { - strcpy(game.strings[p0], game.egoWords[p1].word); + strcpy(_game.strings[p0], _game.egoWords[p1].word); } void AgiEngine::cmd_open_dialogue(uint8 *p) { - game.hasWindow = true; + _game.hasWindow = true; } void AgiEngine::cmd_close_dialogue(uint8 *p) { - game.hasWindow = false; + _game.hasWindow = false; } void AgiEngine::cmd_close_window(uint8 *p) { - g_agi->closeWindow(); + closeWindow(); } void AgiEngine::cmd_status_line_on(uint8 *p) { - game.statusLine = true; - g_agi->writeStatus(); + _game.statusLine = true; + writeStatus(); } void AgiEngine::cmd_status_line_off(uint8 *p) { - game.statusLine = false; - g_agi->writeStatus(); + _game.statusLine = false; + writeStatus(); } void AgiEngine::cmd_show_obj(uint8 *p) { - g_sprites->showObj(p0); + _sprites->showObj(p0); } void AgiEngine::cmd_show_obj_v(uint8 *p) { - g_sprites->showObj(_v[p0]); + _sprites->showObj(_v[p0]); } void AgiEngine::cmd_sound(uint8 *p) { - g_sound->startSound(p0, p1); + _sound->startSound(p0, p1); } void AgiEngine::cmd_stop_sound(uint8 *p) { - g_sound->stopSound(); + _sound->stopSound(); } void AgiEngine::cmd_menu_input(uint8 *p) { - g_agi->newInputMode(INPUT_MENU); + newInputMode(INPUT_MENU); } void AgiEngine::cmd_enable_item(uint8 *p) { - g_agi->_menu->setItem(p0, true); + _menu->setItem(p0, true); } void AgiEngine::cmd_disable_item(uint8 *p) { - g_agi->_menu->setItem(p0, false); + _menu->setItem(p0, false); } void AgiEngine::cmd_submit_menu(uint8 *p) { - g_agi->_menu->submit(); + _menu->submit(); } void AgiEngine::cmd_set_scan_start(uint8 *p) { - curLogic->sIP = curLogic->cIP; + _curLogic->sIP = _curLogic->cIP; } void AgiEngine::cmd_reset_scan_start(uint8 *p) { - curLogic->sIP = 2; + _curLogic->sIP = 2; } void AgiEngine::cmd_save_game(uint8 *p) { - game.simpleSave ? g_agi->saveGameSimple() : g_agi->saveGameDialog(); + _game.simpleSave ? saveGameSimple() : saveGameDialog(); } void AgiEngine::cmd_load_game(uint8 *p) { assert(1); - game.simpleSave ? g_agi->loadGameSimple() : g_agi->loadGameDialog(); + _game.simpleSave ? loadGameSimple() : loadGameDialog(); } void AgiEngine::cmd_init_disk(uint8 *p) { // do nothing @@ -497,7 +485,7 @@ void AgiEngine::cmd_trace_info(uint8 *p) { // do nothing } void AgiEngine::cmd_show_mem(uint8 *p) { - g_agi->messageBox("Enough memory"); + messageBox("Enough memory"); } void AgiEngine::cmd_init_joy(uint8 *p) { // do nothing @@ -508,8 +496,8 @@ void AgiEngine::cmd_script_size(uint8 *p) { } void AgiEngine::cmd_cancel_line(uint8 *p) { - g_agi->_game.inputBuffer[0] = 0; - g_agi->writePrompt(); + _game.inputBuffer[0] = 0; + writePrompt(); } // This implementation is based on observations of Amiga's Gold Rush. @@ -583,7 +571,7 @@ void AgiEngine::cmd_obj_status_f(uint8 *p) { vt_v.stepSize, cycleDesc, motionDesc); - g_agi->messageBox(msg); + messageBox(msg); } // unknown commands: @@ -595,43 +583,43 @@ void AgiEngine::cmd_obj_status_f(uint8 *p) { // unk_177: Disable menus completely -- j5 // unk_181: Deactivate keypressed control (default control of ego) void AgiEngine::cmd_set_simple(uint8 *p) { - if (!(g_agi->getFeatures() & (GF_AGI256 | GF_AGI256_2))) { - game.simpleSave = true; + if (!(getFeatures() & (GF_AGI256 | GF_AGI256_2))) { + _game.simpleSave = true; } else { // AGI256 and AGI256-2 use this unknown170 command to load 256 color pictures. // Load the picture. Similar to void AgiEngine::cmd_load_pic(uint8 *p). - g_sprites->eraseBoth(); - g_agi->agiLoadResource(rPICTURE, _v[p0]); + _sprites->eraseBoth(); + agiLoadResource(rPICTURE, _v[p0]); // Draw the picture. Similar to void AgiEngine::cmd_draw_pic(uint8 *p). - g_picture->decodePicture(_v[p0], false, true); - g_sprites->blitBoth(); - game.pictureShown = 0; + _picture->decodePicture(_v[p0], false, true); + _sprites->blitBoth(); + _game.pictureShown = 0; // Show the picture. Similar to void AgiEngine::cmd_show_pic(uint8 *p). - g_agi->setflag(fOutputMode, false); - g_agi->closeWindow(); - g_picture->showPic(); - game.pictureShown = 1; + setflag(fOutputMode, false); + closeWindow(); + _picture->showPic(); + _game.pictureShown = 1; // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } } void AgiEngine::cmd_pop_script(uint8 *p) { - if (g_agi->getVersion() >= 0x2915) { + if (getVersion() >= 0x2915) { report("pop.script\n"); } } void AgiEngine::cmd_hold_key(uint8 *p) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->_egoHoldKey = true; + if (getVersion() >= 0x3098) { + _egoHoldKey = true; } } void AgiEngine::cmd_discard_sound(uint8 *p) { - if (g_agi->getVersion() >= 0x2936) { + if (getVersion() >= 0x2936) { report("discard.sound\n"); } } @@ -644,14 +632,14 @@ void AgiEngine::cmd_hide_mouse(uint8 *p) { // to walk somewhere else than to the right using the mouse. // FIXME: Write a proper implementation using disassembly and // apply it to other games as well if applicable. - game.viewTable[0].flags &= ~ADJ_EGO_XY; + _game.viewTable[0].flags &= ~ADJ_EGO_XY; g_system->showMouse(false); } void AgiEngine::cmd_allow_menu(uint8 *p) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->setflag(fMenusWork, ((p0 != 0) ? true : false)); + if (getVersion() >= 0x3098) { + setflag(fMenusWork, ((p0 != 0) ? true : false)); } } @@ -660,14 +648,14 @@ void AgiEngine::cmd_show_mouse(uint8 *p) { } void AgiEngine::cmd_fence_mouse(uint8 *p) { - g_agi->_game.mouseFence.moveTo(p0, p1); - g_agi->_game.mouseFence.setWidth(p2 - p0); - g_agi->_game.mouseFence.setHeight(p3 - p1); + _game.mouseFence.moveTo(p0, p1); + _game.mouseFence.setWidth(p2 - p0); + _game.mouseFence.setHeight(p3 - p1); } void AgiEngine::cmd_release_key(uint8 *p) { - if (g_agi->getVersion() >= 0x3098) { - g_agi->_egoHoldKey = false; + if (getVersion() >= 0x3098) { + _egoHoldKey = false; } } @@ -693,28 +681,28 @@ void AgiEngine::cmd_adj_ego_move_to_x_y(uint8 *p) { // onto the ladder so this is more like it (Although that may be caused // by something else because this command doesn't do any flag manipulations // in the Amiga version - checked it with disassembly). - if (x != game.adjMouseX || y != game.adjMouseY) - game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY; + if (x != _game.adjMouseX || y != _game.adjMouseY) + _game.viewTable[EGO_VIEW_TABLE].flags &= ~ADJ_EGO_XY; - game.adjMouseX = x; - game.adjMouseY = y; + _game.adjMouseX = x; + _game.adjMouseY = y; debugC(4, kDebugLevelScripts, "adj.ego.move.to.x.y(%d, %d)", x, y); break; // TODO: Check where (if anywhere) the 0 arguments version is used case 0: default: - game.viewTable[0].flags |= ADJ_EGO_XY; + _game.viewTable[0].flags |= ADJ_EGO_XY; break; } } void AgiEngine::cmd_parse(uint8 *p) { _v[vWordNotFound] = 0; - g_agi->setflag(fEnteredCli, false); - g_agi->setflag(fSaidAcceptedInput, false); + setflag(fEnteredCli, false); + setflag(fSaidAcceptedInput, false); - g_agi->dictionaryWords(g_agi->agiSprintf(game.strings[p0])); + dictionaryWords(agiSprintf(_game.strings[p0])); } void AgiEngine::cmd_call(uint8 *p) { @@ -723,14 +711,14 @@ void AgiEngine::cmd_call(uint8 *p) { // CM: we don't save sIP because set.scan.start can be // used in a called script (fixes xmas demo) - oldCIP = curLogic->cIP; - oldLognum = game.lognum; + oldCIP = _curLogic->cIP; + oldLognum = _game.lognum; - g_agi->runLogic(p0); + runLogic(p0); - game.lognum = oldLognum; - curLogic = &game.logics[game.lognum]; - curLogic->cIP = oldCIP; + _game.lognum = oldLognum; + _curLogic = &_game.logics[_game.lognum]; + _curLogic->cIP = oldCIP; } void AgiEngine::cmd_call_f(uint8 *p) { @@ -739,11 +727,11 @@ void AgiEngine::cmd_call_f(uint8 *p) { void AgiEngine::cmd_draw_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== draw pic %d ===", _v[p0]); - g_sprites->eraseBoth(); - g_picture->decodePicture(_v[p0], true); - g_sprites->blitBoth(); - g_sprites->commitBoth(); - game.pictureShown = 0; + _sprites->eraseBoth(); + _picture->decodePicture(_v[p0], true); + _sprites->blitBoth(); + _sprites->commitBoth(); + _game.pictureShown = 0; debugC(6, kDebugLevelScripts, "--- end of draw pic %d ---", _v[p0]); // WORKAROUND for a script bug which exists in SQ1, logic scripts @@ -758,29 +746,29 @@ void AgiEngine::cmd_draw_pic(uint8 *p) { // above the ground), flag 103 is reset, thereby fixing this issue. Note // that this is a script bug and occurs in the original interpreter as well. // Fixes bug #1658514: AGI: SQ1 (2.2 DOS ENG) bizzare exploding roger - if (g_agi->getGameID() == GID_SQ1 && _v[p0] == 20) - g_agi->setflag(103, false); + if (getGameID() == GID_SQ1 && _v[p0] == 20) + setflag(103, false); // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } void AgiEngine::cmd_show_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "=== show pic ==="); - g_agi->setflag(fOutputMode, false); - g_agi->closeWindow(); - g_picture->showPic(); - game.pictureShown = 1; + setflag(fOutputMode, false); + closeWindow(); + _picture->showPic(); + _game.pictureShown = 1; debugC(6, kDebugLevelScripts, "--- end of show pic ---"); } void AgiEngine::cmd_load_pic(uint8 *p) { - g_sprites->eraseBoth(); - g_agi->agiLoadResource(rPICTURE, _v[p0]); - g_sprites->blitBoth(); - g_sprites->commitBoth(); + _sprites->eraseBoth(); + agiLoadResource(rPICTURE, _v[p0]); + _sprites->blitBoth(); + _sprites->commitBoth(); } void AgiEngine::cmd_discard_pic(uint8 *p) { @@ -791,28 +779,28 @@ void AgiEngine::cmd_discard_pic(uint8 *p) { void AgiEngine::cmd_overlay_pic(uint8 *p) { debugC(6, kDebugLevelScripts, "--- overlay pic ---"); - g_sprites->eraseBoth(); - g_picture->decodePicture(_v[p0], false); - g_sprites->blitBoth(); - game.pictureShown = 0; - g_sprites->commitBoth(); + _sprites->eraseBoth(); + _picture->decodePicture(_v[p0], false); + _sprites->blitBoth(); + _game.pictureShown = 0; + _sprites->commitBoth(); // Simulate slowww computer. Many effects rely on this - g_agi->pause(kPausePicture); + pause(kPausePicture); } void AgiEngine::cmd_show_pri_screen(uint8 *p) { - g_agi->_debug.priority = 1; - g_sprites->eraseBoth(); - g_picture->showPic(); - g_sprites->blitBoth(); + _debug.priority = 1; + _sprites->eraseBoth(); + _picture->showPic(); + _sprites->blitBoth(); - g_agi->waitKey(); + waitKey(); - g_agi->_debug.priority = 0; - g_sprites->eraseBoth(); - g_picture->showPic(); - g_sprites->blitBoth(); + _debug.priority = 0; + _sprites->eraseBoth(); + _picture->showPic(); + _sprites->blitBoth(); } void AgiEngine::cmd_animate_obj(uint8 *p) { @@ -830,7 +818,7 @@ void AgiEngine::cmd_unanimate_all(uint8 *p) { int i; for (i = 0; i < MAX_VIEWTABLE; i++) - game.viewTable[i].flags &= ~(ANIMATED | DRAWN); + _game.viewTable[i].flags &= ~(ANIMATED | DRAWN); } void AgiEngine::cmd_draw(uint8 *p) { @@ -843,19 +831,19 @@ void AgiEngine::cmd_draw(uint8 *p) { debugC(4, kDebugLevelScripts, "draw entry %d", vt.entry); vt.flags |= UPDATE; - if (g_agi->getVersion() >= 0x3000) { - g_agi->setLoop(&vt, vt.currentLoop); - g_agi->setCel(&vt, vt.currentCel); + if (getVersion() >= 0x3000) { + setLoop(&vt, vt.currentLoop); + setCel(&vt, vt.currentCel); } - g_agi->fixPosition(p0); + fixPosition(p0); vt.xPos2 = vt.xPos; vt.yPos2 = vt.yPos; vt.celData2 = vt.celData; - g_sprites->eraseUpdSprites(); + _sprites->eraseUpdSprites(); vt.flags |= DRAWN; - // WORKAROUND: This fixes a bug with AGI Fanmade game Space Trek. + // WORKAROUND: This fixes a bug with AGI Fanmade _game Space Trek. // The original workaround checked if AGI version was <= 2.440, which could // cause regressions with some AGI games. The original workaround no longer // works for Space Trek in ScummVM, as all fanmade games are set to use @@ -866,13 +854,13 @@ void AgiEngine::cmd_draw(uint8 *p) { // TODO: Investigate this further and check if any other fanmade AGI // games are affected. If yes, then it'd be best to set this for Space // Trek only - if (g_agi->getFeatures() & GF_FANMADE) // See Sarien bug #546562 + if (getFeatures() & GF_FANMADE) // See Sarien bug #546562 vt.flags |= ANIMATED; - g_sprites->blitUpdSprites(); + _sprites->blitUpdSprites(); vt.flags &= ~DONTUPDATE; - g_sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true); + _sprites->commitBlock(vt.xPos, vt.yPos - vt.ySize + 1, vt.xPos + vt.xSize - 1, vt.yPos, true); debugC(4, kDebugLevelScripts, "vt entry #%d flags = %02x", p0, vt.flags); } @@ -881,16 +869,16 @@ void AgiEngine::cmd_erase(uint8 *p) { if (~vt.flags & DRAWN) return; - g_sprites->eraseUpdSprites(); + _sprites->eraseUpdSprites(); if (vt.flags & UPDATE) { vt.flags &= ~DRAWN; } else { - g_sprites->eraseNonupdSprites(); + _sprites->eraseNonupdSprites(); vt.flags &= ~DRAWN; - g_sprites->blitNonupdSprites(); + _sprites->blitNonupdSprites(); } - g_sprites->blitUpdSprites(); + _sprites->blitUpdSprites(); int x1, y1, x2, y2; @@ -899,7 +887,7 @@ void AgiEngine::cmd_erase(uint8 *p) { y1 = MIN((int)MIN(vt.yPos, vt.yPos2), MIN(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); y2 = MAX((int)MAX(vt.yPos, vt.yPos2), MAX(vt.yPos - vt.celData->height, vt.yPos2 - vt.celData2->height)); - g_sprites->commitBlock(x1, y1, x2, y2, true); + _sprites->commitBlock(x1, y1, x2, y2, true); } void AgiEngine::cmd_position(uint8 *p) { @@ -919,8 +907,8 @@ void AgiEngine::cmd_position(uint8 *p) { // I haven't checked but if Space Trek solely abuses the position-command we wouldn't // strictly need the identical workaround in the position.v-command but it does make // for a nice symmetry. - if (g_agi->getFeatures() & GF_CLIPCOORDS) - g_agi->clipViewCoordinates(&vt); + if (getFeatures() & GF_CLIPCOORDS) + clipViewCoordinates(&vt); } void AgiEngine::cmd_position_f(uint8 *p) { @@ -930,13 +918,13 @@ void AgiEngine::cmd_position_f(uint8 *p) { // WORKAROUND: Part of the fix for bug #1659209 "AGI: Space Trek sprite duplication" // with an accompanying identical workaround in position-command (i.e. command 0x25). // See that workaround's comment for more in-depth information. - if (g_agi->getFeatures() & GF_CLIPCOORDS) - g_agi->clipViewCoordinates(&vt); + if (getFeatures() & GF_CLIPCOORDS) + clipViewCoordinates(&vt); } void AgiEngine::cmd_get_posn(uint8 *p) { - game.vars[p1] = (unsigned char)vt.xPos; - game.vars[p2] = (unsigned char)vt.yPos; + _game.vars[p1] = (unsigned char)vt.xPos; + _game.vars[p2] = (unsigned char)vt.yPos; } void AgiEngine::cmd_reposition(uint8 *p) { @@ -955,35 +943,35 @@ void AgiEngine::cmd_reposition(uint8 *p) { else vt.yPos += dy; - g_agi->fixPosition(p0); + fixPosition(p0); } void AgiEngine::cmd_reposition_to(uint8 *p) { vt.xPos = p1; vt.yPos = p2; vt.flags |= UPDATE_POS; - g_agi->fixPosition(p0); + fixPosition(p0); } void AgiEngine::cmd_reposition_to_f(uint8 *p) { vt.xPos = _v[p1]; vt.yPos = _v[p2]; vt.flags |= UPDATE_POS; - g_agi->fixPosition(p0); + fixPosition(p0); } void AgiEngine::cmd_add_to_pic(uint8 *p) { - g_sprites->addToPic(p0, p1, p2, p3, p4, p5, p6); + _sprites->addToPic(p0, p1, p2, p3, p4, p5, p6); } void AgiEngine::cmd_add_to_pic_f(uint8 *p) { - g_sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]); + _sprites->addToPic(_v[p0], _v[p1], _v[p2], _v[p3], _v[p4], _v[p5], _v[p6]); } void AgiEngine::cmd_force_update(uint8 *p) { - g_sprites->eraseBoth(); - g_sprites->blitBoth(); - g_sprites->commitBoth(); + _sprites->eraseBoth(); + _sprites->blitBoth(); + _sprites->commitBoth(); } void AgiEngine::cmd_reverse_loop(uint8 *p) { @@ -991,7 +979,7 @@ void AgiEngine::cmd_reverse_loop(uint8 *p) { vt.cycle = CYCLE_REV_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); vt.parm1 = p1; - g_agi->setflag(p1, false); + setflag(p1, false); } void AgiEngine::cmd_end_of_loop(uint8 *p) { @@ -999,20 +987,20 @@ void AgiEngine::cmd_end_of_loop(uint8 *p) { vt.cycle = CYCLE_END_OF_LOOP; vt.flags |= (DONTUPDATE | UPDATE | CYCLING); vt.parm1 = p1; - g_agi->setflag(p1, false); + setflag(p1, false); } void AgiEngine::cmd_block(uint8 *p) { debugC(4, kDebugLevelScripts, "x1=%d, y1=%d, x2=%d, y2=%d", p0, p1, p2, p3); - game.block.active = true; - game.block.x1 = p0; - game.block.y1 = p1; - game.block.x2 = p2; - game.block.y2 = p3; + _game.block.active = true; + _game.block.x1 = p0; + _game.block.y1 = p1; + _game.block.x2 = p2; + _game.block.y2 = p3; } void AgiEngine::cmd_unblock(uint8 *p) { - game.block.active = false; + _game.block.active = false; } void AgiEngine::cmd_normal_motion(uint8 *p) { @@ -1024,7 +1012,7 @@ void AgiEngine::cmd_stop_motion(uint8 *p) { vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only _v[vEgoDir] = 0; - game.playerControl = false; + _game.playerControl = false; } } @@ -1032,17 +1020,17 @@ void AgiEngine::cmd_start_motion(uint8 *p) { vt.motion = MOTION_NORMAL; if (p0 == 0) { // ego only _v[vEgoDir] = 0; - game.playerControl = true; + _game.playerControl = true; } } void AgiEngine::cmd_player_control(uint8 *p) { - game.playerControl = true; - game.viewTable[0].motion = MOTION_NORMAL; + _game.playerControl = true; + _game.viewTable[0].motion = MOTION_NORMAL; } void AgiEngine::cmd_program_control(uint8 *p) { - game.playerControl = false; + _game.playerControl = false; } void AgiEngine::cmd_follow_ego(uint8 *p) { @@ -1050,7 +1038,7 @@ void AgiEngine::cmd_follow_ego(uint8 *p) { vt.parm1 = p1 > vt.stepSize ? p1 : vt.stepSize; vt.parm2 = p2; vt.parm3 = 0xff; - g_agi->setflag(p2, false); + setflag(p2, false); vt.flags |= UPDATE; } @@ -1066,15 +1054,15 @@ void AgiEngine::cmd_move_obj(uint8 *p) { if (p3 != 0) vt.stepSize = p3; - g_agi->setflag(p4, false); + setflag(p4, false); vt.flags |= UPDATE; if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; // AGI 2.272 (ddp, xmas) doesn't call move_obj! - if (g_agi->getVersion() > 0x2272) - g_agi->moveObj(&vt); + if (getVersion() > 0x2272) + moveObj(&vt); } void AgiEngine::cmd_move_obj_f(uint8 *p) { @@ -1087,64 +1075,64 @@ void AgiEngine::cmd_move_obj_f(uint8 *p) { if (_v[p3] != 0) vt.stepSize = _v[p3]; - g_agi->setflag(p4, false); + setflag(p4, false); vt.flags |= UPDATE; if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; // AGI 2.272 (ddp, xmas) doesn't call move_obj! - if (g_agi->getVersion() > 0x2272) - g_agi->moveObj(&vt); + if (getVersion() > 0x2272) + moveObj(&vt); } void AgiEngine::cmd_wander(uint8 *p) { if (p0 == 0) - game.playerControl = false; + _game.playerControl = false; vt.motion = MOTION_WANDER; vt.flags |= UPDATE; } void AgiEngine::cmd_set_game_id(uint8 *p) { - if (curLogic->texts && (p0 - 1) <= curLogic->numTexts) - strncpy(game.id, curLogic->texts[p0 - 1], 8); + if (_curLogic->texts && (p0 - 1) <= _curLogic->numTexts) + strncpy(_game.id, _curLogic->texts[p0 - 1], 8); else - game.id[0] = 0; + _game.id[0] = 0; - report("Game ID: \"%s\"\n", game.id); + report("Game ID: \"%s\"\n", _game.id); } void AgiEngine::cmd_pause(uint8 *p) { - int tmp = game.clockEnabled; + int tmp = _game.clockEnabled; const char *b[] = { "Continue", NULL }; const char *b_ru[] = { "\x8f\xe0\xae\xa4\xae\xab\xa6\xa8\xe2\xec", NULL }; - game.clockEnabled = false; + _game.clockEnabled = false; - switch (g_agi->getLanguage()) { + switch (getLanguage()) { case Common::RU_RUS: - g_agi->selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru); + selectionBox(" \x88\xa3\xe0\xa0 \xae\xe1\xe2\xa0\xad\xae\xa2\xab\xa5\xad\xa0. \n\n\n", b_ru); break; default: - g_agi->selectionBox(" Game is paused. \n\n\n", b); + selectionBox(" Game is paused. \n\n\n", b); break; } - game.clockEnabled = tmp; + _game.clockEnabled = tmp; } void AgiEngine::cmd_set_menu(uint8 *p) { - debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); + debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts); - if (curLogic->texts != NULL && p0 <= curLogic->numTexts) - g_agi->_menu->add(curLogic->texts[p0 - 1]); + if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts) + _menu->add(_curLogic->texts[p0 - 1]); } void AgiEngine::cmd_set_menu_item(uint8 *p) { - debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, curLogic->numTexts); + debugC(4, kDebugLevelScripts, "text %02x of %02x", p0, _curLogic->numTexts); - if (curLogic->texts != NULL && p0 <= curLogic->numTexts) - g_agi->_menu->addItem(curLogic->texts[p0 - 1], p1); + if (_curLogic->texts != NULL && p0 <= _curLogic->numTexts) + _menu->addItem(_curLogic->texts[p0 - 1], p1); } void AgiEngine::cmd_version(uint8 *p) { @@ -1166,7 +1154,7 @@ void AgiEngine::cmd_version(uint8 *p) { sprintf(verMsg, TITLE " v%s", gScummVMVersion); - ver = g_agi->getVersion(); + ver = getVersion(); maj = (ver >> 12) & 0xf; min = ver & 0xfff; @@ -1184,65 +1172,65 @@ void AgiEngine::cmd_version(uint8 *p) { strncpy(q + 1 + gap, verMsg, strlen(verMsg)); sprintf(msg, q, maj, min); - g_agi->messageBox(msg); + messageBox(msg); } void AgiEngine::cmd_configure_screen(uint8 *p) { - game.lineMinPrint = p0; - game.lineUserInput = p1; - game.lineStatus = p2; + _game.lineMinPrint = p0; + _game.lineUserInput = p1; + _game.lineStatus = p2; } void AgiEngine::cmd_text_screen(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to text mode"); - game.gfxMode = false; + _game.gfxMode = false; // Simulates the "bright background bit" of the PC video // controller. - if (game.colorBg) - game.colorBg |= 0x08; + if (_game.colorBg) + _game.colorBg |= 0x08; - g_gfx->clearScreen(game.colorBg); + _gfx->clearScreen(_game.colorBg); } void AgiEngine::cmd_graphics(uint8 *p) { debugC(4, kDebugLevelScripts, "switching to graphics mode"); - if (!game.gfxMode) { - game.gfxMode = true; - g_gfx->clearScreen(0); - g_picture->showPic(); - g_agi->writeStatus(); - g_agi->writePrompt(); + if (!_game.gfxMode) { + _game.gfxMode = true; + _gfx->clearScreen(0); + _picture->showPic(); + writeStatus(); + writePrompt(); } } void AgiEngine::cmd_set_text_attribute(uint8 *p) { - game.colorFg = p0; - game.colorBg = p1; + _game.colorFg = p0; + _game.colorBg = p1; - if (game.gfxMode) { - if (game.colorBg != 0) { - game.colorFg = 0; - game.colorBg = 15; + if (_game.gfxMode) { + if (_game.colorBg != 0) { + _game.colorFg = 0; + _game.colorBg = 15; } } } void AgiEngine::cmd_status(uint8 *p) { - g_agi->inventory(); + inventory(); } void AgiEngine::cmd_quit(uint8 *p) { const char *buttons[] = { "Quit", "Continue", NULL }; - g_sound->stopSound(); + _sound->stopSound(); if (p0) { - g_agi->quitGame(); + quitGame(); } else { - if (g_agi->selectionBox - (" Quit the game, or continue? \n\n\n", buttons) == 0) { - g_agi->quitGame(); + if (selectionBox + (" Quit the _game, or continue? \n\n\n", buttons) == 0) { + quitGame(); } } } @@ -1251,21 +1239,21 @@ void AgiEngine::cmd_restart_game(uint8 *p) { const char *buttons[] = { "Restart", "Continue", NULL }; int sel; - g_sound->stopSound(); - sel = g_agi->getflag(fAutoRestart) ? 0 : - g_agi->selectionBox(" Restart game, or continue? \n\n\n", buttons); + _sound->stopSound(); + sel = getflag(fAutoRestart) ? 0 : + selectionBox(" Restart _game, or continue? \n\n\n", buttons); if (sel == 0) { - g_agi->_restartGame = true; - g_agi->setflag(fRestartGame, true); - g_agi->_menu->enableAll(); + _restartGame = true; + setflag(fRestartGame, true); + _menu->enableAll(); } } void AgiEngine::cmd_distance(uint8 *p) { int16 x1, y1, x2, y2, d; - VtEntry *v0 = &game.viewTable[p0]; - VtEntry *v1 = &game.viewTable[p1]; + VtEntry *v0 = &_game.viewTable[p0]; + VtEntry *v1 = &_game.viewTable[p1]; if (v0->flags & DRAWN && v1->flags & DRAWN) { x1 = v0->xPos + v0->xSize / 2; @@ -1288,7 +1276,7 @@ void AgiEngine::cmd_distance(uint8 *p) { // wouldn't chase Rosella around anymore. If it had worked correctly the zombie // wouldn't have come up at all or it would have come up and gone back down // immediately. The latter approach is the one implemented here. - if (g_agi->getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) { + if (getGameID() == GID_KQ4 && (_v[vCurRoom] == 16 || _v[vCurRoom] == 18) && p2 >= 221 && p2 <= 223) { // Rooms 16 and 18 are graveyards where three zombies come up at night. They use logics 16 and 18. // Variables 221-223 are used to save the distance between each zombie and Rosella. // Variables 155, 156 and 162 are used to save the state of each zombie in room 16. @@ -1316,18 +1304,18 @@ void AgiEngine::cmd_distance(uint8 *p) { void AgiEngine::cmd_accept_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "input normal"); - g_agi->newInputMode(INPUT_NORMAL); - game.inputEnabled = true; - g_agi->writePrompt(); + newInputMode(INPUT_NORMAL); + _game.inputEnabled = true; + writePrompt(); } void AgiEngine::cmd_prevent_input(uint8 *p) { debugC(4, kDebugLevelScripts | kDebugLevelInput, "no input"); - g_agi->newInputMode(INPUT_NONE); - game.inputEnabled = false; + newInputMode(INPUT_NONE); + _game.inputEnabled = false; - g_agi->clearPrompt(); + clearPrompt(); } void AgiEngine::cmd_get_string(uint8 *p) { @@ -1346,63 +1334,63 @@ void AgiEngine::cmd_get_string(uint8 *p) { if (col > 39) col = 39; - g_agi->newInputMode(INPUT_GETSTRING); + newInputMode(INPUT_GETSTRING); - if (curLogic->texts != NULL && curLogic->numTexts >= tex) { - int len = strlen(curLogic->texts[tex]); + if (_curLogic->texts != NULL && _curLogic->numTexts >= tex) { + int len = strlen(_curLogic->texts[tex]); - g_agi->printText(curLogic->texts[tex], 0, col, row, len, game.colorFg, game.colorBg); - g_agi->getString(col + len - 1, row, p4, p0); + printText(_curLogic->texts[tex], 0, col, row, len, _game.colorFg, _game.colorBg); + getString(col + len - 1, row, p4, p0); // SGEO: display input char - g_gfx->printCharacter((col + len), row, game.cursorChar, game.colorFg, game.colorBg); + _gfx->printCharacter((col + len), row, _game.cursorChar, _game.colorFg, _game.colorBg); } do { - g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); + mainCycle(); + } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame)); } void AgiEngine::cmd_get_num(uint8 *p) { debugC(4, kDebugLevelScripts, "%d %d", p0, p1); - g_agi->newInputMode(INPUT_GETSTRING); + newInputMode(INPUT_GETSTRING); - if (curLogic->texts != NULL && curLogic->numTexts >= (p0 - 1)) { - int len = strlen(curLogic->texts[p0 - 1]); + if (_curLogic->texts != NULL && _curLogic->numTexts >= (p0 - 1)) { + int len = strlen(_curLogic->texts[p0 - 1]); - g_agi->printText(curLogic->texts[p0 - 1], 0, 0, 22, len, game.colorFg, game.colorBg); - g_agi->getString(len - 1, 22, 3, MAX_STRINGS); + printText(_curLogic->texts[p0 - 1], 0, 0, 22, len, _game.colorFg, _game.colorBg); + getString(len - 1, 22, 3, MAX_STRINGS); // CM: display input char - g_gfx->printCharacter((p3 + len), 22, game.cursorChar, game.colorFg, game.colorBg); + _gfx->printCharacter((p3 + len), 22, _game.cursorChar, _game.colorFg, _game.colorBg); } do { - g_agi->mainCycle(); - } while (game.inputMode == INPUT_GETSTRING && !(g_agi->shouldQuit() || g_agi->_restartGame)); + mainCycle(); + } while (_game.inputMode == INPUT_GETSTRING && !(shouldQuit() || _restartGame)); - _v[p1] = atoi(game.strings[MAX_STRINGS]); + _v[p1] = atoi(_game.strings[MAX_STRINGS]); - debugC(4, kDebugLevelScripts, "[%s] -> %d", game.strings[MAX_STRINGS], _v[p1]); + debugC(4, kDebugLevelScripts, "[%s] -> %d", _game.strings[MAX_STRINGS], _v[p1]); - g_agi->clearLines(22, 22, game.colorBg); - g_agi->flushLines(22, 22); + clearLines(22, 22, _game.colorBg); + flushLines(22, 22); } void AgiEngine::cmd_set_cursor_char(uint8 *p) { - if (curLogic->texts != NULL && (p0 - 1) <= curLogic->numTexts) { - game.cursorChar = *curLogic->texts[p0 - 1]; + if (_curLogic->texts != NULL && (p0 - 1) <= _curLogic->numTexts) { + _game.cursorChar = *_curLogic->texts[p0 - 1]; } else { // default - game.cursorChar = '_'; + _game.cursorChar = '_'; } } void AgiEngine::cmd_set_key(uint8 *p) { int key; - if (game.lastController >= MAX_CONTROLLERS) { + if (_game.lastController >= MAX_CONTROLLERS) { warning("Number of set.keys exceeded %d", MAX_CONTROLLERS); return; } @@ -1411,32 +1399,32 @@ void AgiEngine::cmd_set_key(uint8 *p) { key = 256 * p1 + p0; - game.controllers[game.lastController].keycode = key; - game.controllers[game.lastController].controller = p2; - game.lastController++; + _game.controllers[_game.lastController].keycode = key; + _game.controllers[_game.lastController].controller = p2; + _game.lastController++; - game.controllerOccured[p2] = false; + _game.controllerOccured[p2] = false; } void AgiEngine::cmd_set_string(uint8 *p) { // CM: to avoid crash in Groza (str = 150) if (p0 > MAX_STRINGS) return; - strcpy(game.strings[p0], curLogic->texts[p1 - 1]); + strcpy(_game.strings[p0], _curLogic->texts[p1 - 1]); } void AgiEngine::cmd_display(uint8 *p) { int len = 40; - char *s = g_agi->wordWrapString(curLogic->texts[p2 - 1], &len); + char *s = wordWrapString(_curLogic->texts[p2 - 1], &len); - g_agi->printText(s, p1, 0, p0, 40, game.colorFg, game.colorBg); + printText(s, p1, 0, p0, 40, _game.colorFg, _game.colorBg); free(s); } void AgiEngine::cmd_display_f(uint8 *p) { - g_agi->printText(curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, game.colorFg, game.colorBg); + printText(_curLogic->texts[_v[p2] - 1], _v[p1], 0, _v[p0], 40, _game.colorFg, _game.colorBg); } void AgiEngine::cmd_clear_text_rect(uint8 *p) { @@ -1460,8 +1448,8 @@ void AgiEngine::cmd_clear_text_rect(uint8 *p) { if (y2 > GFX_HEIGHT) y2 = GFX_HEIGHT - 1; - g_gfx->drawRectangle(x1, y1, x2, y2, c); - g_gfx->flushBlock(x1, y1, x2, y2); + _gfx->drawRectangle(x1, y1, x2, y2, c); + _gfx->flushBlock(x1, y1, x2, y2); } void AgiEngine::cmd_toggle_monitor(uint8 *p) { @@ -1469,9 +1457,9 @@ void AgiEngine::cmd_toggle_monitor(uint8 *p) { } void AgiEngine::cmd_echo_line(uint8 *p) { - strcpy((char *)game.inputBuffer, (const char *)game.echoBuffer); - game.cursorPos = strlen((char *)game.inputBuffer); - game.hasPrompt = 0; + strcpy((char *)_game.inputBuffer, (const char *)_game.echoBuffer); + _game.cursorPos = strlen((char *)_game.inputBuffer); + _game.hasPrompt = 0; } void AgiEngine::cmd_clear_lines(uint8 *p) { @@ -1484,20 +1472,20 @@ void AgiEngine::cmd_clear_lines(uint8 *p) { // #1935838 and #1935842 l = (l <= 24) ? l : 24; - g_agi->clearLines(p0, l, p2); - g_agi->flushLines(p0, l); + clearLines(p0, l, p2); + flushLines(p0, l); } void AgiEngine::cmd_print(uint8 *p) { int n = p0 < 1 ? 1 : p0; - g_agi->print(curLogic->texts[n - 1], 0, 0, 0); + print(_curLogic->texts[n - 1], 0, 0, 0); } void AgiEngine::cmd_print_f(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; - g_agi->print(curLogic->texts[n - 1], 0, 0, 0); + print(_curLogic->texts[n - 1], 0, 0, 0); } void AgiEngine::cmd_print_at(uint8 *p) { @@ -1505,23 +1493,23 @@ void AgiEngine::cmd_print_at(uint8 *p) { debugC(4, kDebugLevelScripts, "%d %d %d %d", p0, p1, p2, p3); - g_agi->print(curLogic->texts[n - 1], p1, p2, p3); + print(_curLogic->texts[n - 1], p1, p2, p3); } void AgiEngine::cmd_print_at_v(uint8 *p) { int n = _v[p0] < 1 ? 1 : _v[p0]; - g_agi->print(curLogic->texts[n - 1], p1, p2, p3); + print(_curLogic->texts[n - 1], p1, p2, p3); } void AgiEngine::cmd_push_script(uint8 *p) { // We run AGIMOUSE always as a side effect - if (g_agi->getFeatures() & GF_AGIMOUSE || 1) { - game.vars[27] = g_agi->_mouse.button; - game.vars[28] = g_agi->_mouse.x / 2; - game.vars[29] = g_agi->_mouse.y; + if (getFeatures() & GF_AGIMOUSE || 1) { + _game.vars[27] = _mouse.button; + _game.vars[28] = _mouse.x / 2; + _game.vars[29] = _mouse.y; } else { - if (g_agi->getVersion() >= 0x2915) { + if (getVersion() >= 0x2915) { report("push.script\n"); } } @@ -1532,20 +1520,20 @@ void AgiEngine::cmd_set_pri_base(uint8 *p) { report("Priority base set to %d\n", p0); - // game.alt_pri = true; + // _game.alt_pri = true; x = (_HEIGHT - p0) * _HEIGHT / 10; for (i = 0; i < _HEIGHT; i++) { pri = (i - p0) < 0 ? 4 : (i - p0) * _HEIGHT / x + 5; if (pri > 15) pri = 15; - game.priTable[i] = pri; + _game.priTable[i] = pri; } } void AgiEngine::cmd_mouse_posn(uint8 *p) { - _v[p0] = WIN_TO_PIC_X(g_agi->_mouse.x); - _v[p1] = WIN_TO_PIC_Y(g_agi->_mouse.y); + _v[p0] = WIN_TO_PIC_X(_mouse.x); + _v[p1] = WIN_TO_PIC_Y(_mouse.y); } void AgiEngine::cmd_shake_screen(uint8 *p) { @@ -1554,8 +1542,8 @@ void AgiEngine::cmd_shake_screen(uint8 *p) { // AGIPAL uses shake.screen values between 100 and 109 to set the palette // (Checked the original AGIPAL-hack's shake.screen-routine's disassembly). if (p0 >= 100 && p0 < 110) { - if (g_agi->getFeatures() & GF_AGIPAL) { - g_gfx->setAGIPal(p0); + if (getFeatures() & GF_AGIPAL) { + _gfx->setAGIPal(p0); return; } else { warning("It looks like GF_AGIPAL flag is missing"); @@ -1564,21 +1552,21 @@ void AgiEngine::cmd_shake_screen(uint8 *p) { // Disables input while shaking to prevent bug // #1678230: AGI: Entering text while screen is shaking - bool originalValue = game.inputEnabled; - game.inputEnabled = false; + bool originalValue = _game.inputEnabled; + _game.inputEnabled = false; - g_gfx->shakeStart(); + _gfx->shakeStart(); - g_sprites->commitBoth(); // Fixes SQ1 demo + _sprites->commitBoth(); // Fixes SQ1 demo for (i = 4 * p0; i; i--) { - g_gfx->shakeScreen(i & 1); - g_gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); - g_agi->mainCycle(); + _gfx->shakeScreen(i & 1); + _gfx->flushBlock(0, 0, GFX_WIDTH - 1, GFX_HEIGHT - 1); + mainCycle(); } - g_gfx->shakeEnd(); + _gfx->shakeEnd(); // Sets input back to what it was - game.inputEnabled = originalValue; + _game.inputEnabled = originalValue; } void AgiEngine::setupOpcodes() { @@ -1797,12 +1785,12 @@ int AgiEngine::runLogic(int n) { } _game.lognum = n; - curLogic = &_game.logics[_game.lognum]; + _curLogic = &_game.logics[_game.lognum]; - code = curLogic->data; - curLogic->cIP = curLogic->sIP; + code = _curLogic->data; + _curLogic->cIP = _curLogic->sIP; - timerHack = 0; + _timerHack = 0; while (ip < _game.logics[n].size && !(shouldQuit() || _restartGame)) { if (_debug.enabled) { if (_debug.steps > 0) { @@ -1837,10 +1825,10 @@ int AgiEngine::runLogic(int n) { // timer must keep running even in goto loops, // but AGI engine can't do that :( - if (timerHack > 20) { + if (_timerHack > 20) { pollTimer(); updateTimer(); - timerHack = 0; + _timerHack = 0; } break; case 0x00: // return diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index f10cdd3f17..6967f6c665 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -51,8 +51,6 @@ static AgiEngine *g_agi; #define testHas(obj) (g_agi->objectGetLocation(obj) == EGO_OWNED) #define testObjInRoom(obj, v) (g_agi->objectGetLocation(obj) == g_agi->getvar(v)) -extern int timerHack; // For the timer loop in MH1 logic 153 - static uint8 testCompareStrings(uint8 s1, uint8 s2) { char ms1[MAX_STRINGLEN]; char ms2[MAX_STRINGLEN]; @@ -263,32 +261,32 @@ int AgiEngine::testIfCode(int lognum) { case 0x01: ec = testEqual(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x02: ec = testEqual(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x03: ec = testLess(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x04: ec = testLess(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x05: ec = testGreater(p[0], p[1]); if (p[0] == 11) - timerHack++; + _timerHack++; break; case 0x06: ec = testGreater(p[0], getvar(p[1])); if (p[0] == 11 || p[1] == 11) - timerHack++; + _timerHack++; break; case 0x07: ec = testIsSet(p[0]); -- cgit v1.2.3 From c7a9865a73eae69e73fb8a67bffbbe2286074a8c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 21 Jun 2010 21:33:45 +0000 Subject: AGI: Change a static var to member var AgiEngine::_lastTickTimer svn-id: r50126 --- engines/agi/agi.cpp | 10 +++++----- engines/agi/agi.h | 1 + 2 files changed, 6 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 333b674379..6a359944e1 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -272,20 +272,19 @@ void AgiEngine::processEvents() { } void AgiEngine::pollTimer() { - static uint32 m = 0; uint32 dm; - if (_tickTimer < m) - m = 0; + if (_tickTimer < _lastTickTimer) + _lastTickTimer = 0; - while ((dm = _tickTimer - m) < 5) { + while ((dm = _tickTimer - _lastTickTimer) < 5) { processEvents(); if (_console->isAttached()) _console->onFrame(); _system->delayMillis(10); _system->updateScreen(); } - m = _tickTimer; + _lastTickTimer = _tickTimer; } void AgiEngine::agiTimerFunctionLow(void *refCon) { @@ -543,6 +542,7 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _allowSynthetic = false; _tickTimer = 0; + _lastTickTimer = 0; _intobj = NULL; diff --git a/engines/agi/agi.h b/engines/agi/agi.h index a67775cec6..301ffa1b6c 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -816,6 +816,7 @@ public: private: uint32 _tickTimer; + uint32 _lastTickTimer; int _keyQueue[KEY_QUEUE_SIZE]; int _keyQueueStart; -- cgit v1.2.3 From 49448af6cb2613460fe37caf79bdb1ed4c206715 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 21 Jun 2010 21:34:06 +0000 Subject: AGI: Turn some more AGI static functions into AgiEngine methods svn-id: r50127 --- engines/agi/agi.h | 11 +++++++ engines/agi/op_test.cpp | 87 +++++++++++++++++++++---------------------------- 2 files changed, 48 insertions(+), 50 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 301ffa1b6c..166470e6e4 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -939,6 +939,17 @@ public: int testIfCode(int); void executeAgiCommand(uint8, uint8 *); +private: + // Some submethods of testIfCode + uint8 testObjRight(uint8, uint8, uint8, uint8, uint8); + uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8); + uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8); + uint8 testPosn(uint8, uint8, uint8, uint8, uint8); + uint8 testSaid(uint8, uint8 *); + uint8 testController(uint8); + uint8 testKeypressed(); + uint8 testCompareStrings(uint8, uint8); + // View private: diff --git a/engines/agi/op_test.cpp b/engines/agi/op_test.cpp index 6967f6c665..ab4f6cadc5 100644 --- a/engines/agi/op_test.cpp +++ b/engines/agi/op_test.cpp @@ -29,35 +29,23 @@ namespace Agi { -static uint8 testObjRight(uint8, uint8, uint8, uint8, uint8); -static uint8 testObjCentre(uint8, uint8, uint8, uint8, uint8); -static uint8 testObjInBox(uint8, uint8, uint8, uint8, uint8); -static uint8 testPosn(uint8, uint8, uint8, uint8, uint8); -static uint8 testSaid(uint8, uint8 *); -static uint8 testController(uint8); -static uint8 testKeypressed(); -static uint8 testCompareStrings(uint8, uint8); - -static AgiEngine *g_agi; -#define game g_agi->_game - -#define ip (game.logics[lognum].cIP) -#define code (game.logics[lognum].data) - -#define testEqual(v1, v2) (g_agi->getvar(v1) == (v2)) -#define testLess(v1, v2) (g_agi->getvar(v1) < (v2)) -#define testGreater(v1, v2) (g_agi->getvar(v1) > (v2)) -#define testIsSet(flag) (g_agi->getflag(flag)) -#define testHas(obj) (g_agi->objectGetLocation(obj) == EGO_OWNED) -#define testObjInRoom(obj, v) (g_agi->objectGetLocation(obj) == g_agi->getvar(v)) - -static uint8 testCompareStrings(uint8 s1, uint8 s2) { +#define ip (_game.logics[lognum].cIP) +#define code (_game.logics[lognum].data) + +#define testEqual(v1, v2) (getvar(v1) == (v2)) +#define testLess(v1, v2) (getvar(v1) < (v2)) +#define testGreater(v1, v2) (getvar(v1) > (v2)) +#define testIsSet(flag) (getflag(flag)) +#define testHas(obj) (objectGetLocation(obj) == EGO_OWNED) +#define testObjInRoom(obj, v) (objectGetLocation(obj) == getvar(v)) + +uint8 AgiEngine::testCompareStrings(uint8 s1, uint8 s2) { char ms1[MAX_STRINGLEN]; char ms2[MAX_STRINGLEN]; int j, k, l; - strcpy(ms1, game.strings[s1]); - strcpy(ms2, game.strings[s2]); + strcpy(ms1, _game.strings[s1]); + strcpy(ms2, _game.strings[s2]); l = strlen(ms1); for (k = 0, j = 0; k < l; k++) { @@ -104,16 +92,16 @@ static uint8 testCompareStrings(uint8 s1, uint8 s2) { return !strcmp(ms1, ms2); } -static uint8 testKeypressed() { - int x = game.keypress; +uint8 AgiEngine::testKeypressed() { + int x = _game.keypress; - game.keypress = 0; + _game.keypress = 0; if (!x) { - InputMode mode = game.inputMode; + InputMode mode = _game.inputMode; - game.inputMode = INPUT_NONE; - g_agi->mainCycle(); - game.inputMode = mode; + _game.inputMode = INPUT_NONE; + mainCycle(); + _game.inputMode = mode; } if (x) @@ -122,12 +110,12 @@ static uint8 testKeypressed() { return x; } -static uint8 testController(uint8 cont) { - return (game.controllerOccured[cont] ? 1 : 0); +uint8 AgiEngine::testController(uint8 cont) { + return (_game.controllerOccured[cont] ? 1 : 0); } -static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; uint8 r; r = v->xPos >= x1 && v->yPos >= y1 && v->xPos <= x2 && v->yPos <= y2; @@ -137,35 +125,35 @@ static uint8 testPosn(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { return r; } -static uint8 testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjInBox(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos >= x1 && v->yPos >= y1 && v->xPos + v->xSize - 1 <= x2 && v->yPos <= y2; } // if n is in centre of box -static uint8 testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjCentre(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos + v->xSize / 2 >= x1 && v->xPos + v->xSize / 2 <= x2 && v->yPos >= y1 && v->yPos <= y2; } // if nect N is in right corner -static uint8 testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { - VtEntry *v = &game.viewTable[n]; +uint8 AgiEngine::testObjRight(uint8 n, uint8 x1, uint8 y1, uint8 x2, uint8 y2) { + VtEntry *v = &_game.viewTable[n]; return v->xPos + v->xSize - 1 >= x1 && v->xPos + v->xSize - 1 <= x2 && v->yPos >= y1 && v->yPos <= y2; } // When player has entered something, it is parsed elsewhere -static uint8 testSaid(uint8 nwords, uint8 *cc) { - int c, n = game.numEgoWords; +uint8 AgiEngine::testSaid(uint8 nwords, uint8 *cc) { + int c, n = _game.numEgoWords; int z = 0; - if (g_agi->getflag(fSaidAcceptedInput) || !g_agi->getflag(fEnteredCli)) + if (getflag(fSaidAcceptedInput) || !getflag(fEnteredCli)) return false; // FR: @@ -196,7 +184,7 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { case 1: // any word break; default: - if (game.egoWords[c].id != z) + if (_game.egoWords[c].id != z) return false; break; } @@ -211,13 +199,12 @@ static uint8 testSaid(uint8 nwords, uint8 *cc) { if (nwords != 0 && READ_LE_UINT16(cc) != 9999) return false; - g_agi->setflag(fSaidAcceptedInput, true); + setflag(fSaidAcceptedInput, true); return true; } int AgiEngine::testIfCode(int lognum) { - g_agi = this; int ec = true; int retval = true; uint8 op = 0; @@ -317,7 +304,7 @@ int AgiEngine::testIfCode(int lognum) { ip++; // skip num_words opcode break; case 0x0F: - debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", game.strings[p[0]], game.strings[p[1]]); + debugC(7, kDebugLevelScripts, "comparing [%s], [%s]", _game.strings[p[0]], _game.strings[p[1]]); ec = testCompareStrings(p[0], p[1]); break; case 0x10: @@ -336,7 +323,7 @@ int AgiEngine::testIfCode(int lognum) { // This command is used at least in the Amiga version of Gold Rush! v2.05 1989-03-09 // (AGI 2.316) in logics 1, 3, 5, 6, 137 and 192 (Logic.192 revealed this command's nature). // TODO: Check this command's implementation using disassembly just to be sure. - ec = game.viewTable[0].flags & ADJ_EGO_XY; + ec = _game.viewTable[0].flags & ADJ_EGO_XY; debugC(7, kDebugLevelScripts, "op_test: in.motion.using.mouse = %s (Amiga-specific testcase 19)", ec ? "true" : "false"); break; default: -- cgit v1.2.3 From bbad3f333a9227ccb1de633a0fe92d9e01ad7bb3 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 21 Jun 2010 21:36:36 +0000 Subject: Patch #1956501: "GUI/LAUNCHER: Midi device selection" svn-id: r50128 --- engines/agi/agi.cpp | 8 ++++---- engines/agi/preagi.cpp | 4 ++-- engines/agi/sound_midi.cpp | 4 ++-- engines/agos/agos.cpp | 6 +++--- engines/draci/draci.cpp | 8 ++++---- engines/gob/gob.cpp | 4 ++-- engines/groovie/music.cpp | 20 ++++++++++---------- engines/groovie/script.cpp | 6 +++--- engines/kyra/kyra_v1.cpp | 12 ++++++------ engines/lure/sound.cpp | 8 ++++---- engines/m4/m4.cpp | 6 +++--- engines/made/made.cpp | 8 ++++---- engines/mohawk/sound.cpp | 4 ++-- engines/parallaction/parallaction_br.cpp | 4 ++-- engines/parallaction/parallaction_ns.cpp | 5 ++--- engines/queen/music.cpp | 9 +++++---- engines/saga/music.cpp | 4 ++-- engines/saga/music.h | 6 +++--- engines/sci/sound/drivers/fb01.cpp | 4 ++-- engines/sci/sound/drivers/midi.cpp | 6 +++--- engines/sci/sound/iterator/core.cpp | 2 +- engines/sci/sound/music.cpp | 16 +++++----------- engines/scumm/detection.cpp | 2 +- engines/scumm/detection_tables.h | 20 ++++++++++---------- engines/scumm/scumm.cpp | 32 ++++++++++++++++---------------- engines/sky/sky.cpp | 10 +++++----- engines/tinsel/tinsel.cpp | 8 ++++---- engines/touche/midi.cpp | 6 +++--- 28 files changed, 113 insertions(+), 119 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index 6a359944e1..a39725a973 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -587,14 +587,14 @@ void AgiEngine::initialize() { } else if (getPlatform() == Common::kPlatformCoCo3) { _soundemu = SOUND_EMU_COCO3; } else { - switch (MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_PCJR | MDT_ADLIB | MDT_MIDI)) { - case MD_PCSPK: + switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) { + case MT_PCSPK: _soundemu = SOUND_EMU_PC; break; - case MD_PCJR: + case MT_PCJR: _soundemu = SOUND_EMU_PCJR; break; - case MD_ADLIB: + case MT_ADLIB: _soundemu = SOUND_EMU_NONE; break; default: diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp index 35285798d4..1a5698dffc 100644 --- a/engines/agi/preagi.cpp +++ b/engines/agi/preagi.cpp @@ -68,8 +68,8 @@ void PreAgiEngine::initialize() { // drivers, and I'm not sure what they are. For now, they might // as well be called "PC Speaker" and "Not PC Speaker". - switch (MidiDriver::detectMusicDriver(MDT_PCSPK)) { - case MD_PCSPK: + switch (MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK))) { + case MT_PCSPK: _soundemu = SOUND_EMU_PC; break; default: diff --git a/engines/agi/sound_midi.cpp b/engines/agi/sound_midi.cpp index 551df527cc..57c5d54b27 100644 --- a/engines/agi/sound_midi.cpp +++ b/engines/agi/sound_midi.cpp @@ -71,8 +71,8 @@ MIDISound::MIDISound(uint8 *data, uint32 len, int resnum, SoundMgr &manager) : A } SoundGenMIDI::SoundGenMIDI(AgiEngine *vm, Audio::Mixer *pMixer) : SoundGen(vm, pMixer), _parser(0), _isPlaying(false), _passThrough(false), _isGM(false) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB); - _driver = MidiDriver::createMidi(midiDriver); + DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB); + _driver = MidiDriver::createMidi(dev); memset(_channel, 0, sizeof(_channel)); memset(_channelVolume, 255, sizeof(_channelVolume)); diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 926b3a8972..481c73dc5c 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -557,10 +557,10 @@ Common::Error AGOSEngine::init() { (getPlatform() == Common::kPlatformPC)) { // Setup midi driver - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM)); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (_nativeMT32) { _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index cbf878279b..9e1e7033bb 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -127,11 +127,11 @@ int DraciEngine::init() { _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency); _sound = new Sound(_mixer); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - _midiDriver = MidiDriver::createMidi(midiDriver); + _midiDriver = MidiDriver::createMidi(dev); if (native_mt32) _midiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index e3472e9fe1..fba616b166 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -345,8 +345,8 @@ void GobEngine::pauseGame() { } bool GobEngine::initGameParts() { - _noMusic = MidiDriver::parseMusicDriver(ConfMan.get("music_driver")) == MD_NULL; - + // just detect some devices some of which will be always there if the music is not disabled + _noMusic = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB) ? false : true; _saveLoad = 0; _global = new Global(this); diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 2ea7454256..7166432e02 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -386,8 +386,8 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) _midiParser = MidiParser::createParser_XMIDI(); // Create the driver - MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = createMidi(dev); this->open(); // Set the parser's driver @@ -402,9 +402,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) } // Load the Global Timbre Library - if (driver == MD_ADLIB) { + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { // MIDI through AdLib - _musicType = MD_ADLIB; + _musicType = MT_ADLIB; loadTimbres(gtlName + ".ad"); // Setup the percussion channel @@ -412,9 +412,9 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) if (_timbres[i].bank == 0x7F) setTimbreAD(9, _timbres[i]); } - } else if ((driver == MD_MT32) || ConfMan.getBool("native_mt32")) { + } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { // MT-32 - _musicType = MD_MT32; + _musicType = MT_MT32; loadTimbres(gtlName + ".mt"); } else { // GM @@ -455,9 +455,9 @@ void MusicPlayerXMI::send(uint32 b) { for (int i = 0; i < numTimbres; i++) { if ((_timbres[i].bank == _chanBanks[chan]) && (_timbres[i].patch == patch)) { - if (_musicType == MD_ADLIB) { + if (_musicType == MT_ADLIB) { setTimbreAD(chan, _timbres[i]); - } else if (_musicType == MD_MT32) { + } else if (_musicType == MT_MT32) { setTimbreMT(chan, _timbres[i]); } return; @@ -682,8 +682,8 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) { _midiParser = MidiParser::createParser_SMF(); // Create the driver - MidiDriverType driver = detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = createMidi(driver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = createMidi(dev); this->open(); // Set the parser's driver diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 297da6ccc2..08df5e7a83 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -86,11 +86,11 @@ Script::Script(GroovieEngine *vm, EngineVersion version) : } // Initialize the music type variable - int midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - if (midiDriver == MD_ADLIB) { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { // MIDI through AdLib setVariable(0x100, 0); - } else if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")) { + } else if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) { // MT-32 setVariable(0x100, 2); } else { diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 00b32425c2..970851c127 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -106,7 +106,7 @@ Common::Error KyraEngine_v1::init() { if (!_flags.useDigSound) { // We prefer AdLib over MIDI, since generally AdLib is better supported - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_MIDI | MDT_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI | MDT_PREFER_MT32); if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) @@ -120,24 +120,24 @@ Common::Error KyraEngine_v1::init() { _sound = new SoundTownsPC98_v2(this, _mixer); } else if (_flags.platform == Common::kPlatformAmiga) { _sound = new SoundAmiga(this, _mixer); - } else if (midiDriver == MD_ADLIB) { + } else if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _sound = new SoundAdLibPC(this, _mixer); } else { Sound::kType type; - if (midiDriver == MD_PCSPK) + if (MidiDriver::getMusicType(dev) == MT_PCSPK) type = Sound::kPCSpkr; - else if (midiDriver == MD_MT32 || ConfMan.getBool("native_mt32")) + else if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32")) type = Sound::kMidiMT32; else type = Sound::kMidiGM; MidiDriver *driver = 0; - if (midiDriver == MD_PCSPK) { + if (MidiDriver::getMusicType(dev) == MT_PCSPK) { driver = new MidiDriver_PCSpeaker(_mixer); } else { - driver = MidiDriver::createMidi(midiDriver); + driver = MidiDriver::createMidi(dev); if (type == Sound::kMidiMT32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp index e725b7c31a..1b306b5021 100644 --- a/engines/lure/sound.cpp +++ b/engines/lure/sound.cpp @@ -50,13 +50,13 @@ SoundManager::SoundManager() { _soundData = NULL; _paused = false; - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _isRoland = midiDriver != MD_ADLIB; - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _isRoland = MidiDriver::getMusicType(dev) != MT_ADLIB; + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); Common::set_to(_channelsInUse, _channelsInUse + NUM_CHANNELS, false); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); int statusCode = _driver->open(); if (statusCode) { warning("Sound driver returned error code %d", statusCode); diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 446f2bf974..8063044205 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -156,10 +156,10 @@ Common::Error MadsM4Engine::run() { // Initialize backend _screen = new M4Surface(true); // Special form for creating screen reference - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (native_mt32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 54e2189471..b983e87cc2 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -97,11 +97,11 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _script = new ScriptInterpreter(this); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver *driver = MidiDriver::createMidi(dev); if (native_mt32) driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index b84573f011..5e1ea8cdb2 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -27,12 +27,12 @@ #include "common/util.h" +#include "sound/musicplugin.h" #include "sound/audiostream.h" #include "sound/decoders/mp3.h" #include "sound/decoders/raw.h" #include "sound/decoders/wave.h" - namespace Mohawk { Sound::Sound(MohawkEngine* vm) : _vm(vm) { @@ -79,7 +79,7 @@ void Sound::initMidi() { // Let's get our MIDI parser/driver _midiParser = MidiParser::createParser_SMF(); - _midiDriver = MidiDriver::createMidi(MidiDriver::detectMusicDriver(MDT_ADLIB|MDT_MIDI)); + _midiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB|MDT_MIDI)); // Set up everything! _midiDriver->open(); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 153ea1541d..6dbf526c96 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -61,8 +61,8 @@ Common::Error Parallaction_br::init() { _disk = new DosDisk_br(this); } _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_br(this, driver); } else { _disk = new AmigaDisk_br(this); diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index c1d6c9367a..7e06aaa5ab 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -24,7 +24,6 @@ */ #include "common/system.h" - #include "common/config-manager.h" #include "parallaction/parallaction.h" @@ -167,8 +166,8 @@ Common::Error Parallaction_ns::init() { _disk->init(); if (getPlatform() == Common::kPlatformPC) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - MidiDriver *driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_ns(this, driver); _soundManI->setMusicVolume(ConfMan.getInt("music_volume")); } else { diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp index b4b9210616..2bbbd53568 100644 --- a/engines/queen/music.cpp +++ b/engines/queen/music.cpp @@ -34,6 +34,7 @@ #include "sound/midiparser.h" + namespace Queen { extern MidiDriver *C_Player_CreateAdLibMidiDriver(Audio::Mixer *); @@ -45,9 +46,9 @@ MidiMusic::MidiMusic(QueenEngine *vm) _queuePos = _lastSong = _currentSong = 0; queueClear(); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _adlib = (midiDriver == MD_ADLIB); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI | MDT_PREFER_MT32); + _adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); const char *musicDataFile; if (vm->resource()->isDemo()) { @@ -72,7 +73,7 @@ MidiMusic::MidiMusic(QueenEngine *vm) // } _driver = C_Player_CreateAdLibMidiDriver(vm->_mixer); } else { - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (_nativeMT32) { _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); } diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index 8b8f26d5a0..dbe79a3e72 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -47,8 +47,8 @@ MusicDriver::MusicDriver() : _isGM(false) { _masterVolume = 0; _nativeMT32 = ConfMan.getBool("native_mt32"); - _driverType = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _driver = MidiDriver::createMidi(_driverType); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _driver = MidiDriver::createMidi(dev); if (isMT32()) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/saga/music.h b/engines/saga/music.h index cb068cd835..5cce3d4c04 100644 --- a/engines/saga/music.h +++ b/engines/saga/music.h @@ -52,8 +52,8 @@ public: void setVolume(int volume); int getVolume() { return _masterVolume; } - bool isAdlib() { return _driverType == MD_ADLIB; } - bool isMT32() { return _driverType == MD_MT32 || _nativeMT32; } + bool isAdlib() { return _driverType == MT_ADLIB; } + bool isMT32() { return _driverType == MT_MT32 || _nativeMT32; } void setGM(bool isGM) { _isGM = isGM; } //MidiDriver interface implementation @@ -78,7 +78,7 @@ protected: MidiChannel *_channel[16]; MidiDriver *_driver; - MidiDriverType _driverType; + MusicType _driverType; byte _channelVolume[16]; bool _isGM; bool _nativeMT32; diff --git a/engines/sci/sound/drivers/fb01.cpp b/engines/sci/sound/drivers/fb01.cpp index 7e9fbd51a1..ab9b2e3df5 100644 --- a/engines/sci/sound/drivers/fb01.cpp +++ b/engines/sci/sound/drivers/fb01.cpp @@ -128,8 +128,8 @@ private: }; MidiPlayer_Fb01::MidiPlayer_Fb01(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _timerParam(NULL), _timerProc(NULL) { - MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI); - _driver = createMidi(midiType); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI); + _driver = createMidi(dev); _sysExBuf[0] = 0x43; _sysExBuf[1] = 0x75; diff --git a/engines/sci/sound/drivers/midi.cpp b/engines/sci/sound/drivers/midi.cpp index 625874eea1..1ef0781906 100644 --- a/engines/sci/sound/drivers/midi.cpp +++ b/engines/sci/sound/drivers/midi.cpp @@ -120,10 +120,10 @@ private: }; MidiPlayer_Midi::MidiPlayer_Midi(SciVersion version) : MidiPlayer(version), _playSwitch(true), _masterVolume(15), _isMt32(false), _hasReverb(false), _isOldPatchFormat(true) { - MidiDriverType midiType = MidiDriver::detectMusicDriver(MDT_MIDI); - _driver = createMidi(midiType); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI); + _driver = createMidi(dev); - if (midiType == MD_MT32 || ConfMan.getBool("native_mt32")) + if (MidiDriver::getMusicType(dev) == MT_MT32 || ConfMan.getBool("native_mt32")) _isMt32 = true; _sysExBuf[0] = 0x41; diff --git a/engines/sci/sound/iterator/core.cpp b/engines/sci/sound/iterator/core.cpp index 7cd730b3e2..e2e62c83b7 100644 --- a/engines/sci/sound/iterator/core.cpp +++ b/engines/sci/sound/iterator/core.cpp @@ -223,7 +223,7 @@ void SfxPlayer::player_timer_callback(void *refCon) { /* API implementation */ Common::Error SfxPlayer::init(ResourceManager *resMan, int expected_latency) { - MidiDriverType musicDriver = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB); + MidiDriverType musicDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB); switch (musicDriver) { case MD_ADLIB: diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index fbf37a78b1..6c697c86e5 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -61,31 +61,25 @@ void SciMusic::init() { // SCI sound init _dwTempo = 0; - MidiDriverType midiType; - // Default to MIDI in SCI32 games, as many don't have AdLib support. // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support those patches yet. // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we // default to MIDI in those games to let them run. Common::Platform platform = g_sci->getPlatform(); + uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); - if (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) - midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI); - else - midiType = MidiDriver::detectMusicDriver(MDT_PCSPK | MDT_ADLIB | MDT_MIDI); - - switch (midiType) { - case MD_ADLIB: + switch (MidiDriver::getMusicType(dev)) { + case MT_ADLIB: // FIXME: There's no Amiga sound option, so we hook it up to AdLib if (g_sci->getPlatform() == Common::kPlatformAmiga) _pMidiDrv = MidiPlayer_Amiga_create(_soundVersion); else _pMidiDrv = MidiPlayer_AdLib_create(_soundVersion); break; - case MD_PCJR: + case MT_PCJR: _pMidiDrv = MidiPlayer_PCJr_create(_soundVersion); break; - case MD_PCSPK: + case MT_PCSPK: _pMidiDrv = MidiPlayer_PCSpeaker_create(_soundVersion); break; default: diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 551e4c70a7..f509cabb2c 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -896,7 +896,7 @@ GameList ScummMetaEngine::detectGames(const Common::FSList &fslist) const { } } - dg.setGUIOptions(x->game.guioptions | MidiDriver::midiDriverFlags2GUIO(x->game.midi)); + dg.setGUIOptions(x->game.guioptions | MidiDriver::musicType2GUIO(x->game.midi)); dg.appendGUIOptions(getGameGUIOptionsDescriptionLanguage(x->language)); detectedGames.push_back(dg); diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index db6d04b785..e9dfce8057 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -224,7 +224,7 @@ static const GameSettings gameVariantsTable[] = { {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, {"loom", "No AdLib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, #ifdef USE_RGB_COLOR {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS | GF_OLD256 | GF_16BIT_COLOR, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, @@ -234,24 +234,24 @@ static const GameSettings gameVariantsTable[] = { {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, - {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, + {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, {"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NONE}, - {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI, 0, UNK, GUIO_NOSPEECH}, + {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE}, + {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, - {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NONE}, - {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, #ifdef ENABLE_SCUMM_7_8 {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI}, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 862353bf95..7c3b8a4a1d 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1634,28 +1634,28 @@ void ScummEngine_v100he::resetScumm() { #endif void ScummEngine::setupMusic(int midi) { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(midi); - _native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(midi); + _native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); - switch (midiDriver) { - case MD_NULL: + switch (MidiDriver::getMusicType(dev)) { + case MT_NULL: _musicType = MDT_NONE; break; - case MD_PCSPK: - case MD_PCJR: + case MT_PCSPK: + case MT_PCJR: _musicType = MDT_PCSPK; break; - case MD_CMS: + //case MT_CMS: #if 1 _musicType = MDT_ADLIB; #else _musicType = MDT_CMS; // Still has number of bugs, disable by default #endif break; - case MD_TOWNS: + case MT_TOWNS: _musicType = MDT_TOWNS; break; - case MD_ADLIB: + case MT_ADLIB: _musicType = MDT_ADLIB; break; default: @@ -1707,7 +1707,7 @@ void ScummEngine::setupMusic(int midi) { if (!_mixer->isReady()) { warning("Sound mixer initialization failed"); if (_musicType == MDT_ADLIB || _musicType == MDT_PCSPK || _musicType == MDT_CMS) { - midiDriver = MD_NULL; + dev = 0; _musicType = MDT_NONE; warning("MIDI driver depends on sound mixer, switching to null MIDI driver"); } @@ -1735,11 +1735,11 @@ void ScummEngine::setupMusic(int midi) { } else if (_game.platform == Common::kPlatformAmiga && _game.version <= 4) { _musicEngine = new Player_V4A(this, _mixer); } else if (_game.id == GID_MANIAC && _game.version == 1) { - _musicEngine = new Player_V1(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V1(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if (_game.version <= 2) { - _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if ((_musicType == MDT_PCSPK) && (_game.version > 2 && _game.version <= 4)) { - _musicEngine = new Player_V2(this, _mixer, midiDriver != MD_PCSPK); + _musicEngine = new Player_V2(this, _mixer, MidiDriver::getMusicType(dev) != MT_PCSPK); } else if (_musicType == MDT_CMS) { _musicEngine = new Player_V2CMS(this, _mixer); } else if (_game.platform == Common::kPlatform3DO && _game.heversion <= 62) { @@ -1749,12 +1749,12 @@ void ScummEngine::setupMusic(int midi) { MidiDriver *adlibMidiDriver = 0; if (_musicType != MDT_ADLIB) - nativeMidiDriver = MidiDriver::createMidi(midiDriver); + nativeMidiDriver = MidiDriver::createMidi(dev); if (nativeMidiDriver != NULL && _native_mt32) nativeMidiDriver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); bool multi_midi = ConfMan.getBool("multi_midi") && _musicType != MDT_NONE && (midi & MDT_ADLIB); if (_musicType == MDT_ADLIB || multi_midi) { - adlibMidiDriver = MidiDriver_ADLIB_create(); + adlibMidiDriver = MidiDriver::createMidi(MidiDriver::detectDevice(MDT_ADLIB)); adlibMidiDriver->property(MidiDriver::PROP_OLD_ADLIB, (_game.features & GF_SMALL_HEADER) ? 1 : 0); } @@ -1769,7 +1769,7 @@ void ScummEngine::setupMusic(int midi) { // YM2162 driver can't handle midi->getPercussionChannel(), NULL shouldn't init MT-32/GM/GS if ((midi != MDT_TOWNS) && (midi != MDT_NONE)) { _imuse->property(IMuse::PROP_NATIVE_MT32, _native_mt32); - if (midiDriver != MD_MT32) // MT-32 Emulation shouldn't be GM/GS initialized + if (MidiDriver::getMusicType(dev) != MT_MT32) // MT-32 Emulation shouldn't be GM/GS initialized _imuse->property(IMuse::PROP_GS, _enable_gs); } if (_game.heversion >= 60 || midi == MDT_TOWNS) { diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index 9ea20aafc6..58e3f5be2c 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -259,16 +259,16 @@ Common::Error SkyEngine::init() { _systemVars.gameVersion = _skyDisk->determineGameVersion(); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI); - if (midiDriver == MD_ADLIB) { + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32); + if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _systemVars.systemFlags |= SF_SBLASTER; _skyMusic = new AdLibMusic(_mixer, _skyDisk); } else { _systemVars.systemFlags |= SF_ROLAND; - if ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")) - _skyMusic = new MT32Music(MidiDriver::createMidi(midiDriver), _skyDisk); + if ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")) + _skyMusic = new MT32Music(MidiDriver::createMidi(dev), _skyDisk); else - _skyMusic = new GmMusic(MidiDriver::createMidi(midiDriver), _skyDisk); + _skyMusic = new GmMusic(MidiDriver::createMidi(dev), _skyDisk); } if (isCDVersion()) { diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index 8d11efef3c..e5a39308da 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -856,11 +856,11 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) if (cd_num >= 0) _system->openCD(cd_num); - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - bool native_mt32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - //bool adlib = (midiDriver == MD_ADLIB); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); - _driver = MidiDriver::createMidi(midiDriver); + _driver = MidiDriver::createMidi(dev); if (native_mt32) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index 9dbef4d76f..5c1d687827 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -92,9 +92,9 @@ void MidiPlayer::setVolume(int volume) { } int MidiPlayer::open() { - MidiDriverType midiDriver = MidiDriver::detectMusicDriver(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); - _nativeMT32 = ((midiDriver == MD_MT32) || ConfMan.getBool("native_mt32")); - _driver = MidiDriver::createMidi(midiDriver); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); + _driver = MidiDriver::createMidi(dev); int ret = _driver->open(); if (ret == 0) { _parser = MidiParser::createParser_SMF(); -- cgit v1.2.3 From 1041067a0c1ca2ac528338d99eaa1df677538265 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 22:07:03 +0000 Subject: SCI: instead of queueing inside midiparser, we are queueing now globally in SciMusic, also some little cleanup svn-id: r50130 --- engines/sci/sound/midiparser_sci.cpp | 60 +++++++++++------------ engines/sci/sound/midiparser_sci.h | 19 ++++---- engines/sci/sound/music.cpp | 94 ++++++++++++++++++++++++++---------- engines/sci/sound/music.h | 14 +++++- 4 files changed, 117 insertions(+), 70 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 9a6be1e1df..4766118f52 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -61,14 +61,20 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : _dataincToAdd = 0; _resetOnPause = false; _pSnd = 0; - - _manualCommandCount = 0; } MidiParser_SCI::~MidiParser_SCI() { unloadMusic(); } +void MidiParser_SCI::mainThreadBegin() { + _mainThreadCalled = true; +} + +void MidiParser_SCI::mainThreadEnd() { + _mainThreadCalled = false; +} + bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion) { unloadMusic(); _track = track; @@ -107,7 +113,7 @@ void MidiParser_SCI::sendInitCommands() { byte voiceCount = 0; if (_channelUsed[i]) { voiceCount = _pSnd->soundRes->getInitialVoiceCount(i); - sendToDriverQueue(0xB0 | i, 0x4B, voiceCount); + sendToDriver(0xB0 | i, 0x4B, voiceCount); } } } @@ -115,7 +121,8 @@ void MidiParser_SCI::sendInitCommands() { // Send a velocity off signal to all channels for (int i = 0; i < 15; ++i) { - sendToDriverQueue(0xB0 | i, 0x4E, 0); // Reset velocity + if (_channelUsed[i]) + sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity } } @@ -145,44 +152,27 @@ void MidiParser_SCI::unloadMusic() { } } -// this is used for scripts sending direct midi commands to us. we verify in that case that the channel is actually -// used and actually store the command for getting really sent when being onTimer() -void MidiParser_SCI::sendToDriverQueue(uint32 b) { - byte midiChannel = b & 0xf; +// this is used for scripts sending midi commands to us. we verify in that case that the channel is actually +// used, so that channel remapping will work as well and then send them on +void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) { + byte midiChannel = midi & 0xf; if (!_channelUsed[midiChannel]) { // trying to send to an unused channel // this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue return; } - - if (_manualCommandCount >= 200) - error("driver queue is full"); - _manualCommands[_manualCommandCount] = b; - _manualCommandCount++; + sendToDriver(midi); } -// This sends the stored commands from queue to driver (is supposed to get called only during onTimer()) -// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get -// a crash during piano scene in lsl5) -void MidiParser_SCI::sendQueueToDriver() { - int curCommand = 0; +void MidiParser_SCI::sendToDriver(uint32 midi) { + byte midiChannel = midi & 0xf; - while (curCommand < _manualCommandCount) { - sendToDriver(_manualCommands[curCommand]); - curCommand++; - } - _manualCommandCount = 0; -} - -void MidiParser_SCI::sendToDriver(uint32 b) { - byte midiChannel = b & 0xf; - - if ((b & 0xFFF0) == 0x4EB0) { + if ((midi & 0xFFF0) == 0x4EB0) { // this is channel mute only for sci1 // it's velocity control for sci0 if (_soundVersion >= SCI_VERSION_1_EARLY) { - _channelMuted[midiChannel] = b & 0xFF0000 ? true : false; + _channelMuted[midiChannel] = midi & 0xFF0000 ? true : false; return; // don't send this to driver at all } } @@ -194,8 +184,11 @@ void MidiParser_SCI::sendToDriver(uint32 b) { int16 realChannel = _channelRemap[midiChannel]; assert(realChannel != -1); - b = (b & 0xFFFFFFF0) | realChannel; - _driver->send(b); + midi = (midi & 0xFFFFFFF0) | realChannel; + if (_mainThreadCalled) + _music->putMidiCommandInQueue(midi); + else + _driver->send(midi); } void MidiParser_SCI::parseNextEvent(EventInfo &info) { @@ -681,7 +674,8 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_LATE: // sending volume change to all used channels for (int i = 0; i < 15; i++) - sendToDriverQueue(0xB0 + i, 7, _volume); + if (_channelUsed[i]) + sendToDriver(0xB0 + i, 7, _volume); break; default: diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 5abffdb3a1..dbd37018b1 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -55,6 +55,10 @@ class MidiParser_SCI : public MidiParser { public: MidiParser_SCI(SciVersion soundVersion, SciMusic *music); ~MidiParser_SCI(); + + void mainThreadBegin(); + void mainThreadEnd(); + bool loadMusic(SoundResource::Track *track, MusicEntry *psnd, int channelFilterMask, SciVersion soundVersion); bool loadMusic(byte *, uint32) { return false; @@ -77,16 +81,11 @@ public: const byte *getMixedData() const { return _mixedData; } void tryToOwnChannels(); - void sendToDriver(uint32 b); + void sendFromScriptToDriver(uint32 midi); + void sendToDriver(uint32 midi); void sendToDriver(byte status, byte firstOp, byte secondOp) { sendToDriver(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); } - void sendToDriverQueue(uint32 b); - void sendToDriverQueue(byte status, byte firstOp, byte secondOp) { - sendToDriverQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); - } - - void sendQueueToDriver(); protected: void parseNextEvent(EventInfo &info); @@ -96,6 +95,9 @@ protected: SciMusic *_music; + // this is set, when main thread calls us -> we send commands to queue instead to driver + bool _mainThreadCalled; + SciVersion _soundVersion; byte *_mixedData; SoundResource::Track *_track; @@ -112,9 +114,6 @@ protected: bool _channelUsed[16]; int16 _channelRemap[16]; bool _channelMuted[16]; - - int _manualCommandCount; - uint32 _manualCommands[200]; }; } // End of namespace Sci diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 6c697c86e5..b6ab7f9f70 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -46,6 +46,8 @@ SciMusic::SciMusic(SciVersion soundVersion) for (int i = 0; i < 16; i++) _usedChannel[i] = 0; + + _queuedCommandCount = 0; } SciMusic::~SciMusic() { @@ -102,6 +104,49 @@ void SciMusic::init() { _driverFirstChannel = _pMidiDrv->getFirstChannel(); } +void SciMusic::miditimerCallback(void *p) { + SciMusic *sciMusic = (SciMusic *)p; + + Common::StackLock lock(sciMusic->_mutex); + sciMusic->onTimer(); +} + +void SciMusic::onTimer() { + const MusicList::iterator end = _playList.end(); + // sending out queued commands that were "sent" via main thread + sendMidiCommandsFromQueue(); + + for (MusicList::iterator i = _playList.begin(); i != end; ++i) + (*i)->onTimer(); + + // for sending out fade commands immediately + sendMidiCommandsFromQueue(); +} + +void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) { + putMidiCommandInQueue(status | ((uint32)firstOp << 8) | ((uint32)secondOp << 16)); +} + +void SciMusic::putMidiCommandInQueue(uint32 midi) { + if (_queuedCommandCount >= 1000) + error("driver queue is full"); + _queuedCommands[_queuedCommandCount] = midi; + _queuedCommandCount++; +} + +// This sends the stored commands from queue to driver (is supposed to get called only during onTimer()) +// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get +// a crash during piano scene in lsl5) +void SciMusic::sendMidiCommandsFromQueue() { + int curCommand = 0; + + while (curCommand < _queuedCommandCount) { + _pMidiDrv->send(_queuedCommands[curCommand]); + curCommand++; + } + _queuedCommandCount = 0; +} + void SciMusic::clearPlayList() { Common::StackLock lock(_mutex); @@ -127,14 +172,6 @@ void SciMusic::stopAll() { } } - -void SciMusic::miditimerCallback(void *p) { - SciMusic *aud = (SciMusic *)p; - - Common::StackLock lock(aud->_mutex); - aud->onTimer(); -} - void SciMusic::soundSetSoundOn(bool soundOnFlag) { Common::StackLock lock(_mutex); @@ -219,8 +256,10 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { // Find out what channels to filter for SCI0 channelFilterMask = pSnd->soundRes->getChannelFilterMask(_pMidiDrv->getPlayId(), _pMidiDrv->hasRhythmChannel()); - pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); + pSnd->pMidiParser->mainThreadBegin(); + pSnd->pMidiParser->loadMusic(track, pSnd, channelFilterMask, _soundVersion); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } @@ -255,12 +294,6 @@ void SciMusic::freeChannels(MusicEntry *caller) { } } -void SciMusic::onTimer() { - const MusicList::iterator end = _playList.end(); - for (MusicList::iterator i = _playList.begin(); i != end; ++i) - (*i)->onTimer(); -} - void SciMusic::soundPlay(MusicEntry *pSnd) { _mutex.lock(); @@ -316,18 +349,21 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { DisposeAfterUse::NO); } } else { - _mutex.lock(); if (pSnd->pMidiParser) { + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->tryToOwnChannels(); pSnd->pMidiParser->setVolume(pSnd->volume); if (pSnd->status == kSoundStopped) { pSnd->pMidiParser->sendInitCommands(); pSnd->pMidiParser->jumpToTick(0); - } else + } else { // Fast forward to the last position and perform associated events when loading pSnd->pMidiParser->jumpToTick(pSnd->ticker, true); + } + pSnd->pMidiParser->mainThreadEnd(); + _mutex.unlock(); } - _mutex.unlock(); } pSnd->status = kSoundPlaying; @@ -342,8 +378,10 @@ void SciMusic::soundStop(MusicEntry *pSnd) { if (pSnd->pMidiParser) { _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->stop(); freeChannels(pSnd); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } @@ -354,7 +392,9 @@ void SciMusic::soundSetVolume(MusicEntry *pSnd, byte volume) { _pMixer->setChannelVolume(pSnd->hCurrentAud, volume * 2); // Mixer is 0-255, SCI is 0-127 } else if (pSnd->pMidiParser) { _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->setVolume(volume); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } @@ -369,13 +409,15 @@ void SciMusic::soundSetPriority(MusicEntry *pSnd, byte prio) { void SciMusic::soundKill(MusicEntry *pSnd) { pSnd->status = kSoundStopped; - _mutex.lock(); if (pSnd->pMidiParser) { + _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->unloadMusic(); + pSnd->pMidiParser->mainThreadEnd(); delete pSnd->pMidiParser; pSnd->pMidiParser = NULL; + _mutex.unlock(); } - _mutex.unlock(); if (pSnd->pStreamAud) { _pMixer->stopHandle(pSnd->hCurrentAud); @@ -409,8 +451,10 @@ void SciMusic::soundPause(MusicEntry *pSnd) { } else { if (pSnd->pMidiParser) { _mutex.lock(); + pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->pause(); freeChannels(pSnd); + pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); } } @@ -458,10 +502,12 @@ void SciMusic::sendMidiCommand(uint32 cmd) { void SciMusic::sendMidiCommand(MusicEntry *pSnd, uint32 cmd) { Common::StackLock lock(_mutex); - if (pSnd->pMidiParser) - pSnd->pMidiParser->sendToDriverQueue(cmd); - else + if (!pSnd->pMidiParser) error("tried to cmdSendMidi on non midi slot (%04x:%04x)", PRINT_REG(pSnd->soundObj)); + + pSnd->pMidiParser->mainThreadBegin(); + pSnd->pMidiParser->sendFromScriptToDriver(cmd); + pSnd->pMidiParser->mainThreadEnd(); } void SciMusic::printPlayList(Console *con) { @@ -567,8 +613,6 @@ void MusicEntry::onTimer() { // Only process MIDI streams in this thread, not digital sound effects if (pMidiParser) { - // Process manual commands first - pMidiParser->sendQueueToDriver(); pMidiParser->onTimer(); ticker = (uint16)pMidiParser->getTick(); } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 36db9a04bf..0a461cf76e 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -132,7 +132,15 @@ public: ~SciMusic(); void init(); + void onTimer(); + void putMidiCommandInQueue(byte status, byte firstOp, byte secondOp); + void putMidiCommandInQueue(uint32 midi); +private: + static void miditimerCallback(void *p); + void sendMidiCommandsFromQueue(); + +public: void clearPlayList(); void pauseAll(bool pause); void stopAll(); @@ -209,14 +217,16 @@ protected: // Mixed AdLib/MIDI mode: when enabled from the ScummVM sound options screen, // and a sound has a digital track, the sound from the AdLib track is played bool _bMultiMidi; -private: - static void miditimerCallback(void *p); +private: MusicList _playList; bool _soundOn; byte _masterVolume; MusicEntry *_usedChannel[16]; + int _queuedCommandCount; + uint32 _queuedCommands[1000]; + int _driverFirstChannel; }; -- cgit v1.2.3 From b5dffc5aa33466bdaf5bd06c4a24d7b1b4194ff3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 21 Jun 2010 22:15:33 +0000 Subject: SCI: fades already send out commands directly svn-id: r50131 --- engines/sci/sound/music.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index b6ab7f9f70..38d4968fee 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -118,9 +118,6 @@ void SciMusic::onTimer() { for (MusicList::iterator i = _playList.begin(); i != end; ++i) (*i)->onTimer(); - - // for sending out fade commands immediately - sendMidiCommandsFromQueue(); } void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) { -- cgit v1.2.3 From 727841ef913bbf61d035847b705ba47e488c57aa Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Mon, 21 Jun 2010 22:58:33 +0000 Subject: In SCI32, kDoAudio subop 10 is no longer CD audio. Just stub it off for now. svn-id: r50134 --- engines/sci/engine/ksound.cpp | 19 ++++++++++++++----- 1 file changed, 14 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 0d08cc2e06..46f9aa95d8 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -174,21 +174,30 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { } break; case kSciAudioCD: - debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop"); - return kDoCdAudio(s, argc - 1, argv + 1); + + if (getSciVersion() <= SCI_VERSION_1_1) { + debugC(2, kDebugLevelSound, "kDoAudio: CD audio subop"); + return kDoCdAudio(s, argc - 1, argv + 1); +#ifdef ENABLE_SCI32 + } else { + // TODO: This isn't CD Audio in SCI32 anymore + warning("kDoAudio: Unhandled case 10, %d extra arguments passed", argc - 1); + break; +#endif + } // 3 new subops in Pharkas. kDoAudio in Pharkas sits at seg026:038C case 11: - warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + warning("kDoAudio: Unhandled case 11, %d extra arguments passed", argc - 1); break; case 12: // Seems to be audio sync, used in Pharkas. Silenced the warning due to // the high level of spam it produces. - //warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + //warning("kDoAudio: Unhandled case 12, %d extra arguments passed", argc - 1); break; case 13: // Used in Pharkas whenever a speech sample starts - warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); + warning("kDoAudio: Unhandled case 13, %d extra arguments passed", argc - 1); break; default: warning("kDoAudio: Unhandled case %d, %d extra arguments passed", argv[0].toUint16(), argc - 1); -- cgit v1.2.3 From e3b3641db22ba38177a66d2ff73f342075f0687b Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Jun 2010 05:10:43 +0000 Subject: Finish implementation of the jspit elevator logic. svn-id: r50136 --- engines/mohawk/riven_external.cpp | 32 +++++++++++++++++++++++++++----- 1 file changed, 27 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 4e6bba1c2a..8ba4361f3f 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -1043,8 +1043,10 @@ int RivenExternal::jspitElevatorLoop() { void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + // If we've moved the handle down, go down a floor if (changeLevel == -1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(1); + _vm->_video->playMovieBlocking(2); _vm->changeToCard(_vm->matchRMAPToCard(0x1e374)); } } @@ -1052,8 +1054,10 @@ void RivenExternal::xhandlecontrolup(uint16 argc, uint16 *argv) { void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + // If we've moved the handle up, go up a floor if (changeLevel == 1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(1); + _vm->_video->playMovieBlocking(2); _vm->changeToCard(_vm->matchRMAPToCard(0x1e374)); } } @@ -1061,11 +1065,29 @@ void RivenExternal::xhandlecontroldown(uint16 argc, uint16 *argv) { void RivenExternal::xhandlecontrolmid(uint16 argc, uint16 *argv) { int changeLevel = jspitElevatorLoop(); + if (changeLevel == 0) + return; + + // Play the handle moving video + if (changeLevel == 1) + _vm->_video->playMovieBlocking(7); + else + _vm->_video->playMovieBlocking(6); + + // If the whark's mouth is open, close it + uint32 *mouthVar = _vm->matchVarToString("jwmouth"); + if (*mouthVar == 1) { + _vm->_video->playMovieBlocking(3); + _vm->_video->playMovieBlocking(8); + *mouthVar = 0; + } + + // Play the elevator video and then change the card if (changeLevel == 1) { - // TODO: Run movie + _vm->_video->playMovieBlocking(5); _vm->changeToCard(_vm->matchRMAPToCard(0x1e597)); - } else if (changeLevel == -1) { - // TODO: Run movie + } else { + _vm->_video->playMovieBlocking(4); _vm->changeToCard(_vm->matchRMAPToCard(0x1e29c)); } } -- cgit v1.2.3 From 53b82298e8236938d8724f904d2baba1f67b9eb1 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 Jun 2010 08:57:25 +0000 Subject: Stop saving the buffer, script and heap sizes of each script in saved games svn-id: r50137 --- engines/sci/engine/savegame.cpp | 17 +++++++++++------ engines/sci/engine/savegame.h | 2 +- 2 files changed, 12 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index fb79056e0c..d6cbd32eae 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -520,9 +520,12 @@ void HunkTable::saveLoadWithSerializer(Common::Serializer &s) { void Script::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_nr); - s.syncAsUint32LE(_bufSize); - s.syncAsUint32LE(_scriptSize); - s.syncAsUint32LE(_heapSize); + + if (s.isLoading()) + init(_nr, g_sci->getResMan()); + s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _bufSize + s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _scriptSize + s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _heapSize if (s.getVersion() <= 10) { assert((s.isLoading())); @@ -775,9 +778,11 @@ void SegManager::reconstructScripts(EngineState *s) { Object *obj = scr->scriptObjInit(addr, false); if (getSciVersion() < SCI_VERSION_1_1) { - if (!obj->initBaseObject(this, addr, false)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - //scr->scriptObjRemove(addr); + if (!obj->isFreed()) { + if (!obj->initBaseObject(this, addr, false)) { + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + //scr->scriptObjRemove(addr); + } } } } diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index aa22d42135..29f716d48d 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -36,7 +36,7 @@ namespace Sci { struct EngineState; enum { - CURRENT_SAVEGAME_VERSION = 22, + CURRENT_SAVEGAME_VERSION = 23, MINIMUM_SAVEGAME_VERSION = 9 }; -- cgit v1.2.3 From 019657fcd6278906a4c96425c438cc98808fd172 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Jun 2010 14:03:55 +0000 Subject: Fully implement xvga1300_carriage, the gallow's carriage is now fully usable. svn-id: r50139 --- engines/mohawk/riven_external.cpp | 81 ++++++++++++++++++++++++++------------- 1 file changed, 54 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 8ba4361f3f..89e10c7deb 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -960,33 +960,60 @@ void RivenExternal::xjtunnel106_pictfix(uint16 argc, uint16 *argv) { } void RivenExternal::xvga1300_carriage(uint16 argc, uint16 *argv) { - // TODO: This function is supposed to do a lot more, something like this (pseudocode): - - // Show level pull movie - // Set transition up - // Change to up card - // Show movie of carriage coming down - // Set transition down - // Change back to card 276 - // Show movie of carriage coming down - // if jgallows == 0 - // Set up timer - // Enter new input loop - // if you click within the time - // move forward - // set transition right - // change to card right - // show movie of ascending - // change to card 263 - // else - // show movie of carriage ascending only - // else - // show movie of carriage ascending only - - - // For now, if the gallows base is closed, assume ascension and move to that card. - if (*_vm->matchVarToString("jgallows") == 0) - _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); + // Run the gallows's carriage + + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_video->playMovieBlocking(1); // Play handle movie + _vm->_gfx->scheduleTransition(15); // Set pan down transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18e77)); // Change to card facing up + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor (again) + _vm->_video->playMovieBlocking(4); // Play carriage beginning to drop + _vm->_gfx->scheduleTransition(14); // Set pan up transition + _vm->changeToCard(_vm->matchRMAPToCard(0x183a9)); // Change to card looking straight again + _vm->_video->playMovieBlocking(2); + + uint32 *gallows = _vm->matchVarToString("jgallows"); + if (*gallows == 1) { + // If the gallows is open, play the up movie and return + _vm->_video->playMovieBlocking(3); + return; + } + + // Give the player 5 seconds to click (anywhere) + uint32 startTime = _vm->_system->getMillis(); + bool gotClick = false; + while (_vm->_system->getMillis() - startTime <= 5000 && !gotClick) { + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { + switch (event.type) { + case Common::EVENT_MOUSEMOVE: + _vm->_system->updateScreen(); + break; + case Common::EVENT_LBUTTONUP: + gotClick = true; + break; + default: + break; + } + } + + _vm->_system->delayMillis(10); + } + + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + + if (gotClick) { + _vm->_gfx->scheduleTransition(16); // Schedule dissolve transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18d4d)); // Move forward + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_system->delayMillis(500); // Delay a half second before changing again + _vm->_gfx->scheduleTransition(12); // Schedule pan left transition + _vm->changeToCard(_vm->matchRMAPToCard(0x18ab5)); // Turn right + _vm->_gfx->changeCursor(kRivenHideCursor); // Hide the cursor + _vm->_video->playMovieBlocking(1); // Play carriage ride movie + _vm->changeToCard(_vm->matchRMAPToCard(0x17167)); // We have arrived at the top + } else + _vm->_video->playMovieBlocking(3); // Too slow! } void RivenExternal::xjdome25_resetsliders(uint16 argc, uint16 *argv) { -- cgit v1.2.3 From 5855cd7127c9c7b40a67dd9d8aecbd065fc231b9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 Jun 2010 15:01:45 +0000 Subject: The volume subop of kDoAudio returns the previous volume in SCI2.1, but not in earlier versions svn-id: r50141 --- engines/sci/engine/ksound.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 46f9aa95d8..0172b005ac 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -152,8 +152,15 @@ reg_t kDoAudio(EngineState *s, int argc, reg_t *argv) { int16 volume = argv[1].toUint16(); volume = CLIP(volume, 0, AUDIO_VOLUME_MAX); debugC(2, kDebugLevelSound, "kDoAudio: set volume to %d", volume); +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2_1) { + int16 volumePrev = mixer->getVolumeForSoundType(Audio::Mixer::kSpeechSoundType) / 2; + volumePrev = CLIP(volumePrev, 0, AUDIO_VOLUME_MAX); + mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); + return make_reg(0, volumePrev); + } else +#endif mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, volume * 2); - return make_reg(0, volume); } case kSciAudioLanguage: // In SCI1.1: tests for digital audio support -- cgit v1.2.3 From c28fa2cf196eec983ad2b33b4f5ca9e607a9652d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 Jun 2010 15:03:19 +0000 Subject: Reverted the code which handles objects without a base object when loading, for now. This possibly indicates an issue related to the garbage collector svn-id: r50142 --- engines/sci/engine/savegame.cpp | 10 +++++----- engines/sci/engine/segment.cpp | 2 -- engines/sci/engine/segment.h | 2 -- 3 files changed, 5 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d6cbd32eae..351e7c6a7b 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -778,11 +778,11 @@ void SegManager::reconstructScripts(EngineState *s) { Object *obj = scr->scriptObjInit(addr, false); if (getSciVersion() < SCI_VERSION_1_1) { - if (!obj->isFreed()) { - if (!obj->initBaseObject(this, addr, false)) { - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - //scr->scriptObjRemove(addr); - } + if (!obj->initBaseObject(this, addr, false)) { + // TODO/FIXME: This should not be happening at all. It might indicate a possible issue + // with the garbage collector. It happens for example in LSL5 (German, perhaps English too). + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + scr->scriptObjRemove(addr); } } } diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index c2f72ecdbd..98f03ff18a 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -268,14 +268,12 @@ Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { return obj; } -#if 0 void Script::scriptObjRemove(reg_t obj_pos) { if (getSciVersion() < SCI_VERSION_1_1) obj_pos.offset += 8; _objects.erase(obj_pos.toUint16()); } -#endif // This helper function is used by Script::relocateLocal and Object::relocate static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 141576cb67..253d94cc53 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -406,13 +406,11 @@ public: */ Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); -#if 0 /** * Removes a script object * @param obj_pos Location (segment, offset) of the object. */ void scriptObjRemove(reg_t obj_pos); -#endif /** * Processes a relocation block witin a script -- cgit v1.2.3 From a82ca9de5cd207e9c00b41277e8a3e1e3869e254 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 15:05:09 +0000 Subject: SCI: change midi queue to Common::Array and make it resize itself if needed instead of error() svn-id: r50143 --- engines/sci/sound/music.cpp | 20 ++++++++++++-------- engines/sci/sound/music.h | 5 +++-- 2 files changed, 15 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 38d4968fee..8ee43fea64 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -47,7 +47,8 @@ SciMusic::SciMusic(SciVersion soundVersion) for (int i = 0; i < 16; i++) _usedChannel[i] = 0; - _queuedCommandCount = 0; + _queuedCommandCapacity = 1000; + _queuedCommands.reserve(_queuedCommandCapacity); } SciMusic::~SciMusic() { @@ -125,23 +126,26 @@ void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) { } void SciMusic::putMidiCommandInQueue(uint32 midi) { - if (_queuedCommandCount >= 1000) - error("driver queue is full"); - _queuedCommands[_queuedCommandCount] = midi; - _queuedCommandCount++; + if (_queuedCommands.size() == _queuedCommandCapacity) { + // We need more space + _queuedCommandCapacity *= 2; + _queuedCommands.reserve(_queuedCommandCapacity); + } + _queuedCommands.push_back(midi); } // This sends the stored commands from queue to driver (is supposed to get called only during onTimer()) // at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get // a crash during piano scene in lsl5) void SciMusic::sendMidiCommandsFromQueue() { - int curCommand = 0; + uint curCommand = 0; + uint commandCount = _queuedCommands.size(); - while (curCommand < _queuedCommandCount) { + while (curCommand < commandCount) { _pMidiDrv->send(_queuedCommands[curCommand]); curCommand++; } - _queuedCommandCount = 0; + _queuedCommands.clear(); } void SciMusic::clearPlayList() { diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 0a461cf76e..0a6662a7ce 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -120,6 +120,7 @@ public: }; typedef Common::Array MusicList; +typedef Common::Array MidiCommandQueue; class SciMusic #ifndef USE_OLD_MUSIC_FUNCTIONS @@ -224,8 +225,8 @@ private: byte _masterVolume; MusicEntry *_usedChannel[16]; - int _queuedCommandCount; - uint32 _queuedCommands[1000]; + uint _queuedCommandCapacity; + MidiCommandQueue _queuedCommands; int _driverFirstChannel; }; -- cgit v1.2.3 From bb9f556c363718959a43c7a65cec1944b626d358 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Jun 2010 15:18:55 +0000 Subject: Add support for the QFG3 demo audio map and audio resources. Based on a patch by Walter. svn-id: r50144 --- engines/sci/resource_audio.cpp | 51 +++++++++++++++++++++++++++++------------- engines/sci/sound/audio.cpp | 21 ++++++++++++----- 2 files changed, 52 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 72fd8f4594..909f1d6480 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -110,17 +110,19 @@ bool Resource::loadFromAudioVolumeSCI11(Common::SeekableReadStream *file) { _headerSize = file->readByte(); if (type == kResourceTypeAudio) { - if (_headerSize != 11 && _headerSize != 12) { + if (_headerSize != 7 && _headerSize != 11 && _headerSize != 12) { warning("Unsupported audio header"); unalloc(); return false; } - // Load sample size - file->seek(7, SEEK_CUR); - size = file->readUint32LE(); - // Adjust offset to point at the header data again - file->seek(-11, SEEK_CUR); + if (_headerSize != 7) { // Size is defined already from the map + // Load sample size + file->seek(7, SEEK_CUR); + size = file->readUint32LE(); + // Adjust offset to point at the header data again + file->seek(-11, SEEK_CUR); + } } return loadPatch(file); @@ -247,7 +249,6 @@ void ResourceManager::removeAudioResource(ResourceId resId) { // w syncAscSize (iff seq has bit 6 set) int ResourceManager::readAudioMapSCI11(ResourceSource *map) { - bool isEarly = true; uint32 offset = 0; Resource *mapRes = findResource(ResourceId(kResourceTypeMap, map->_volumeNumber), false); @@ -263,11 +264,16 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { byte *ptr = mapRes->data; - if (map->_volumeNumber == 65535) { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 6) && (ptr[mapRes->size - 6] != 0xff)) - isEarly = false; + // Heuristic to detect entry size + uint32 entrySize = 0; + for (int i = mapRes->size - 1; i >= 0; --i) { + if (ptr[i] == 0xff) + entrySize++; + else + break; + } + if (map->_volumeNumber == 65535) { while (ptr < mapRes->data + mapRes->size) { uint16 n = READ_LE_UINT16(ptr); ptr += 2; @@ -275,7 +281,7 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { if (n == 0xffff) break; - if (isEarly) { + if (entrySize == 6) { offset = READ_LE_UINT32(ptr); ptr += 4; } else { @@ -285,10 +291,25 @@ int ResourceManager::readAudioMapSCI11(ResourceSource *map) { addResource(ResourceId(kResourceTypeAudio, n), src, offset); } + } else if (map->_volumeNumber == 0 && entrySize == 10 && ptr[3] == 0) { + // QFG3 demo format + // ptr[3] would be 'seq' in the normal format and cannot possibly be 0 + while (ptr < mapRes->data + mapRes->size) { + uint16 n = READ_BE_UINT16(ptr); + ptr += 2; + + if (n == 0xffff) + break; + + offset = READ_LE_UINT32(ptr); + ptr += 4; + uint32 size = READ_LE_UINT32(ptr); + ptr += 4; + + addResource(ResourceId(kResourceTypeAudio, n), src, offset, size); + } } else { - // Heuristic to detect late SCI1.1 map format - if ((mapRes->size >= 11) && (ptr[mapRes->size - 11] == 0xff)) - isEarly = false; + bool isEarly = (entrySize != 11); if (!isEarly) { offset = READ_LE_UINT32(ptr); diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 0e235ee400..336218eaec 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -182,17 +182,28 @@ static void deDPCM8(byte *soundBuf, Common::SeekableReadStream &audioStream, uin // Sierra SOL audio file reader // Check here for more info: http://wiki.multimedia.cx/index.php?title=Sierra_Audio -static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags) { - if (headerSize != 11 && headerSize != 12) { +static bool readSOLHeader(Common::SeekableReadStream *audioStream, int headerSize, uint32 &size, uint16 &audioRate, byte &audioFlags, uint32 resSize) { + if (headerSize != 7 && headerSize != 11 && headerSize != 12) { warning("SOL audio header of size %i not supported", headerSize); return false; } - audioStream->readUint32LE(); // skip "SOL" + 0 (4 bytes) + uint32 tag = audioStream->readUint32BE(); + + if (tag != MKID_BE('SOL\0')) { + warning("No 'SOL' FourCC found"); + return false; + } + audioRate = audioStream->readUint16LE(); audioFlags = audioStream->readByte(); - size = audioStream->readUint32LE(); + // For the QFG3 demo format, just use the resource size + // Otherwise, load it from the header + if (headerSize == 7) + size = resSize; + else + size = audioStream->readUint32LE(); return true; } @@ -294,7 +305,7 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 // SCI1.1 Common::MemoryReadStream headerStream(audioRes->_header, audioRes->_headerSize, DisposeAfterUse::NO); - if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags)) { + if (readSOLHeader(&headerStream, audioRes->_headerSize, size, _audioRate, audioFlags, audioRes->size)) { Common::MemoryReadStream dataStream(audioRes->data, audioRes->size, DisposeAfterUse::NO); data = readSOLAudio(&dataStream, size, audioFlags, flags); } -- cgit v1.2.3 From 66c286d096503bf54cce16a1920fa96b9a46228e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 15:33:46 +0000 Subject: SCI: kPalVary(setTarget) now triggers an error svn-id: r50146 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 0b2f37f690..82a565c6d2 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -696,7 +696,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { } case 4: { // Change Target // seems to be 1 parameter, we should find a game that is using this feature before implementing it - warning("kPalVary(changeTarget) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + error("kPalVary(changeTarget) called with parameter %d (argc %d)", argv[1].toUint16(), argc); break; } case 5: { // Change ticks -- cgit v1.2.3 From 3c4bfa6caccb8beeb5c603865879da7f6b31c556 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 15:45:59 +0000 Subject: SCI: removing unneeded capacity uint from r50143 svn-id: r50147 --- engines/sci/sound/music.cpp | 8 +------- engines/sci/sound/music.h | 1 - 2 files changed, 1 insertion(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 8ee43fea64..0d1f0f4db9 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -47,8 +47,7 @@ SciMusic::SciMusic(SciVersion soundVersion) for (int i = 0; i < 16; i++) _usedChannel[i] = 0; - _queuedCommandCapacity = 1000; - _queuedCommands.reserve(_queuedCommandCapacity); + _queuedCommands.reserve(1000); } SciMusic::~SciMusic() { @@ -126,11 +125,6 @@ void SciMusic::putMidiCommandInQueue(byte status, byte firstOp, byte secondOp) { } void SciMusic::putMidiCommandInQueue(uint32 midi) { - if (_queuedCommands.size() == _queuedCommandCapacity) { - // We need more space - _queuedCommandCapacity *= 2; - _queuedCommands.reserve(_queuedCommandCapacity); - } _queuedCommands.push_back(midi); } diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 0a6662a7ce..a29b6edee2 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -225,7 +225,6 @@ private: byte _masterVolume; MusicEntry *_usedChannel[16]; - uint _queuedCommandCapacity; MidiCommandQueue _queuedCommands; int _driverFirstChannel; -- cgit v1.2.3 From 90a1d7c609760830fb9c94c574c2f7c6aa694321 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 22 Jun 2010 16:09:27 +0000 Subject: SCUMM: Add Japanese FOA CD version from tracker #3017219 svn-id: r50149 --- engines/scumm/scumm-md5.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index cc382d9621..73553cf72a 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Mon May 24 13:24:24 2010 + This file was generated by the md5table tool on Tue Jun 22 15:59:56 2010 DO NOT EDIT MANUALLY! */ @@ -130,7 +130,7 @@ static const MD5Table md5table[] = { { "2d388339d6050d8ccaa757b64633954e", "zak", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4536a56e01da4b02eb021e7770afa2", "zak", "FM-TOWNS", "", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, { "2d4acbdcfd8e374c9da8c2e7303a5cd0", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, - { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "2d624d1b214f7faf0094daea65c6d1a6", "maniac", "Apple II", "", -1, Common::EN_ANY, Common::kPlatformApple2GS }, { "2d9d46f23cb07bbc90b8ad464d3e4ff8", "atlantis", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "2e85f7aa054930c692a5b1bed1dfc295", "football2002", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "2e8a1f76ea33bc5e04347646feee173d", "pajama3", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, @@ -576,6 +576,7 @@ static const MD5Table md5table[] = { { "e6cd81b25ab1453a8a6d3482118c391e", "pass", "", "", 7857, Common::EN_ANY, Common::kPlatformPC }, { "e72bb4c2b613db2cf50f89ff6350e70a", "ft", "", "", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "e781230da44a44e2f0770edb2b3b3633", "maniac", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga }, + { "e8d0697906e53fee8b7e9f5652696da8", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformPC }, { "e94c7cc3686fce406d3c91b5eae5a72d", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformAmiga }, { "e95cf980719c0be078fb68a67af97b4a", "funpack", "", "", -1, Common::JA_JPN, Common::kPlatform3DO }, { "e98b982ceaf9d253d730bde8903233d6", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, -- cgit v1.2.3 From 33347e12bd94552a0c100351747b6c693d144f68 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 22 Jun 2010 16:09:50 +0000 Subject: SCUMM: Add a debug message to detectGames() to help find filesizes of detection files svn-id: r50150 --- engines/scumm/detection.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index f509cabb2c..dbd86505a8 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -488,6 +488,12 @@ static void detectGames(const Common::FSList &fslist, Common::Listsize(); + if (d.md5Entry->filesize != filesize) + debug(1, "SCUMM detector found matching file '%s' with MD5 %s, size %d\n", + file.c_str(), md5str, filesize); + // Sanity check: We *should* have found a matching gameid / variant at this point. // If not, then there's a bug in our data tables... assert(dr.game.gameid != 0); -- cgit v1.2.3 From 5b24d39cdd94889e223d41acfea395414b608040 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 22 Jun 2010 16:10:16 +0000 Subject: SCUMM: Specify various file sizes of detection files svn-id: r50151 --- engines/scumm/scumm-md5.h | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 73553cf72a..8570f0c6a3 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Tue Jun 22 15:59:56 2010 + This file was generated by the md5table tool on Tue Jun 22 16:01:03 2010 DO NOT EDIT MANUALLY! */ @@ -47,7 +47,7 @@ static const MD5Table md5table[] = { { "0be88565f734b1e9e77ccaaf3bb14b29", "loom", "EGA", "EGA", -1, Common::ES_ESP, Common::kPlatformPC }, { "0bf1a3eb198ca1bd2ebe104825cec770", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "0c331637580950aea2346e012ef2a868", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST }, - { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, + { "0c45eb4baff0c12c3d9dfa889c8070ab", "pajama3", "", "Demo", 13884, Common::DE_DEU, Common::kPlatformUnknown }, { "0cccfa5223099a60e76cfcca57a1a141", "freddi3", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "0d1b69471605201ef2fa9cec1f5f02d2", "maniac", "V2", "V2", -1, Common::ES_ESP, Common::kPlatformPC }, { "0e4c5d54a0ad4b26132e78b5ea76642a", "samnmax", "Floppy", "Demo", 6485, Common::EN_ANY, Common::kPlatformPC }, @@ -79,7 +79,7 @@ static const MD5Table md5table[] = { { "16effd200aa6b8abe9c569c3e578814d", "freddi4", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "179879b6e35c1ead0d93aab26db0951b", "fbear", "HE 70", "", 13381, Common::EN_ANY, Common::kPlatformWindows }, { "17b5d5e6af4ae89d62631641d66d5a05", "indy3", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformPC }, - { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", -1, Common::EN_GRB, Common::kPlatformNES }, + { "17f7296f63c78642724f057fd8e736a7", "maniac", "NES", "", 2082, Common::EN_GRB, Common::kPlatformNES }, { "17fa250eb72dae2dad511ba79c0b6b0a", "tentacle", "", "Demo", -1, Common::FR_FRA, Common::kPlatformPC }, { "182344899c2e2998fca0bebcd82aa81a", "atlantis", "", "CD", 12035, Common::EN_ANY, Common::kPlatformPC }, { "183d7464902d40d00800e8ee1f04117c", "maniac", "V2", "V2", 1988, Common::DE_DEU, Common::kPlatformPC }, @@ -145,7 +145,7 @@ static const MD5Table md5table[] = { { "330f631502e381a4e199a3f7cb483c20", "indy3", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "33e989f85da700e2014d00f345cab3d7", "puttrace", "HE 98.5", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "3433be9866ca4261b2d5d25374e3f243", "monkey", "VGA", "VGA", -1, Common::FR_FRA, Common::kPlatformAmiga }, - { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "3486ede0f904789267d4bcc5537a46d4", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformMacintosh }, { "356fb5f680b68251333016175935d126", "BluesABCTime", "HE CUP", "Preview", 4133436, Common::UNK_LANG, Common::kPlatformUnknown }, { "35a2d3040fa512f8232d9e443319d84d", "dig", "", "", 659335495, Common::EN_ANY, Common::kPlatformMacintosh }, { "362c1d281fb9899254cda66ad246c66a", "dig", "Demo", "Demo", 3472, Common::EN_ANY, Common::kPlatformUnknown }, @@ -183,7 +183,7 @@ static const MD5Table md5table[] = { { "425205754fa749f4f0b0dd9d09fa45fd", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "430bc518017b6fac046f58bab6baad5d", "monkey2", "", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "439a7f4adf510489981ac52308e7d7a2", "maniac", "C64", "", -1, Common::DE_DEU, Common::kPlatformC64 }, - { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "45082a5c9f42ba14dacfe1fdeeba819d", "freddicove", "HE 100", "Demo", 18422, Common::EN_ANY, Common::kPlatformUnknown }, { "45152f7cf2ba8f43cf8a8ea2e740ae09", "monkey", "VGA", "VGA", 8357, Common::ES_ESP, Common::kPlatformPC }, { "4521138d15d1fd7649c31fb981746231", "pajama2", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "46b53fd430adcfbed791b48a0d4b079f", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatformPC }, @@ -225,7 +225,7 @@ static const MD5Table md5table[] = { { "5262a27afcaee04e5c4900220bd463e7", "PuttsFunShop", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "52a4bae0746a11d7b1e8554e91a6645c", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC }, { "53e94115b55dd51d4b8ff0871aa1df1e", "spyfox", "", "Demo", 20103, Common::EN_ANY, Common::kPlatformUnknown }, - { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", -1, Common::EN_ANY, Common::kPlatformAmiga }, + { "54a936ad06161ff7bfefcb96200f7bff", "monkey", "VGA", "VGA Demo", 7617, Common::EN_ANY, Common::kPlatformAmiga }, { "55518cd73cf9c6d23ea29c51ee06bdfe", "ft", "", "", -1, Common::IT_ITA, Common::kPlatformUnknown }, { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows }, @@ -242,7 +242,7 @@ static const MD5Table md5table[] = { { "59d5cfcc5e672a6e07baae01328b918b", "PuttTime", "HE 90", "Demo", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "5a35e36fd777e9c37a49c5b2faca52f9", "loom", "EGA", "EGA Demo", 6108, Common::EN_ANY, Common::kPlatformPC }, { "5b08000a9c47b2887df6506ac767ca68", "fbear", "HE 62", "", -1, Common::EN_ANY, Common::kPlatform3DO }, - { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "5bd335265a61caa3d78956ad9f88ba23", "football", "", "Demo", 23135, Common::EN_ANY, Common::kPlatformUnknown }, { "5c21fc49aee8f46e58fef21579e614a1", "thinker1", "", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "5d88b9d6a88e6f8e90cded9d01b7f082", "loom", "VGA", "VGA", 8307, Common::EN_ANY, Common::kPlatformPC }, { "5dda73606533d66a4c3f4f9ea6e842af", "farm", "", "", 87061, Common::RU_RUS, Common::kPlatformWindows }, @@ -366,13 +366,13 @@ static const MD5Table md5table[] = { { "8aed489aba45d2b9fb8a04079c9c6e6a", "baseball", "HE CUP", "Preview", 12876596, Common::UNK_LANG, Common::kPlatformUnknown }, { "8afb3cf9f95abf208358e984f0c9e738", "funpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "8bdb0bf87b5e303dd35693afb9351215", "ft", "", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, - { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "8d479e36f35e80257dfc102cf4b8a912", "farm", "HE 72", "Demo", 34333, Common::EN_ANY, Common::kPlatformWindows }, { "8de13897f0121c79d29a2377159f9ad0", "socks", "HE 99", "Updated", -1, Common::EN_ANY, Common::kPlatformWindows }, { "8e3241ddd6c8dadf64305e8740d45e13", "balloon", "HE 100", "Updated", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "8e4ee4db46954bfe2912e259a16fad82", "monkey2", "", "", -1, Common::FR_FRA, Common::kPlatformPC }, { "8e9417564f33790815445b2136efa667", "atlantis", "", "CD", 11915, Common::JA_JPN, Common::kPlatformMacintosh }, { "8e9830a6f2702be5b22c8fa0a6aaf977", "freddi2", "HE 80", "", -1, Common::NL_NLD, Common::kPlatformMacintosh }, - { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "8eb84cee9b429314c7f0bdcf560723eb", "monkey", "FM-TOWNS", "", 9925, Common::EN_ANY, Common::kPlatformFMTowns }, { "8ee63cafb1fe9d62aa0d5a23117e70e7", "freddi2", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "8f3758ff98c9c5d78e5d635222cad026", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformPC }, { "8fec68383202d38c0d25e9e3b757c5df", "comi", "Demo", "Demo", 18041, Common::UNK_LANG, Common::kPlatformWindows }, @@ -489,13 +489,13 @@ static const MD5Table md5table[] = { { "c4787c3e8b5e2dfda90850ee800af00f", "zak", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformPC }, { "c4ffae9fac495475d6bc3343ccc8faf9", "Soccer2004", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "c5cc7cba02a2fbd539c4439e775b0536", "puttzoo", "HE 99", "Updated", 43470, Common::DE_DEU, Common::kPlatformWindows }, - { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "c5d10e190d4b4d59114b824f2fdbd00e", "loom", "FM-TOWNS", "", 7540, Common::EN_ANY, Common::kPlatformFMTowns }, { "c63ee46143ba65f9ce14cf539ca51bd7", "atlantis", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, { "c666a998af90d81db447eccba9f72c8d", "monkey", "No AdLib", "EGA", -1, Common::EN_ANY, Common::kPlatformAtariST }, { "c6907d44f1166941d982864cd42cdc89", "pajama2", "HE 99", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, { "c782fbbe74a987c3df8ac73cd3e289ed", "freddi", "HE 73", "", -1, Common::SE_SWE, Common::kPlatformMacintosh }, { "c7890e038806df2bb5c0c8c6f1986ea2", "monkey", "VGA", "VGA", -1, Common::EN_ANY, Common::kPlatformPC }, - { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", -1, Common::EN_ANY, Common::kPlatformFMTowns }, + { "c7be10f775404fd9785a8b92a06d240c", "atlantis", "", "", 12030, Common::EN_ANY, Common::kPlatformFMTowns }, { "c7c492a107ec520d7a7943037d0ca54a", "freddi", "HE 71", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "c83079157ec765a28de445aec9768d60", "tentacle", "", "Demo", 7477, Common::EN_ANY, Common::kPlatformUnknown }, { "c8575e0b973ff1723aba6cd92c642db2", "puttrace", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, @@ -519,7 +519,7 @@ static const MD5Table md5table[] = { { "cf4ef315214c7d8cdab6302cdb7e50db", "freddi", "HE 73", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, { "cf8d13446ec6cb6222287a925fd47c1d", "baseball", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "cf8ef3a1fb483c5c4b1c584d1167b2c4", "freddi", "HE 73", "", -1, Common::DE_DEU, Common::kPlatformWindows }, - { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformWindows }, + { "cf90b4db5486ef798db78fe6fbf897e5", "pajama3", "", "Demo", 13902, Common::EN_USA, Common::kPlatformWindows }, { "d00ffc8c32d17e575fd985d435d2eb88", "arttime", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d0549508a06bbb9f99ed19c9e97891f3", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "d06fbe28818fef7bfc45c2cdf0c0849d", "zak", "V2", "V2", -1, Common::DE_DEU, Common::kPlatformPC }, @@ -561,7 +561,7 @@ static const MD5Table md5table[] = { { "df047cc4792150f601290357566d36a6", "freddi", "HE 90", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "e01acc8c12ef44e8f778fe87e5f90f4e", "fbpack", "", "", -1, Common::EN_ANY, Common::kPlatform3DO }, { "e03ed1474ec14de78359970e0457a820", "freddi4", "HE 99", "Demo", -1, Common::EN_GRB, Common::kPlatformWindows }, - { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "e144f5f49d9241d2a9dee2576b3d09cb", "airport", "", "Demo", 51152, Common::EN_ANY, Common::kPlatformWindows }, { "e17db1ddf91b39ca6bbc8ad3ed19e883", "monkey", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, { "e246e02db9630533a40d99c9f54a8e01", "monkey2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "e361a7058ed8e8ebb462663c0a3ae8d6", "puttputt", "HE 62", "", -1, Common::HE_ISR, Common::kPlatformPC }, @@ -582,7 +582,7 @@ static const MD5Table md5table[] = { { "e98b982ceaf9d253d730bde8903233d6", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, { "eae95b2b3546d8ba86ae1d397c383253", "dog", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "eb700bb73ca1cc44a1ad5e4b1a4bdeaf", "indy3", "EGA", "EGA", 5361, Common::DE_DEU, Common::kPlatformPC }, - { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, + { "ebd0b2c8a387f18887282afe6cad894a", "spyozon", "", "Demo", 15317, Common::EN_ANY, Common::kPlatformUnknown }, { "ebd324dcf06a4c49e1ba5c231eee1060", "freddi4", "HE 99", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "ecc4340c2b801f5af8da4e00c0e432d9", "puttcircus", "", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "ed2b074bc3166087a747acb2a3c6abb0", "freddi3", "HE 98.5", "Demo", -1, Common::DE_DEU, Common::kPlatformUnknown }, @@ -618,7 +618,7 @@ static const MD5Table md5table[] = { { "fbbbb38a81fc9d6a61d509278390a290", "farm", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "fbdd947d21e8f5bac6d6f7a316af1c5a", "spyfox", "", "Demo", 15693, Common::EN_ANY, Common::kPlatformUnknown }, { "fc53ce0e5f6562b1c1e1b4b8203acafb", "samnmax", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformPC }, - { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformPC }, + { "fc6b6148e80d67939d9a18697c0f626a", "monkey", "EGA", "EGA", 8367, Common::DE_DEU, Common::kPlatformPC }, { "fc8d197a22146e74766e9cb0cfcaf1da", "freddi2", "HE 80", "Demo", 27298, Common::EN_ANY, Common::kPlatformUnknown }, { "fcb78ebecab2757264c590890c319cc5", "PuttTime", "HE 85", "", -1, Common::NL_NLD, Common::kPlatformUnknown }, { "fce4b8010704b103acfeea9413788f32", "freddi2", "HE 80", "", -1, Common::DE_DEU, Common::kPlatformUnknown }, -- cgit v1.2.3 From 9ca43423b478561d17716ae2537f6b232f625c74 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 17:05:00 +0000 Subject: SCI: kPalVary(SetTarget) implemented svn-id: r50153 --- engines/sci/engine/kgraphics.cpp | 15 ++++++++++----- engines/sci/graphics/palette.cpp | 15 +++++++++++++++ engines/sci/graphics/palette.h | 1 + 3 files changed, 26 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 82a565c6d2..bc278a2bb1 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -673,7 +673,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { warning("kPalVary(reverse) called with ticks = %d, stop = %d, direction = %d", ticks, stepStop, direction); return make_reg(0, result); } else { - warning("kPalVary(reverse) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + warning("kPalVary(reverse) called with unsupported argc %d", argc); } } case 2: { // Get Current Step @@ -681,7 +681,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { int16 currentStep = g_sci->_gfxPalette->kernelPalVaryGetCurrentStep(); return make_reg(0, currentStep); } else { - warning("kPalVary(GetCurrentStep) called with unsupported argc %d", argc); + warning("kPalVary(getCurrentStep) called with unsupported argc %d", argc); } break; } @@ -695,8 +695,13 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { break; } case 4: { // Change Target - // seems to be 1 parameter, we should find a game that is using this feature before implementing it - error("kPalVary(changeTarget) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + if (argc == 2) { + GuiResourceId paletteId = argv[1].toUint16(); + int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId); + return make_reg(0, currentStep); + } else { + warning("kPalVary(changeTarget) called with unsupported argc %d", argc); + } break; } case 5: { // Change ticks @@ -704,7 +709,7 @@ reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { uint16 ticks = argv[1].toUint16(); g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); } else { - warning("kPalVary(changeTicks) called with parameter %d (argc %d)", argv[1].toUint16(), argc); + warning("kPalVary(changeTicks) called with unsupported argc %d", argc); } break; } diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index d256227ea8..339cac8e15 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -572,6 +572,21 @@ int16 GfxPalette::kernelPalVaryGetCurrentStep() { return -_palVaryStep; } +int16 GfxPalette::kernelPalVaryChangeTarget(GuiResourceId resourceId) { + if (_palVaryResourceId != -1) { + Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); + if (palResource) { + Palette insertPalette; + createFromData(palResource->data, &insertPalette); + // insert new palette into target + insert(&insertPalette, &_palVaryTargetPalette); + // update palette and set on screen + palVaryProcess(0, true); + } + } + return kernelPalVaryGetCurrentStep(); +} + void GfxPalette::kernelPalVaryChangeTicks(uint16 ticks) { _palVaryTicks = ticks; if (_palVaryStep - _palVaryStepStop) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 021096873b..ce9888c7db 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -66,6 +66,7 @@ public: bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction); int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction); int16 kernelPalVaryGetCurrentStep(); + int16 kernelPalVaryChangeTarget(GuiResourceId resourceId); void kernelPalVaryChangeTicks(uint16 ticks); void kernelPalVaryPause(bool pause); void kernelPalVaryDeinit(); -- cgit v1.2.3 From 079e5c3135aea031a23401c39110cc883c421112 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 17:13:44 +0000 Subject: SCI: fixed typo svn-id: r50154 --- engines/sci/graphics/palette.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index ce9888c7db..29120daa7d 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -45,7 +45,7 @@ public: void modifyAmigaPalette(byte *data); void setEGA(); void set(Palette *sciPal, bool force, bool forceRealMerge = false); - bool insert(Palette *newPaette, Palette *destPalette); + bool insert(Palette *newPalette, Palette *destPalette); bool merge(Palette *pFrom, bool force, bool forceRealMerge); uint16 matchColor(byte r, byte g, byte b); void getSys(Palette *pal); -- cgit v1.2.3 From 3a394793b6ef84d3bf200c7aac276ac39f8dc36f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 Jun 2010 18:25:15 +0000 Subject: Fixed 2 crashes in QFG1VGA, when dying: - Ignoring a non-game breaking script bug (modifying the "longSong" object with argc = 2) - Don't pop the callk stack frame if the stack is empty - fixes a crash when restoring from the death screen svn-id: r50157 --- engines/sci/engine/vm.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index cc7f1a1be6..350734f8fc 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -417,6 +417,9 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt if (!strcmp(objectName, "Sq4GlobalNarrator") && selector == 606) { // SQ4 has a script bug in the Sq4GlobalNarrator object when invoking the // returnVal selector, which doesn't affect gameplay, thus don't diplay it + } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == "qfg1") { + // QFG1VGA has a script bug in the longSong object when invoking the + // loop selector, which doesn't affect gameplay, thus don't diplay it } else { // Unknown script bug, show it reg_t oldReg = *varp.getPointer(s->_segMan); @@ -636,8 +639,9 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { #endif } - // Remove callk stack frame again - s->_executionStack.pop_back(); + // Remove callk stack frame again, if there's still an execution stack + if (s->_executionStack.begin() != s->_executionStack.end()) + s->_executionStack.pop_back(); } else { Common::String warningMsg = "Dummy function " + kernelFunc.origName + Common::String::printf("[0x%x]", kernelFuncNum) + -- cgit v1.2.3 From 56bf0c0e635383929704ba12df3808f39aeb697e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 22 Jun 2010 18:33:19 +0000 Subject: Fixed kMergePoly after discussing with waltervn so that it correctly returns a pointer to an empty (for now) polygon array. This means that you can walk over enemy bodies after killing them in QFG1VGA, but at least it fixes the crashes after killing monsters svn-id: r50160 --- engines/sci/engine/kpathing.cpp | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index 8988aa5734..ba6fb9bb6e 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1739,14 +1739,9 @@ reg_t kIntersections(EngineState *s, int argc, reg_t *argv) { * is in QFG1VGA, after killing any monster. */ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { +#if 0 // 3 parameters: raw polygon data, polygon list, list size reg_t polygonData = argv[0]; - - // TODO: actually merge the polygon - // In QFG1VGA, there are no immediately visible side-effects - // of this being a stub. - -#if 0 List *list = s->_segMan->lookupList(argv[1]); Node *node = s->_segMan->lookupNode(list->first); // List size is not needed @@ -1765,9 +1760,14 @@ reg_t kMergePoly(EngineState *s, int argc, reg_t *argv) { } #endif + // TODO: actually merge the polygon. We return an empty polygon for now. + // In QFG1VGA, you can walk over enemy bodies after killing them, since + // this is a stub. + reg_t output = allocateOutputArray(s->_segMan, 1); + SegmentRef arrayRef = s->_segMan->dereference(output); + writePoint(arrayRef, 0, Common::Point(POLY_LAST_POINT, POLY_LAST_POINT)); warning("Stub: kMergePoly"); - - return polygonData; + return output; } } // End of namespace Sci -- cgit v1.2.3 From 38cf6aa3e4c0415f507f5ec514834440bfbf90ca Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 19:01:43 +0000 Subject: SCI: implemented kAssertPalette and a palvary fix for ::set, fixes erana's place in qfg1vga nighttime svn-id: r50162 --- engines/sci/graphics/palette.cpp | 20 ++++++++++++++++---- engines/sci/graphics/view.cpp | 2 +- 2 files changed, 17 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 339cac8e15..b0969ceb74 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -30,9 +30,11 @@ #include "sci/sci.h" #include "sci/engine/state.h" +#include "sci/graphics/cache.h" #include "sci/graphics/maciconbar.h" #include "sci/graphics/palette.h" #include "sci/graphics/screen.h" +#include "sci/graphics/view.h" namespace Sci { @@ -216,15 +218,16 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); newPalette->timestamp = _sysPalette.timestamp; + bool updatePalette = _sysPaletteChanged && _screen->_picNotValid == 0; + if (_palVaryResourceId != -1) { // Pal-vary currently active, we don't set at any time, but also insert into origin palette insert(newPalette, &_palVaryOriginPalette); + palVaryProcess(0, updatePalette); return; } - if (_sysPaletteChanged && _screen->_picNotValid == 0) { // && systime != _sysPalette.timestamp) { - // Removed timestamp checking, because this shouldnt be needed anymore. I'm leaving it commented just in - // case this causes regressions + if (updatePalette) { setOnScreen(); _sysPaletteChanged = false; } @@ -467,7 +470,16 @@ void GfxPalette::kernelAnimateSet() { } void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { - warning("kAssertPalette %d", resourceId); + // Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga) + if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId))) + return; + + GfxView *view = g_sci->_gfxCache->getView(resourceId); + Palette *viewPalette = view->getPalette(); + if (viewPalette) { + // merge/insert this palette + set(viewPalette, true); + } } // palVary diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 7c33f87a14..40e2a4fb30 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -653,7 +653,7 @@ uint16 GfxView::getCelCount(int16 loopNo) { } Palette *GfxView::getPalette() { - return _embeddedPal ? &_viewPalette : &_palette->_sysPalette; + return _embeddedPal ? &_viewPalette : NULL; } } // End of namespace Sci -- cgit v1.2.3 From 33b991ee9d987acf013606341a60c8e3ff95ca77 Mon Sep 17 00:00:00 2001 From: Jordi Vilalta Prat Date: Tue, 22 Jun 2010 19:21:05 +0000 Subject: Groovie: Add support for the compressed MIDI files of T7G Mac. svn-id: r50163 --- engines/groovie/music.cpp | 63 ++++++++++++++++++++++++++++++++++++++++------- engines/groovie/music.h | 3 +++ 2 files changed, 57 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 7166432e02..7e8f21bbbc 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -703,20 +703,65 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { Common::SeekableReadStream *file = _vm->_macResFork->getResource(MKID_BE('cmid'), fileref & 0x3FF); if (file) { - // TODO: A form of LZSS, not supported by the current Groovie decoder. - // The offset/length uint16 is BE, but not sure the amount of length bits - // nor whether the offset is absolute/relative. - warning("TODO: Mac Compressed MIDI: cmid 0x%04x", fileref & 0x3FF); + // Found the resource, decompress it + Common::SeekableReadStream *tmp = decompressMidi(file); delete file; + file = tmp; + } else { + // Otherwise, it's uncompressed + file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); + if (!file) + error("Groovie::Music: Couldn't find resource 0x%04X", fileref); return false; } - // Otherwise, it's uncompressed - file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); - if (!file) - error("Groovie::Music: Couldn't find resource 0x%04X", fileref); - return loadParser(file, loop); } +Common::SeekableReadStream *MusicPlayerMac::decompressMidi(Common::SeekableReadStream *stream) { + // Initialize an output buffer of the given size + uint32 size = stream->readUint32BE(); + byte *output = (byte *)malloc(size); + + byte *current = output; + uint32 decompBytes = 0; + while ((decompBytes < size) && !stream->eos()) { + // 8 flags + byte flags = stream->readByte(); + + for (byte i = 0; (i < 8) && !stream->eos(); i++) { + if (flags & 1) { + // 1: Next byte is a literal + *(current++) = stream->readByte(); + if (stream->eos()) + continue; + decompBytes++; + } else { + // 0: It's a reference to part of the history + uint16 args = stream->readUint16BE(); + if (stream->eos()) + continue; + + // Length = 4bit unsigned (3 minimal) + uint8 length = (args >> 12) + 3; + + // Offset = 12bit signed (all values are negative) + int16 offset = (args & 0xFFF) | 0xF000; + + // Copy from the past decompressed bytes + decompBytes += length; + while (length > 0) { + *(current) = *(current + offset); + current++; + length--; + } + } + flags = flags >> 1; + } + } + + // Return the output buffer wrapped in a MemoryReadStream + return new Common::MemoryReadStream(output, size, DisposeAfterUse::YES); +} + } // End of Groovie namespace diff --git a/engines/groovie/music.h b/engines/groovie/music.h index 2feef9cbf7..5b5f5bd346 100644 --- a/engines/groovie/music.h +++ b/engines/groovie/music.h @@ -161,6 +161,9 @@ public: protected: bool load(uint32 fileref, bool loop); + +private: + Common::SeekableReadStream *decompressMidi(Common::SeekableReadStream *stream); }; } // End of Groovie namespace -- cgit v1.2.3 From 99807b88945082ac029710c4ab9be5322c04e0ea Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 22 Jun 2010 19:39:30 +0000 Subject: Fix uncompressed MIDI in T7G Mac. svn-id: r50165 --- engines/groovie/music.cpp | 1 - 1 file changed, 1 deletion(-) (limited to 'engines') diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 7e8f21bbbc..9b46af1483 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -712,7 +712,6 @@ bool MusicPlayerMac::load(uint32 fileref, bool loop) { file = _vm->_macResFork->getResource(MKID_BE('Midi'), fileref & 0x3FF); if (!file) error("Groovie::Music: Couldn't find resource 0x%04X", fileref); - return false; } return loadParser(file, loop); -- cgit v1.2.3 From a836f965f8c313fad8d3f36b94ccec4bf5c0c00b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 20:40:41 +0000 Subject: SCI: set offTop to 26 for mixed up fairy tales to fix all sorts of non-fully-removed windows svn-id: r50166 --- engines/sci/graphics/ports.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 8ba7c57b62..9f0edb290f 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -90,6 +90,9 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te Common::String gameId = g_sci->getGameId(); if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; + // Mixed-Up Fairy Tales uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere + if (gameId == "fairytales") + offTop = 26; openPort(_wmgrPort); setPort(_wmgrPort); -- cgit v1.2.3 From 93b2336aa2ed65bcc1cca1db878dc0d07dc0fc2f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 21:01:34 +0000 Subject: SCI: demo of fairy tales uses regular offTop svn-id: r50168 --- engines/sci/graphics/ports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 9f0edb290f..571687a05f 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -91,7 +91,7 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; // Mixed-Up Fairy Tales uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere - if (gameId == "fairytales") + if ((gameId == "fairytales") && (!g_sci->isDemo())) offTop = 26; openPort(_wmgrPort); -- cgit v1.2.3 From d8968ee5b95d62fd357dfec163436f7f164e5244 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 21:05:34 +0000 Subject: SCI: reversing r50168, demo is using the same offTop as well (demo.bat) svn-id: r50169 --- engines/sci/graphics/ports.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 571687a05f..b8e3ec9c9d 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -90,8 +90,8 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te Common::String gameId = g_sci->getGameId(); if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; - // Mixed-Up Fairy Tales uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere - if ((gameId == "fairytales") && (!g_sci->isDemo())) + // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere + if (gameId == "fairytales") offTop = 26; openPort(_wmgrPort); -- cgit v1.2.3 From 04c04ff01ee4e6288d8600661c67aebee8b959b3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 21:24:52 +0000 Subject: SCI: eco quest 1 demo also uses inbetween sci1.1 interpreter, fixing graphics svn-id: r50170 --- engines/sci/graphics/palette.cpp | 18 ++++++++++-------- 1 file changed, 10 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index b0969ceb74..385c3f4e3e 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -66,14 +66,16 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case - // Quest for Glory 3 demo and police quest 1 vga behave the same interpreter wise and all have glitches, if we don't - // switch back - if (g_sci->getGameId() == "laurabow2" && (g_sci->isDemo())) - _alwaysForceRealMerge = true; - else if (g_sci->getGameId() == "qfg3" && (g_sci->isDemo())) - _alwaysForceRealMerge = true; - else if (g_sci->getGameId() == "pq1sci") - _alwaysForceRealMerge = true; + // Quest for Glory 3 demo, Eco Quest 1 demo and police quest 1 vga behave the same interpreter wise and all have glitches, + // if we don't switch back + Common::String gameId = g_sci->getGameId(); + if (g_sci->isDemo()) { + if (gameId == "laurabow2" || gameId == "qfg3" || gameId == "ecoquest") + _alwaysForceRealMerge = true; + } else { + if (gameId == "pq1sci") + _alwaysForceRealMerge = true; + } palVaryInit(); } -- cgit v1.2.3 From b68180efe525c37f48a81ce7946d9e6f2045cf07 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 22 Jun 2010 21:58:55 +0000 Subject: SCI: added nicks picks sq to the sci1.1 interpreter games, the other ones may also use the same interpreter, but we currently can not verify svn-id: r50172 --- engines/sci/graphics/palette.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 385c3f4e3e..208bc6751b 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -62,18 +62,19 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _alwaysForceRealMerge = false; // Pseudo-WORKAROUND - // Laura Bow 2 demo uses an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 + // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and Nick's Picks Space Quest + // all use an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case - // Quest for Glory 3 demo, Eco Quest 1 demo and police quest 1 vga behave the same interpreter wise and all have glitches, - // if we don't switch back + // FIXME: the other nick's Picks may also use the same interpreter, but we can not verify + // if the other games also get reported having palette issues, add them here Common::String gameId = g_sci->getGameId(); if (g_sci->isDemo()) { if (gameId == "laurabow2" || gameId == "qfg3" || gameId == "ecoquest") _alwaysForceRealMerge = true; } else { - if (gameId == "pq1sci") + if (gameId == "pq1sci" || gameId == "cnick-sq") _alwaysForceRealMerge = true; } -- cgit v1.2.3 From 717005bf25b6e74f22418324845f363eb4a1068d Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 23 Jun 2010 10:11:01 +0000 Subject: Rewrote the MADS animation frame decoder to better guard against invalid data causing memory overruns svn-id: r50174 --- engines/m4/sprite.cpp | 94 +++++++++++++++++++++++++++++---------------------- 1 file changed, 54 insertions(+), 40 deletions(-) (limited to 'engines') diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index da043c695f..553b27dd9a 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -121,56 +121,70 @@ void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int // TODO: The sprite outlines (pixel value 0xFD) are not shown void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { - byte *outp, *lineStart; - bool newLine = false; - - outp = getBasePtr(); - lineStart = getBasePtr(); - - while (1) { - byte cmd1, cmd2, count, pixel; - - if (newLine) { - if (outp < (lineStart + w)) - Common::set_to(outp, lineStart + w, TRANSPARENT_COLOUR_INDEX); - - outp = lineStart + w; - lineStart = outp; - newLine = false; - } - - cmd1 = source->readByte(); - - if (cmd1 == 0xFC) - break; - else if (cmd1 == 0xFF) + // Set entire sprite contents to transparent pixels + fillRect(bounds(), TRANSPARENT_COLOUR_INDEX); + + // Major line loop + for (int y = 0; y < h; ++y) { + byte *destP = getBasePtr(0, y); + bool newLine = false; + byte cmd = source->readByte(); + int x = 0; + + if (cmd == 0xff) + // The entire line is empty newLine = true; - else if (cmd1 == 0xFD) { - while (!newLine) { - count = source->readByte(); - if (count == 0xFF) { + else if (cmd == 0xFD) { + // Lines contains only run lenghs of pixels + while (x < w) { + byte cmd = source->readByte(); + if (cmd == 0xff) { + // End of line reached newLine = true; - } else { - pixel = source->readByte(); - while (count--) - *outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel; + break; + } + + byte v = source->readByte(); + while (cmd-- > 0) { + if (x < w) + *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; + ++x; } } } else { - while (!newLine) { - cmd2 = source->readByte(); - if (cmd2 == 0xFF) { + // Line intermixes run lengths with individual pixels + while (x < w) { + cmd = source->readByte(); + if (cmd == 0xff) { + // End of line reached newLine = true; - } else if (cmd2 == 0xFE) { - count = source->readByte(); - pixel = source->readByte(); - while (count--) - *outp++ = (pixel == 0xFD) ? TRANSPARENT_COLOUR_INDEX : pixel; + break; + } + + if (cmd == 0xFE) { + // Handle repeated sequence + cmd = source->readByte(); + byte v = source->readByte(); + while (cmd-- > 0) { + if (x < w) { + *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; + } + ++x; + } } else { - *outp++ = (cmd2 == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd2; + // Handle writing out single pixel + *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd; + ++x; } } } + + // Check if we need to scan forward to find the end of the line + if (!newLine) { + do { + assert(!source->eos()); + } while (source->readByte() != 0xff); + } } } -- cgit v1.2.3 From 3569b496622a61eb7d82c3033b188c4cd0426ae6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 23 Jun 2010 11:22:44 +0000 Subject: Changed some asserts to warnings svn-id: r50175 --- engines/m4/assets.cpp | 7 ++++++- engines/m4/graphics.cpp | 6 ++++-- engines/m4/sprite.cpp | 5 ++++- 3 files changed, 14 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 1f3cf278ae..c329373add 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -320,7 +320,12 @@ void SpriteAsset::loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndia } M4Sprite *SpriteAsset::getFrame(int frameIndex) { - return _frames[frameIndex].frame; + if ((uint)frameIndex < _frames.size()) { + return _frames[frameIndex].frame; + } else { + warning("SpriteAsset::getFrame: Invalid frame %d, out of %d", frameIndex, _frames.size()); + return _frames[_frames.size() - 1].frame; + } } void SpriteAsset::loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY) { diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index b0bc8bbc0c..85d138328d 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -920,8 +920,10 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { for (int i = 0; i < width() * height(); ++i, ++p) { if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) { - assert(*p < list->size()); - *p = palIndexes[*p]; + if (*p < list->size()) { + warning("Pal pointer exceeds list size"); + *p = palIndexes[*p]; + } } } diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 553b27dd9a..55de6714d1 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -182,7 +182,10 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { // Check if we need to scan forward to find the end of the line if (!newLine) { do { - assert(!source->eos()); + if (source->eos()) { + warning("M4Sprite::loadMadsSprite: unexpected end of data"); + break; + } } while (source->readByte() != 0xff); } } -- cgit v1.2.3 From fedc06060594c4f9fbd1db4511c513eb3926d135 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 23 Jun 2010 11:28:53 +0000 Subject: Corrected newly added palette conversion warning svn-id: r50176 --- engines/m4/graphics.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 85d138328d..b1d590c114 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -920,10 +920,10 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { for (int i = 0; i < width() * height(); ++i, ++p) { if (!isTransparent || (*p != TRANSPARENT_COLOUR_INDEX)) { - if (*p < list->size()) { - warning("Pal pointer exceeds list size"); + if (*p < list->size()) *p = palIndexes[*p]; - } + else + warning("Pal pointer exceeds list size"); } } -- cgit v1.2.3 From 3cdd841192d840be6094aefa3b89eee582375946 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 23 Jun 2010 11:32:36 +0000 Subject: Made a warning more verbose svn-id: r50177 --- engines/m4/graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index b1d590c114..55c16cb9e7 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -923,7 +923,7 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { if (*p < list->size()) *p = palIndexes[*p]; else - warning("Pal pointer exceeds list size"); + warning("Pal index %d exceeds list size %d", *p, list->size()); } } -- cgit v1.2.3 From f0145e6dcd3f96225be7fc6c5b8aebce9ee545d8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 11:47:14 +0000 Subject: SCI: implementing boundary checking for GfxPalette::createFromData(), sq5 has a broken picture 0 resource, which would result in either crash or at least bad read from memory depending on whats read there svn-id: r50178 --- engines/sci/graphics/palette.cpp | 25 ++++++++++++++++++++----- engines/sci/graphics/palette.h | 2 +- engines/sci/graphics/picture.cpp | 4 ++-- engines/sci/graphics/view.cpp | 5 +++-- engines/sci/graphics/view.h | 1 + 5 files changed, 27 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 208bc6751b..ef20aafc82 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -97,7 +97,7 @@ void GfxPalette::setDefault() { #define SCI_PAL_FORMAT_CONSTANT 1 #define SCI_PAL_FORMAT_VARIABLE 0 -void GfxPalette::createFromData(byte *data, Palette *paletteOut) { +void GfxPalette::createFromData(byte *data, int bytesLeft, Palette *paletteOut) { int palFormat = 0; int palOffset = 0; int palColorStart = 0; @@ -105,10 +105,16 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { int colorNo = 0; memset(paletteOut, 0, sizeof(Palette)); - // Setup default mapping + // Setup 1:1 mapping for (colorNo = 0; colorNo < 256; colorNo++) { paletteOut->mapping[colorNo] = colorNo; } + if (bytesLeft < 37) { + // This happens when loading palette of picture 0 in sq5 - the resource is broken and doesn't contain a full + // palette + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette header"); + return; + } if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0)) { // SCI0/SCI1 palette palFormat = SCI_PAL_FORMAT_VARIABLE; // CONSTANT; @@ -123,6 +129,11 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { } switch (palFormat) { case SCI_PAL_FORMAT_CONSTANT: + // Check, if enough bytes left + if (bytesLeft < palOffset + (3 * palColorCount)) { + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors"); + return; + } for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { paletteOut->colors[colorNo].used = 1; paletteOut->colors[colorNo].r = data[palOffset++]; @@ -131,6 +142,10 @@ void GfxPalette::createFromData(byte *data, Palette *paletteOut) { } break; case SCI_PAL_FORMAT_VARIABLE: + if (bytesLeft < palOffset + (4 * palColorCount)) { + warning("GfxPalette::createFromData() - not enough bytes in resource, expected palette colors"); + return; + } for (colorNo = palColorStart; colorNo < palColorStart + palColorCount; colorNo++) { paletteOut->colors[colorNo].used = data[palOffset++]; paletteOut->colors[colorNo].r = data[palOffset++]; @@ -378,7 +393,7 @@ bool GfxPalette::kernelSetFromResource(GuiResourceId resourceId, bool force) { Palette palette; if (palResource) { - createFromData(palResource->data, &palette); + createFromData(palResource->data, palResource->size, &palette); set(&palette, force); return true; } @@ -526,7 +541,7 @@ bool GfxPalette::palVaryLoadTargetPalette(GuiResourceId resourceId) { Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (palResource) { // Load and initialize destination palette - createFromData(palResource->data, &_palVaryTargetPalette); + createFromData(palResource->data, palResource->size, &_palVaryTargetPalette); return true; } return false; @@ -592,7 +607,7 @@ int16 GfxPalette::kernelPalVaryChangeTarget(GuiResourceId resourceId) { Resource *palResource = _resMan->findResource(ResourceId(kResourceTypePalette, resourceId), false); if (palResource) { Palette insertPalette; - createFromData(palResource->data, &insertPalette); + createFromData(palResource->data, palResource->size, &insertPalette); // insert new palette into target insert(&insertPalette, &_palVaryTargetPalette); // update palette and set on screen diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 29120daa7d..e640d9b39d 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -40,7 +40,7 @@ public: ~GfxPalette(); void setDefault(); - void createFromData(byte *data, Palette *paletteOut); + void createFromData(byte *data, int bytesLeft, Palette *paletteOut); bool setAmiga(); void modifyAmigaPalette(byte *data); void setEGA(); diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index 0b62a558ca..b410fc47f1 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -109,7 +109,7 @@ void GfxPicture::drawSci11Vga() { Palette palette; // Create palette and set it - _palette->createFromData(inbuffer + palette_data_ptr, &palette); + _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette); _palette->set(&palette, true); // display Cel-data @@ -147,7 +147,7 @@ void GfxPicture::drawSci32Vga(int16 celNo) { if ((celNo == -1) || (celNo == 0)) { // Create palette and set it - _palette->createFromData(inbuffer + palette_data_ptr, &palette); + _palette->createFromData(inbuffer + palette_data_ptr, size - palette_data_ptr, &palette); _palette->set(&palette, true); } if (celNo != -1) { diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 40e2a4fb30..f00d6a652d 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -62,6 +62,7 @@ void GfxView::initData(GuiResourceId resourceId) { error("view resource %d not found", resourceId); } _resourceData = _resource->data; + _resourceSize = _resource->size; byte *celData, *loopData; uint16 celOffset; @@ -114,7 +115,7 @@ void GfxView::initData(GuiResourceId resourceId) { // On the other side: vga sci1 games have this pointing to a VGA palette // and ega sci1 games have this pointing to a 8x16 byte mapping table that needs to get applied then if (!isEGA) { - _palette->createFromData(&_resourceData[palOffset], &_viewPalette); + _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette); _embeddedPal = true; } else { // Only use the EGA-mapping, when being SCI1 @@ -197,7 +198,7 @@ void GfxView::initData(GuiResourceId resourceId) { assert(celSize >= 32); if (palOffset) { - _palette->createFromData(&_resourceData[palOffset], &_viewPalette); + _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette); _embeddedPal = true; } diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index a2050dc9d5..fe033dfe23 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -86,6 +86,7 @@ private: GuiResourceId _resourceId; Resource *_resource; byte *_resourceData; + int _resourceSize; uint16 _loopCount; LoopInfo *_loop; -- cgit v1.2.3 From 3bc011357bba0104de2e7f910cde6a7d62d7581f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 12:58:14 +0000 Subject: SCI: some initial work on global scaling svn-id: r50179 --- engines/sci/engine/selector.cpp | 1 + engines/sci/engine/static_selectors.cpp | 1 + engines/sci/engine/vm.h | 3 ++- engines/sci/graphics/animate.cpp | 20 ++++++++++++++------ engines/sci/graphics/animate.h | 6 +++--- 5 files changed, 21 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 08e2ba5e99..cc2adeb62b 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -157,6 +157,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(scaleSignal); FIND_SELECTOR(scaleX); FIND_SELECTOR(scaleY); + FIND_SELECTOR(maxScale); FIND_SELECTOR(iconIndex); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index eca18f67fb..c7ee7b854a 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -107,6 +107,7 @@ static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_1_1, SCI_VERSION_1_1,"scaleSignal", 103 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleX", 104 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleY", 105 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "maxScale", 106 }, { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } }; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index fa57a1151c..d4be76dd40 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -152,8 +152,9 @@ struct SelectorCache { Selector syncTime; // SCI1.1 specific selectors - Selector scaleSignal; // < Used by Animate() for cel scaling (SCI1.1+) + Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+) Selector scaleX, scaleY; ///< SCI1.1 view scaling + Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling // Used for auto detection purposes Selector overlay; ///< Used to determine if a game is using old gfx functions or not diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 339132a76c..57879b6653 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -185,12 +185,6 @@ void GfxAnimate::makeSortedList(List *list) { listEntry->scaleX = 128; listEntry->scaleY = 128; } - // TODO - // On scaleSignal bit 1 sierra sci does some stuff with global var 2, current Port - // and some other stuff and sets scaleX/Y accordingly. It seems this functionality is needed in at - // least sq5 right when starting the game before wilco exists the room. Currently we dont get scaling - // but sierra sci does scaling there. I dont fully understand the code yet, that's why i didnt implement - // anything. } else { listEntry->scaleSignal = 0; listEntry->scaleX = 128; @@ -236,6 +230,20 @@ void GfxAnimate::fill(byte &old_picNotValid) { writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), listEntry->celNo); } + // Process global scaling, if needed + if (listEntry->scaleSignal & kScaleSignalDoScaling) { + if (listEntry->scaleSignal & kScaleSignalGlobalScaling) { + // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY + int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale)); + int16 maxCelHeight = (maxScale * view->getHeight(listEntry->loopNo, listEntry->celNo)) >> 7; + // TODO! + + // and set objects scale selectors + //writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), listEntry->scaleX); + //writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), listEntry->scaleY); + } + } + // Create rect according to coordinates and given cel if (listEntry->scaleSignal & kScaleSignalDoScaling) { view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, &listEntry->celRect); diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 324ca0d700..a7d925c6e0 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -51,9 +51,9 @@ enum ViewSignals { }; enum ViewScaleSignals { - kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) - kScaleSignalUnknown1 = 0x0002, // seems to do something with globalvar 2, sets scaleX/scaleY - kScaleSignalUnknown2 = 0x0004 // really unknown + kScaleSignalDoScaling = 0x0001, // enables scaling when drawing that cel (involves scaleX and scaleY) + kScaleSignalGlobalScaling = 0x0002, // means that global scaling shall get applied on that cel (sets scaleX/scaleY) + kScaleSignalUnknown2 = 0x0004 // really unknown }; struct AnimateEntry { -- cgit v1.2.3 From eeba2812c1a950380ea3ea8766704ced11afaffd Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 13:42:09 +0000 Subject: SCI: adding some more global scaling code, adding vanishingY and vanishingX as selectors svn-id: r50180 --- engines/sci/engine/selector.cpp | 2 ++ engines/sci/engine/static_selectors.cpp | 2 ++ engines/sci/engine/vm.h | 2 ++ engines/sci/graphics/animate.cpp | 4 ++++ 4 files changed, 10 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index cc2adeb62b..65024742c7 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -158,6 +158,8 @@ void Kernel::mapSelectors() { FIND_SELECTOR(scaleX); FIND_SELECTOR(scaleY); FIND_SELECTOR(maxScale); + FIND_SELECTOR(vanishingX); + FIND_SELECTOR(vanishingY); FIND_SELECTOR(iconIndex); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index c7ee7b854a..6f44788fd7 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -108,6 +108,8 @@ static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleX", 104 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleY", 105 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "maxScale", 106 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingX", 107 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "vanishingY", 108 }, { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, 0 } }; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index d4be76dd40..9de7cc587c 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -155,6 +155,8 @@ struct SelectorCache { Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+) Selector scaleX, scaleY; ///< SCI1.1 view scaling Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling + Selector vanishingX; ///< SCI1.1 view scaling, used by global scaling + Selector vanishingY; ///< SCI1.1 view scaling, used by global scaling // Used for auto detection purposes Selector overlay; ///< Used to determine if a game is using old gfx functions or not diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 57879b6653..f96a1646ef 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -233,9 +233,13 @@ void GfxAnimate::fill(byte &old_picNotValid) { // Process global scaling, if needed if (listEntry->scaleSignal & kScaleSignalDoScaling) { if (listEntry->scaleSignal & kScaleSignalGlobalScaling) { + warning("%lx:%lx", PRINT_REG(curObject)); // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale)); int16 maxCelHeight = (maxScale * view->getHeight(listEntry->loopNo, listEntry->celNo)) >> 7; + reg_t globalVar2 = _s->variables[VAR_GLOBAL][1]; // current room + int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY)); + //warning("vanishingY %d maxScale %d", vanishingY, maxScale); // TODO! // and set objects scale selectors -- cgit v1.2.3 From c1d3fd670c34b751c5e7a4236c14cb72ca973548 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 14:06:31 +0000 Subject: SCI: global scaling implemented (hopefully, i'm not sure if it works 100% :P) thx to waltervn for telling me the vocab 994 stuff used for disassembly svn-id: r50181 --- engines/sci/graphics/animate.cpp | 25 ++++++++++++++++++------- 1 file changed, 18 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index f96a1646ef..9051111d2d 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -233,18 +233,29 @@ void GfxAnimate::fill(byte &old_picNotValid) { // Process global scaling, if needed if (listEntry->scaleSignal & kScaleSignalDoScaling) { if (listEntry->scaleSignal & kScaleSignalGlobalScaling) { - warning("%lx:%lx", PRINT_REG(curObject)); // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale)); - int16 maxCelHeight = (maxScale * view->getHeight(listEntry->loopNo, listEntry->celNo)) >> 7; - reg_t globalVar2 = _s->variables[VAR_GLOBAL][1]; // current room + int16 celHeight = view->getHeight(listEntry->loopNo, listEntry->celNo); + int16 maxCelHeight = (maxScale * celHeight) >> 7; + reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY)); - //warning("vanishingY %d maxScale %d", vanishingY, maxScale); - // TODO! + + int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY; + int16 fixedEntryY = listEntry->y - vanishingY; + if (!fixedEntryY) + fixedEntryY = 1; + + if ((celHeight == 0) || (fixedPortY == 0)) + error("global scaling panic"); + + listEntry->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY; + listEntry->scaleY = (listEntry->scaleY * 128) / celHeight; + + listEntry->scaleX = listEntry->scaleY; // and set objects scale selectors - //writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), listEntry->scaleX); - //writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), listEntry->scaleY); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), listEntry->scaleX); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), listEntry->scaleY); } } -- cgit v1.2.3 From db6c7a3deee4f9e312c8dcead3e7e32baddf4166 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 23 Jun 2010 15:08:23 +0000 Subject: Removed a hack with SCI1.1 static selectors, and set them properly. This fixes scaling in the demo of QFG3 svn-id: r50182 --- engines/sci/engine/static_selectors.cpp | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index 6f44788fd7..fcef04f6ad 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -100,10 +100,18 @@ static const SelectorRemap sciSelectorRemap[] = { { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "moveDone", 170 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "points", 316 }, { SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE, "flags", 368 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "nodePtr", 44 }, - { SCI_VERSION_1_LATE, SCI_VERSION_1_1, "cantBeHere", 57 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "topString", 101 }, - { SCI_VERSION_1_EARLY, SCI_VERSION_1_1, "flags", 102 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "nodePtr", 44 }, + { SCI_VERSION_1_LATE, SCI_VERSION_1_LATE, "cantBeHere", 57 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "topString", 101 }, + { SCI_VERSION_1_EARLY, SCI_VERSION_1_LATE, "flags", 102 }, + // SCI1.1 + { SCI_VERSION_1_1, SCI_VERSION_1_1, "nodePtr", 41 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "cantBeHere", 54 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "topString", 98 }, + { SCI_VERSION_1_1, SCI_VERSION_1_1, "flags", 99 }, + // quitGame + // restart + // hide { SCI_VERSION_1_1, SCI_VERSION_1_1,"scaleSignal", 103 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleX", 104 }, { SCI_VERSION_1_1, SCI_VERSION_1_1, "scaleY", 105 }, @@ -146,9 +154,6 @@ Common::StringArray Kernel::checkStaticSelectorNames() { if (selectorRemap->slot >= names.size()) names.resize(selectorRemap->slot + 1); if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) { - // The SCI1 selectors we use exist in SCI1.1 too, offset by 3 - if (selectorRemap->minVersion >= SCI_VERSION_1_EARLY && getSciVersion() == SCI_VERSION_1_1) - slot -= 3; names[slot] = selectorRemap->name; } } -- cgit v1.2.3 From 0a102981f004733c9e7956ae58b4d0050db38e2b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 23 Jun 2010 15:23:37 +0000 Subject: Moved the SelectorCache struct inside selector.h, where it belongs, and fixed some header dependencies in the process svn-id: r50183 --- engines/sci/console.cpp | 1 + engines/sci/engine/features.cpp | 1 + engines/sci/engine/kernel.h | 2 + engines/sci/engine/savegame.cpp | 1 + engines/sci/engine/selector.cpp | 1 + engines/sci/engine/selector.h | 112 ++++++++++++++++++++++++++++++++- engines/sci/engine/state.cpp | 1 + engines/sci/engine/vm.h | 111 -------------------------------- engines/sci/graphics/animate.cpp | 1 + engines/sci/graphics/compare.cpp | 1 + engines/sci/graphics/controls.cpp | 1 + engines/sci/graphics/coordadjuster.cpp | 1 + engines/sci/graphics/frameout.cpp | 2 +- engines/sci/graphics/maciconbar.cpp | 1 + engines/sci/graphics/menu.cpp | 1 + engines/sci/sound/soundcmd.cpp | 1 + 16 files changed, 126 insertions(+), 113 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 1fdcd579c0..cf87b34bba 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -31,6 +31,7 @@ #include "sci/event.h" #include "sci/resource.h" #include "sci/engine/state.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" #include "sci/engine/savegame.h" #include "sci/engine/gc.h" diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index e8f2fe326c..75f271f3ad 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -24,6 +24,7 @@ */ #include "sci/engine/features.h" +#include "sci/engine/kernel.h" #include "sci/engine/script.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 11bc76348d..802a2d5f0b 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -31,6 +31,7 @@ #include "common/rect.h" #include "common/str-array.h" +#include "sci/engine/selector.h" #include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm.h" @@ -39,6 +40,7 @@ namespace Sci { struct Node; // from segment.h struct List; // from segment.h +struct SelectorCache; // from selector.h /** * @defgroup VocabularyResources Vocabulary resources in SCI diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 351e7c6a7b..f6a6afd196 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -33,6 +33,7 @@ #include "sci/event.h" #include "sci/engine/features.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/message.h" #include "sci/engine/savegame.h" diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 65024742c7..00480743cc 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -24,6 +24,7 @@ */ #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 851ff6bc81..acb7912d8d 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -30,10 +30,120 @@ #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm.h" -#include "sci/engine/kernel.h" // for Kernel::_selectorCache namespace Sci { +/** Contains selector IDs for a few selected selectors */ +struct SelectorCache { + SelectorCache() { + memset(this, 0, sizeof(*this)); + } + + // Statically defined selectors, (almost the) same in all SCI versions + Selector y; + Selector x; + Selector view, loop, cel; ///< Description of a specific image + Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data + Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen') + Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls + Selector signal; ///< Used by Animate() to control a view's behaviour + Selector illegalBits; ///< Used by CanBeHere + Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle + // name, key, time + Selector text; ///< Used by controls + Selector elements; ///< Used by SetSynonyms() + // color, back + Selector mode; ///< Used by text controls (-> DrawControl()) + // style + Selector state, font, type;///< Used by controls + // window + Selector cursor, max; ///< Used by EditControl + // mark, who + Selector message; ///< Used by GetEvent + // edit + Selector play; ///< Play function (first function to be called) + Selector number; + Selector handle; ///< Replaced by nodePtr in SCI1+ + Selector nodePtr; ///< Replaces handle in SCI1+ + Selector client; ///< The object that wants to be moved + Selector dx, dy; ///< Deltas + Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars + Selector xStep, yStep; ///< BR adjustments + Selector moveSpeed; ///< Used for DoBresen + Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0 + Selector heading, mover; ///< Used in DoAvoider + Selector doit; ///< Called (!) by the Animate() system call + Selector isBlocked, looper; ///< Used in DoAvoider + Selector priority; + Selector modifiers; ///< Used by GetEvent + Selector replay; ///< Replay function + // setPri, at, next, done, width + Selector wordFail, syntaxFail; ///< Used by Parse() + // semanticFail, pragmaFail + // said + Selector claimed; ///< Used generally by the event mechanism + // value, save, restore, title, button, icon, draw + Selector delete_; ///< Called by Animate() to dispose a view object + Selector z; + + // SCI1+ static selectors + Selector parseLang; + Selector printLang; ///< Used for i18n + Selector subtitleLang; + Selector size; + Selector points; ///< Used by AvoidPath() + Selector palette; + Selector dataInc; + // handle (in SCI1) + Selector min; ///< SMPTE time format + Selector sec; + Selector frame; + Selector vol; + Selector pri; + // perform + Selector moveDone; ///< used for DoBresen + + // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static + Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere + Selector topString; ///< SCI1 scroll lists use this instead of lsTop + Selector flags; + + // SCI1+ audio sync related selectors, not static. They're used for lip syncing in + // CD talkie games + Selector syncCue; ///< Used by DoSync() + Selector syncTime; + + // SCI1.1 specific selectors + Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+) + Selector scaleX, scaleY; ///< SCI1.1 view scaling + Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling + Selector vanishingX; ///< SCI1.1 view scaling, used by global scaling + Selector vanishingY; ///< SCI1.1 view scaling, used by global scaling + + // Used for auto detection purposes + Selector overlay; ///< Used to determine if a game is using old gfx functions or not + + // SCI1.1 Mac icon bar selectors + Selector iconIndex; ///< Used to index icon bar objects + +#ifdef ENABLE_SCI32 + Selector data; // Used by Array()/String() + Selector picture; // Used to hold the picture ID for SCI32 pictures + + Selector plane; + Selector top; + Selector left; + Selector bottom; + Selector right; + Selector resX; + Selector resY; + + Selector fore; + Selector back; + Selector dimmed; +#endif +}; + /** * Map a selector name to a selector id. Shortcut for accessing the selector cache. */ diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 129976ce99..4b99097476 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -29,6 +29,7 @@ #include "sci/debug.h" // for g_debug_sleeptime_factor #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 9de7cc587c..88898cdbba 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -71,117 +71,6 @@ struct Class { #define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) -/** Contains selector IDs for a few selected selectors */ -struct SelectorCache { - SelectorCache() { - memset(this, 0, sizeof(*this)); - } - - // Statically defined selectors, (almost the) same in all SCI versions - Selector y; - Selector x; - Selector view, loop, cel; ///< Description of a specific image - Selector underBits; ///< Used by the graphics subroutines to store backupped BG pic data - Selector nsTop, nsLeft, nsBottom, nsRight; ///< View boundaries ('now seen') - Selector lsTop, lsLeft, lsBottom, lsRight; ///< Used by Animate() subfunctions and scroll list controls - Selector signal; ///< Used by Animate() to control a view's behaviour - Selector illegalBits; ///< Used by CanBeHere - Selector brTop, brLeft, brBottom, brRight; ///< Bounding Rectangle - // name, key, time - Selector text; ///< Used by controls - Selector elements; ///< Used by SetSynonyms() - // color, back - Selector mode; ///< Used by text controls (-> DrawControl()) - // style - Selector state, font, type;///< Used by controls - // window - Selector cursor, max; ///< Used by EditControl - // mark, who - Selector message; ///< Used by GetEvent - // edit - Selector play; ///< Play function (first function to be called) - Selector number; - Selector handle; ///< Replaced by nodePtr in SCI1+ - Selector nodePtr; ///< Replaces handle in SCI1+ - Selector client; ///< The object that wants to be moved - Selector dx, dy; ///< Deltas - Selector b_movCnt, b_i1, b_i2, b_di, b_xAxis, b_incr; ///< Various Bresenham vars - Selector xStep, yStep; ///< BR adjustments - Selector moveSpeed; ///< Used for DoBresen - Selector canBeHere; ///< Funcselector: Checks for movement validity in SCI0 - Selector heading, mover; ///< Used in DoAvoider - Selector doit; ///< Called (!) by the Animate() system call - Selector isBlocked, looper; ///< Used in DoAvoider - Selector priority; - Selector modifiers; ///< Used by GetEvent - Selector replay; ///< Replay function - // setPri, at, next, done, width - Selector wordFail, syntaxFail; ///< Used by Parse() - // semanticFail, pragmaFail - // said - Selector claimed; ///< Used generally by the event mechanism - // value, save, restore, title, button, icon, draw - Selector delete_; ///< Called by Animate() to dispose a view object - Selector z; - - // SCI1+ static selectors - Selector parseLang; - Selector printLang; ///< Used for i18n - Selector subtitleLang; - Selector size; - Selector points; ///< Used by AvoidPath() - Selector palette; - Selector dataInc; - // handle (in SCI1) - Selector min; ///< SMPTE time format - Selector sec; - Selector frame; - Selector vol; - Selector pri; - // perform - Selector moveDone; ///< used for DoBresen - - // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static - Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere - Selector topString; ///< SCI1 scroll lists use this instead of lsTop - Selector flags; - - // SCI1+ audio sync related selectors, not static. They're used for lip syncing in - // CD talkie games - Selector syncCue; ///< Used by DoSync() - Selector syncTime; - - // SCI1.1 specific selectors - Selector scaleSignal; //< Used by kAnimate() for cel scaling (SCI1.1+) - Selector scaleX, scaleY; ///< SCI1.1 view scaling - Selector maxScale; ///< SCI1.1 view scaling, limit for cel, when using global scaling - Selector vanishingX; ///< SCI1.1 view scaling, used by global scaling - Selector vanishingY; ///< SCI1.1 view scaling, used by global scaling - - // Used for auto detection purposes - Selector overlay; ///< Used to determine if a game is using old gfx functions or not - - // SCI1.1 Mac icon bar selectors - Selector iconIndex; ///< Used to index icon bar objects - -#ifdef ENABLE_SCI32 - Selector data; // Used by Array()/String() - Selector picture; // Used to hold the picture ID for SCI32 pictures - - Selector plane; - Selector top; - Selector left; - Selector bottom; - Selector right; - Selector resX; - Selector resY; - - Selector fore; - Selector back; - Selector dimmed; -#endif -}; - // A reference to an object's variable. // The object is stored as a reg_t, the variable as an index into _variables struct ObjVarRef { diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 9051111d2d..59cbedd7a2 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 47b4f22607..a245eefdda 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/compare.h" diff --git a/engines/sci/graphics/controls.cpp b/engines/sci/graphics/controls.cpp index 26af9741c2..ff5a91eed4 100644 --- a/engines/sci/graphics/controls.cpp +++ b/engines/sci/graphics/controls.cpp @@ -30,6 +30,7 @@ #include "sci/sci.h" #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/ports.h" diff --git a/engines/sci/graphics/coordadjuster.cpp b/engines/sci/graphics/coordadjuster.cpp index 422df52f27..9481a68f13 100644 --- a/engines/sci/graphics/coordadjuster.cpp +++ b/engines/sci/graphics/coordadjuster.cpp @@ -26,6 +26,7 @@ #include "common/util.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/coordadjuster.h" diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 05c2a1b7ad..4247c4db9e 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -28,6 +28,7 @@ #include "graphics/primitives.h" #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/vm.h" @@ -86,7 +87,6 @@ void GfxFrameout::kernelDeleteScreenItem(reg_t object) { int16 GfxFrameout::kernelGetHighPlanePri() { sortPlanes(); - reg_t object = _planes.back(); return readSelectorValue(g_sci->getEngineState()->_segMan, _planes.back(), SELECTOR(priority)); } diff --git a/engines/sci/graphics/maciconbar.cpp b/engines/sci/graphics/maciconbar.cpp index a06e98ccbf..6f2c9596db 100644 --- a/engines/sci/graphics/maciconbar.cpp +++ b/engines/sci/graphics/maciconbar.cpp @@ -24,6 +24,7 @@ */ #include "sci/sci.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" #include "sci/engine/state.h" #include "sci/graphics/maciconbar.h" diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 00eb533b41..323539573b 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -29,6 +29,7 @@ #include "sci/sci.h" #include "sci/event.h" +#include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/graphics/ports.h" diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 6470b17e83..043f2b8516 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -34,6 +34,7 @@ #include "sci/sound/music.h" #include "sci/sound/soundcmd.h" +#include "sci/engine/kernel.h" #include "sci/engine/selector.h" namespace Sci { -- cgit v1.2.3 From 496905dcc3f0871ef763de133010dc3b996de21d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 16:49:03 +0000 Subject: SCI: dont write palette in reorderView() if there is no palette :P svn-id: r50184 --- engines/sci/decompressor.cpp | 16 +++++++++------- 1 file changed, 9 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/decompressor.cpp b/engines/sci/decompressor.cpp index 84af50b596..96c7f24ef6 100644 --- a/engines/sci/decompressor.cpp +++ b/engines/sci/decompressor.cpp @@ -574,15 +574,17 @@ void DecompressorLZW::reorderView(byte *src, byte *dest) { for (c = 0; c < cel_total; c++) decodeRLE(&rle_ptr, &pix_ptr, cc_pos[c] + 8, cc_lengths[c]); - *writer++ = 'P'; - *writer++ = 'A'; - *writer++ = 'L'; + if (pal_offset) { + *writer++ = 'P'; + *writer++ = 'A'; + *writer++ = 'L'; - for (c = 0; c < 256; c++) - *writer++ = c; + for (c = 0; c < 256; c++) + *writer++ = c; - seeker -= 4; /* The missing four. Don't ask why. */ - memcpy(writer, seeker, 4*256 + 4); + seeker -= 4; /* The missing four. Don't ask why. */ + memcpy(writer, seeker, 4*256 + 4); + } free(cc_pos); free(cc_lengths); -- cgit v1.2.3 From e39f2ae1c19ecc1bf42a20ab1eb430e09e46ef52 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 16:53:56 +0000 Subject: SCI: adding cnick-longbow to inbetween sci1.1 in GfxPalette svn-id: r50185 --- engines/sci/graphics/palette.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index ef20aafc82..759f8979f3 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -74,7 +74,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) if (gameId == "laurabow2" || gameId == "qfg3" || gameId == "ecoquest") _alwaysForceRealMerge = true; } else { - if (gameId == "pq1sci" || gameId == "cnick-sq") + if (gameId == "pq1sci" || gameId == "cnick-sq" || gameId == "cnick-longbow") _alwaysForceRealMerge = true; } -- cgit v1.2.3 From e7634ee147323f1c698cc87671d5f49d40a16526 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 16:58:42 +0000 Subject: SCI: it seems that all cnick games are using the inbetween interpreter svn-id: r50186 --- engines/sci/graphics/palette.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 759f8979f3..28edfae24b 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -62,19 +62,17 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _alwaysForceRealMerge = false; // Pseudo-WORKAROUND - // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and Nick's Picks Space Quest + // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and all Nick's Picks // all use an inbetween interpreter, some parts are SCI1.1, some parts are SCI1 // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case - // FIXME: the other nick's Picks may also use the same interpreter, but we can not verify - // if the other games also get reported having palette issues, add them here Common::String gameId = g_sci->getGameId(); if (g_sci->isDemo()) { if (gameId == "laurabow2" || gameId == "qfg3" || gameId == "ecoquest") _alwaysForceRealMerge = true; } else { - if (gameId == "pq1sci" || gameId == "cnick-sq" || gameId == "cnick-longbow") + if (gameId == "pq1sci" || gameId == "cnick-sq" || gameId == "cnick-longbow" || gameId == "cnick-kq" || gameId == "cnick-laurabow" || gameId == "cnick-lsl") _alwaysForceRealMerge = true; } -- cgit v1.2.3 From 72ee20bc4d2aa4326530d1f91f2c5e5b3f6fa5db Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 17:05:54 +0000 Subject: SCI: cnick-laurabow & cnick-kq are called with -Nw 0 0... svn-id: r50187 --- engines/sci/graphics/ports.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index b8e3ec9c9d..a9bf81f013 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -84,11 +84,11 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te else _styleUser = SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_TRANSPARENT; - // Jones, Slater and Hoyle 3 were called with parameter -Nw 0 0 200 320. + // Jones, Slater, Hoyle 3&4 and Crazy Nicks Laura Bow/Kings Quest were called with parameter -Nw 0 0 200 320. // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort Common::String gameId = g_sci->getGameId(); - if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) + if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || gameId == "cnick-laurabow" || gameId == "cnick-kq" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) offTop = 0; // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere if (gameId == "fairytales") -- cgit v1.2.3 From 6d1f2d1d26ed1faad4c55aa8b4e71a290f0137fa Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 23 Jun 2010 17:30:18 +0000 Subject: Fixed memory fragmentation warnings in Crazy Nick's games svn-id: r50188 --- engines/sci/engine/kmisc.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 64da511ca8..4dd7df1b52 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -105,7 +105,11 @@ enum kMemoryInfoFunc { }; reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { - const uint16 size = 0x7fff; // Must not be 0xffff, or some memory calculations will overflow + // The free heap size returned must not be 0xffff, or some memory + // calculations will overflow. Crazy Nick's games handle up to 32746 + // bytes (0x7fea), otherwise they throw a warning that the memory is + // fragmented + const uint16 size = 0x7fea; switch (argv[0].offset) { case K_MEMORYINFO_LARGEST_HEAP_BLOCK: -- cgit v1.2.3 From 51ba34df0e7fce4f9760de9c2b3c0da77d605e06 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 23 Jun 2010 20:13:33 +0000 Subject: SCI: we extended the showBits() rect all the way depending on where the object moved, fixed - fixes kq6cd flickering coin and pq1 flickering locker issue svn-id: r50190 --- engines/sci/graphics/animate.cpp | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 59cbedd7a2..9018a6f62e 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -472,10 +472,12 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { _paint16->bitsShow(lsRect); workerRect = listEntry->celRect; } - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), workerRect.left); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), workerRect.top); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), workerRect.right); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), workerRect.bottom); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), listEntry->celRect.left); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), listEntry->celRect.top); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), listEntry->celRect.right); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), listEntry->celRect.bottom); + // may get used for debugging + //_paint16->frameRect(workerRect); _paint16->bitsShow(workerRect); if (signal & kSignalHidden) { -- cgit v1.2.3 From 3838197ac14be050f1b2db5e1f26d82052dbd331 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 24 Jun 2010 01:29:46 +0000 Subject: Silence gcc warnings. svn-id: r50197 --- engines/m4/sprite.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 55de6714d1..48a36ac26e 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -125,19 +125,19 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { fillRect(bounds(), TRANSPARENT_COLOUR_INDEX); // Major line loop - for (int y = 0; y < h; ++y) { + for (int y2 = 0; y2 < h; ++y2) { byte *destP = getBasePtr(0, y); bool newLine = false; byte cmd = source->readByte(); - int x = 0; + int x2 = 0; if (cmd == 0xff) // The entire line is empty newLine = true; else if (cmd == 0xFD) { // Lines contains only run lenghs of pixels - while (x < w) { - byte cmd = source->readByte(); + while (x2 < w) { + cmd = source->readByte(); if (cmd == 0xff) { // End of line reached newLine = true; @@ -146,14 +146,14 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { byte v = source->readByte(); while (cmd-- > 0) { - if (x < w) + if (x2 < w) *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; - ++x; + ++x2; } } } else { // Line intermixes run lengths with individual pixels - while (x < w) { + while (x2 < w) { cmd = source->readByte(); if (cmd == 0xff) { // End of line reached @@ -166,15 +166,15 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { cmd = source->readByte(); byte v = source->readByte(); while (cmd-- > 0) { - if (x < w) { + if (x2 < w) { *destP++ = (v == 0xFD) ? TRANSPARENT_COLOUR_INDEX : v; } - ++x; + ++x2; } } else { // Handle writing out single pixel *destP++ = (cmd == 0xFD) ? TRANSPARENT_COLOUR_INDEX : cmd; - ++x; + ++x2; } } } -- cgit v1.2.3 From 7c9cbf75c0ed6e66b5c7875f5e7657313b943a5c Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 24 Jun 2010 05:31:07 +0000 Subject: Implement the rest of xvalvecontrol for the boiler puzzle in Riven, initialize a variable for the boiler platform switch. svn-id: r50200 --- engines/mohawk/riven_external.cpp | 39 ++++++++++++++++++++++++++++++++------- engines/mohawk/riven_vars.cpp | 1 + 2 files changed, 33 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 89e10c7deb..5b5163dbb3 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -662,15 +662,17 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) { // Get the variable for the valve uint32 *valve = _vm->matchVarToString("bvalve"); - Common::Event event; int changeX = 0; int changeY = 0; + bool done = false; // Set the cursor to the closed position _vm->_gfx->changeCursor(2004); _vm->_system->updateScreen(); - for (;;) { + while (!done) { + Common::Event event; + while (_vm->_system->getEventManager()->pollEvent(event)) { switch (event.type) { case Common::EVENT_MOUSEMOVE: @@ -682,30 +684,53 @@ void RivenExternal::xvalvecontrol(uint16 argc, uint16 *argv) { // FIXME: These values for changes in x/y could be tweaked. if (*valve == 0 && changeY <= -10) { *valve = 1; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(2); _vm->refreshCard(); } else if (*valve == 1) { if (changeX >= 0 && changeY >= 10) { *valve = 0; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(3); _vm->refreshCard(); } else if (changeX <= -10 && changeY <= 10) { *valve = 2; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(1); _vm->refreshCard(); } } else if (*valve == 2 && changeX >= 10) { *valve = 1; - // TODO: Play movie + _vm->_gfx->changeCursor(kRivenHideCursor); + _vm->_video->playMovieBlocking(4); _vm->refreshCard(); } - return; + done = true; default: break; } } _vm->_system->delayMillis(10); } + + // If we changed state and the new state is that the valve is flowing to + // the boiler, we need to update the boiler state. + if (*valve == 1) { + if (*_vm->matchVarToString("bidvlv") == 1) { // Check which way the water is going at the boiler + if (*_vm->matchVarToString("bblrarm") == 1) { + // If the pipe is open, make sure the water is drained out + *_vm->matchVarToString("bheat") = 0; + *_vm->matchVarToString("bblrwtr") = 0; + } else { + // If the pipe is closed, fill the boiler again + *_vm->matchVarToString("bheat") = *_vm->matchVarToString("bblrvalve"); + *_vm->matchVarToString("bblrwtr") = 1; + } + } else { + // Have the grating inside the boiler match the switch outside + *_vm->matchVarToString("bblrgrt") = (*_vm->matchVarToString("bblrsw") == 1) ? 0 : 1; + } + } } void RivenExternal::xbchipper(uint16 argc, uint16 *argv) { diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index 3f7cd5a8b6..163626203a 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -319,6 +319,7 @@ void MohawkEngine_Riven::initVars() { *matchVarToString("bheat") = 1; *matchVarToString("waterenabled") = 1; *matchVarToString("ogehnpage") = 1; + *matchVarToString("bblrsw") = 1; // Randomize the telescope combination uint32 *teleCombo = matchVarToString("tcorrectorder"); -- cgit v1.2.3 From f65c4f988639b1ba5e6b2a95174aef3ec7fd8941 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 07:32:34 +0000 Subject: Changed an error in LocalVariables::dereference() back to a warning, as it occurs in 2 places during the intro of LB2 (called from kMemory(peek)) svn-id: r50202 --- engines/sci/engine/segment.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 98f03ff18a..28cc03d175 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -464,7 +464,10 @@ SegmentRef LocalVariables::dereference(reg_t pointer) { if (ret.maxSize > 0) { ret.reg = &_locals[pointer.offset / 2]; } else { - error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + // Happens in two places during the intro of LB2CD, both from kMemory(peek): + // - room 160: Heap 160 has 83 local variables (0-82), and the game asks for variables at indices 83 - 90 too + // - room 220: Heap 220 has 114 local variables (0-113), and the game asks for variables at indices 114-120 too + warning("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); ret.reg = 0; } return ret; -- cgit v1.2.3 From bbb29e2650bf9b51818e710fb177b6b19894c1fe Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 07:54:02 +0000 Subject: Fixed script 140 in the Island of Dr. Brain by adding a workaround for it inside op_link svn-id: r50203 --- engines/sci/engine/vm.cpp | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 350734f8fc..de04c49ef7 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -757,6 +757,9 @@ void run_vm(EngineState *s, bool restoring) { int old_executionStackBase = s->executionStackBase; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) + // Used for a workaround in op_link below, in order to avoid string matching (which can + // be slow if used in the game script interpreter) + bool isIslandOfDrBrain = (g_sci->getGameId() == "islandbrain"); if (!local_script) { error("run_vm(): program counter gone astray (local_script pointer is null)"); @@ -1128,8 +1131,15 @@ void run_vm(EngineState *s, bool restoring) { break; case op_link: // 0x1f (31) - for (int i = 0; i < opparams[0]; i++) - s->xs->sp[i] = NULL_REG; + if (local_script->_nr == 140 && isIslandOfDrBrain) { + // WORKAROUND for The Island of Dr. Brain, room 140. + // Script 140 runs in an endless loop if we set its + // variables to 0 here. + } else { + for (int i = 0; i < opparams[0]; i++) + s->xs->sp[i] = NULL_REG; + } + s->xs->sp += opparams[0]; break; -- cgit v1.2.3 From 70e9df9566007a495f5b77fa6ee4c6d31efdbe15 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 24 Jun 2010 08:15:31 +0000 Subject: Corrected incorrect variable name change svn-id: r50204 --- engines/m4/sprite.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 48a36ac26e..4ce1b75b35 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -125,8 +125,8 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { fillRect(bounds(), TRANSPARENT_COLOUR_INDEX); // Major line loop - for (int y2 = 0; y2 < h; ++y2) { - byte *destP = getBasePtr(0, y); + for (int yp = 0; yp < h; ++yp) { + byte *destP = getBasePtr(0, yp); bool newLine = false; byte cmd = source->readByte(); int x2 = 0; -- cgit v1.2.3 From cd8bec1ae28c89f89fa8e4707a81b2947bd9ebc5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 24 Jun 2010 08:16:40 +0000 Subject: Corrected rendering of sprites into a scene background svn-id: r50205 --- engines/m4/mads_views.cpp | 31 +++++++++++++++++-------------- engines/m4/mads_views.h | 2 +- 2 files changed, 18 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index a644e81d51..1184ab81e7 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -133,20 +133,22 @@ bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) { typedef Common::List DepthList; -void MadsSpriteSlots::drawBackground() { +void MadsSpriteSlots::drawBackground(int yOffset) { // Draw all active sprites onto the background surface for (int i = 0; i < startIndex; ++i) { - if (_entries[i].spriteType >= 0) { + MadsSpriteSlot &slot = _entries[i]; + + if (slot.spriteType >= 0) { _owner._dirtyAreas[i].active = false; } else { _owner._dirtyAreas[i].textActive = true; - _owner._dirtyAreas.setSpriteSlot(i, _entries[i]); + _owner._dirtyAreas.setSpriteSlot(i, slot); - if (_entries[i].spriteType == BACKGROUND_SPRITE) { - SpriteAsset &spriteSet = getSprite(_entries[i].spriteListIndex); - M4Sprite *frame = spriteSet.getFrame((_entries[i].frameNumber & 0x7fff) - 1); - int xp = _entries[i].xp; - int yp = _entries[i].yp; + if (slot.spriteType == BACKGROUND_SPRITE) { + SpriteAsset &spriteSet = getSprite(slot.spriteListIndex); + M4Sprite *frame = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); + int xp = slot.xp; + int yp = slot.yp; if (_entries[i].scale != -1) { // Adjust position based on frame size @@ -154,12 +156,13 @@ void MadsSpriteSlots::drawBackground() { yp -= frame->height() / 2; } - if (_entries[i].depth <= 1) { - // No depth, so simply copy the frame onto the background - frame->copyTo(_owner._bgSurface, xp, yp, 0); + if (slot.depth > 1) { + // Draw the frame with depth processing + _owner._bgSurface->copyFrom(frame, xp, yp, Common::Point(0, yOffset), slot.depth, + _owner._depthSurface, 100, frame->getTransparencyIndex()); } else { - // Depth was specified, so draw frame using scene's depth information - frame->copyTo(_owner._bgSurface, xp, yp, _entries[i].depth, _owner._depthSurface, 100, 0); + // No depth, so simply draw the image + frame->copyTo(_owner._bgSurface, xp, yp + yOffset, frame->getTransparencyIndex()); } } } @@ -1201,7 +1204,7 @@ MadsView::~MadsView() { void MadsView::refresh() { // Draw any sprites - _spriteSlots.drawBackground(); + _spriteSlots.drawBackground(_yOffset); // Process dirty areas _textDisplay.setDirtyAreas(); diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index f0ded634b1..843596412e 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -97,7 +97,7 @@ public: void clear(); void deleteTimer(int seqIndex); - void drawBackground(); + void drawBackground(int yOffset); void drawForeground(View *view, int yOffset); void setDirtyAreas(); void fullRefresh(); -- cgit v1.2.3 From aa0c86e7557fbe68d33dec52139015562004742f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 24 Jun 2010 08:17:46 +0000 Subject: Bugfix for correctly decoding 2-bit encoded depth surfaces svn-id: r50206 --- engines/m4/mads_scene.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index a464438981..60fffadc07 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -714,7 +714,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) { byte v = byteVal; for (int bitCtr = 0; bitCtr < 4; ++bitCtr, v >>= 2) - *destP++ = v & 3; + *destP++ = (((v & 1) + 1) << 3) - 1; } } else { // 8-bit depth pixels -- cgit v1.2.3 From 0fb54293181d76d5b84cb7da5ff54c883630bf86 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 09:52:08 +0000 Subject: Initialize the stack with 'S' or 's' characters, like SSCI does (ultimately, we should not change the stack again like we do in op_link - this is what Sierra is doing). Some cleanup svn-id: r50207 --- engines/sci/engine/kgraphics.cpp | 2 +- engines/sci/engine/klists.cpp | 3 +-- engines/sci/engine/seg_manager.cpp | 8 +++++++- 3 files changed, 9 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index bc278a2bb1..eaef049951 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -540,7 +540,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened, // till the actual problem is found - if (g_sci->getGameId() == "lsl1sci" && s->currentRoomNumber() == 300) { + if (s->currentRoomNumber() == 300 && g_sci->getGameId() == "lsl1sci") { int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop)); writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2); } diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 86d82bd3d1..1fd34849ea 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -115,8 +115,7 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { reg_t kNewList(EngineState *s, int argc, reg_t *argv) { reg_t listbase; - List *l; - l = s->_segMan->allocateList(&listbase); + List *l = s->_segMan->allocateList(&listbase); l->first = l->last = NULL_REG; debugC(2, kDebugLevelNodes, "New listbase at %04x:%04x", PRINT_REG(listbase)); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 5371238304..b464438553 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -402,6 +402,12 @@ DataStack *SegManager::allocateStack(int size, SegmentId *segid) { retval->_entries = (reg_t *)calloc(size, sizeof(reg_t)); retval->_capacity = size; + // SSCI initializes the stack with "S" characters (uppercase S in SCI0-SCI1, + // lowercase s in SCI0 and SCI11) - probably stands for "stack" + byte filler = (getSciVersion() >= SCI_VERSION_01 && getSciVersion() <= SCI_VERSION_1_LATE) ? 'S' : 's'; + for (int i = 0; i < size; i++) + retval->_entries[i] = make_reg(0, filler); + return retval; } @@ -448,7 +454,7 @@ byte *SegManager::getHunkPointer(reg_t addr) { HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); if (!ht || !ht->isValidEntry(addr.offset)) { - warning("getHunkPointer() with invalid handle"); + warning("getHunkPointer() with invalid handle %04x:%04x", PRINT_REG(addr)); return NULL; } -- cgit v1.2.3 From afffcec96ec03a0e39d692080849e2e36722637a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 11:29:26 +0000 Subject: Turned two hacks inside validate_property() into errors till we find out where and why they occur (they shouldn't occur). Also turned an error inside send_selector() when argc > 1 into a warning - these are usually script bugs and aren't fatal svn-id: r50208 --- engines/sci/engine/vm.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index de04c49ef7..53cba93f98 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -103,13 +103,19 @@ static reg_t &validate_property(Object *obj, int index) { // may modify the value of the returned reg_t. static reg_t dummyReg = NULL_REG; + // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead + // to all sorts of issues! Turned it into an error for now... + // If this occurs, it means there's probably something wrong with the garbage + // collector, so don't hide it with fake return values if (!obj) { - debugC(2, kDebugLevelVM, "[VM] Sending to disposed object!"); + error("Sending to disposed object"); return dummyReg; } + // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead + // to all sorts of issues! Turned it into an error for now... if (index < 0 || (uint)index >= obj->getVarCount()) { - debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!", + error("Invalid object property #%d (out of [0..%d]) requested!", index, obj->getVarCount()); return dummyReg; } @@ -421,11 +427,11 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt // QFG1VGA has a script bug in the longSong object when invoking the // loop selector, which doesn't affect gameplay, thus don't diplay it } else { - // Unknown script bug, show it + // Unknown script bug, show it. Usually these aren't fatal. reg_t oldReg = *varp.getPointer(s->_segMan); reg_t newReg = argp[1]; const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); - error("send_selector(): argc = %d while modifying variable selector " + warning("send_selector(): argc = %d while modifying variable selector " "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", argc, selector, selectorName, PRINT_REG(send_obj), objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); -- cgit v1.2.3 From 9a3ef9b8e17151993c9b1a6f79fd97ec058a4cc9 Mon Sep 17 00:00:00 2001 From: Arnaud Boutonné Date: Thu, 24 Jun 2010 11:50:25 +0000 Subject: Initialize properly paramCount in gob1. This fixes several valgrind errors, and the unknown opcodes are now skipped as expected. (related to bug #3018918, only partially solved) svn-id: r50209 --- engines/gob/inter_v1.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index 805893d8a7..b35e0b8a82 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -1331,7 +1331,8 @@ bool Inter_v1::o1_goblinFunc(OpFuncParams ¶ms) { gobParams.retVarPtr.set(*_variables, 236); cmd = _vm->_game->_script->readInt16(); - _vm->_game->_script->skip(2); + gobParams.paramCount = _vm->_game->_script->readInt16(); + if ((cmd > 0) && (cmd < 17)) { objDescSet = true; gobParams.extraData = _vm->_game->_script->readInt16(); -- cgit v1.2.3 From 0722d96a3e249a7efe853d77b1432100912499d1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 11:52:08 +0000 Subject: SCI: fix kTextSize to not crash when destination has an invalid rect in it svn-id: r50210 --- engines/sci/graphics/text16.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index c9a7f09973..e9adac9572 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -467,7 +467,7 @@ bool GfxText16::SwitchToFont900OnSjis(const char *text) { } void GfxText16::kernelTextSize(const char *text, int16 font, int16 maxWidth, int16 *textWidth, int16 *textHeight) { - Common::Rect rect(0, 0, *textWidth, *textHeight); + Common::Rect rect(0, 0, 0, 0); Size(rect, text, font, maxWidth); *textWidth = rect.width(); *textHeight = rect.height(); -- cgit v1.2.3 From f93ca1e4242da27079e6ce4cd4d4e8d569984ec4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 11:54:33 +0000 Subject: SCI: implement detection for uninitialized temp variable reads and implement direct fixes for them, i couldnt figure out a valid replacement for island, pharkas and laurabow2 work that way. this should also get changed to a replacement table svn-id: r50211 --- engines/sci/engine/kgraphics.cpp | 4 +++- engines/sci/engine/vm.cpp | 49 +++++++++++++++++++++++++++++----------- 2 files changed, 39 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index eaef049951..3d1bca320b 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -351,7 +351,7 @@ reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { } textWidth = dest[3].toUint16(); textHeight = dest[2].toUint16(); - + #ifdef ENABLE_SCI32 if (!g_sci->_gfxText16) { // TODO: Implement this @@ -1041,6 +1041,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; +#if 0 if (g_sci->getGameId() == "freddypharkas") { // WORKAROUND // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that @@ -1058,6 +1059,7 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { if ((viewId == 995) && (priority == 0)) priority = 15; } +#endif g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 53cba93f98..fdd2032ce3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -184,9 +184,28 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in } static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { - if (validate_variable(r, stack_base, type, max, index, line)) + if (validate_variable(r, stack_base, type, max, index, line)) { + if (type == VAR_TEMP && r[index].segment == 0xffff) { + // Uninitialized read on a temp + // We need to find correct replacements for each situation manually + // FIXME: this should use a table which contains workarounds for gameId, scriptnumber and temp index and + // a replacement value + Script *local_script = g_sci->getEngineState()->_segMan->getScriptIfLoaded(g_sci->getEngineState()->xs->local_segment); + int currentScriptNr = local_script->_nr; + warning("uninitialized read for temp %d, script %d", index, currentScriptNr); + Common::String gameId = g_sci->getGameId(); + if ((gameId == "laurabow2") && (currentScriptNr == 24) && (index == 5)) + return make_reg(0, 0xf); // priority replacement for menu + if ((gameId == "freddypharkas") && (currentScriptNr == 24) && (index == 5)) + return make_reg(0, 0xf); // priority replacement for menu + if ((gameId == "islandbrain") && (currentScriptNr == 140) && (index == 3)) { + r[index] = make_reg(0, 255); + return r[index]; + } + error("uninitialized read!"); + } return r[index]; - else + } else return default_value; } @@ -763,9 +782,6 @@ void run_vm(EngineState *s, bool restoring) { int old_executionStackBase = s->executionStackBase; // Used to detect the stack bottom, for "physical" returns const byte *code_buf = NULL; // (Avoid spurious warning) - // Used for a workaround in op_link below, in order to avoid string matching (which can - // be slow if used in the game script interpreter) - bool isIslandOfDrBrain = (g_sci->getGameId() == "islandbrain"); if (!local_script) { error("run_vm(): program counter gone astray (local_script pointer is null)"); @@ -1137,14 +1153,21 @@ void run_vm(EngineState *s, bool restoring) { break; case op_link: // 0x1f (31) - if (local_script->_nr == 140 && isIslandOfDrBrain) { - // WORKAROUND for The Island of Dr. Brain, room 140. - // Script 140 runs in an endless loop if we set its - // variables to 0 here. - } else { - for (int i = 0; i < opparams[0]; i++) - s->xs->sp[i] = NULL_REG; - } + // We shouldn't initialize temp variables at all + // We put special segment 0xFFFF in there, so that uninitialized reads can get detected + for (int i = 0; i < opparams[0]; i++) + s->xs->sp[i] = make_reg(0xffff, 0xffff); +// for (int i = 0; i < opparams[0]; i++) +// s->xs->sp[i] = make_reg(0, 'ss'); + + //if (local_script->_nr == 140 && isIslandOfDrBrain) { + // // WORKAROUND for The Island of Dr. Brain, room 140. + // // Script 140 runs in an endless loop if we set its + // // variables to 0 here. + //} else { + // for (int i = 0; i < opparams[0]; i++) + // s->xs->sp[i] = NULL_REG; + //} s->xs->sp += opparams[0]; break; -- cgit v1.2.3 From e5f22da0510065f1d38cfe745c49873f07de6904 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 12:25:47 +0000 Subject: SCI: added objectname and method name printed out when uninitialized temps are read svn-id: r50212 --- engines/sci/engine/vm.cpp | 23 +++++++++++++++++++---- 1 file changed, 19 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fdd2032ce3..6af5783e3b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -190,17 +190,32 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i // We need to find correct replacements for each situation manually // FIXME: this should use a table which contains workarounds for gameId, scriptnumber and temp index and // a replacement value - Script *local_script = g_sci->getEngineState()->_segMan->getScriptIfLoaded(g_sci->getEngineState()->xs->local_segment); + EngineState *engine = g_sci->getEngineState(); + Script *local_script = engine->_segMan->getScriptIfLoaded(engine->xs->local_segment); int currentScriptNr = local_script->_nr; - warning("uninitialized read for temp %d, script %d", index, currentScriptNr); + + Common::List::iterator callIterator = engine->_executionStack.begin(); + ExecStack call = *callIterator; + while (callIterator != engine->_executionStack.end()) { + call = *callIterator; + callIterator++; + } + + const char *objName = engine->_segMan->getObjectName(call.sendp); + const char *selectorName = ""; + if (call.type == EXEC_STACK_TYPE_CALL) { + selectorName = g_sci->getKernel()->getSelectorName(call.selector).c_str(); + } + warning("uninitialized read for temp %d from method %s::%s (script %d)", index, objName, selectorName, currentScriptNr); + Common::String gameId = g_sci->getGameId(); if ((gameId == "laurabow2") && (currentScriptNr == 24) && (index == 5)) return make_reg(0, 0xf); // priority replacement for menu if ((gameId == "freddypharkas") && (currentScriptNr == 24) && (index == 5)) return make_reg(0, 0xf); // priority replacement for menu if ((gameId == "islandbrain") && (currentScriptNr == 140) && (index == 3)) { - r[index] = make_reg(0, 255); - return r[index]; + //r[index] = make_reg(0, 255); + //return r[index]; } error("uninitialized read!"); } -- cgit v1.2.3 From 898c9165d9a7f110b674a8bee82d30090a6010bc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 12:32:41 +0000 Subject: SCI: added currently known object/methodnames in comments for uninitialized reads svn-id: r50213 --- engines/sci/engine/vm.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 6af5783e3b..4204131ad3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -210,10 +210,11 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i Common::String gameId = g_sci->getGameId(); if ((gameId == "laurabow2") && (currentScriptNr == 24) && (index == 5)) - return make_reg(0, 0xf); // priority replacement for menu + return make_reg(0, 0xf); // priority replacement for menu - gcWin::open if ((gameId == "freddypharkas") && (currentScriptNr == 24) && (index == 5)) - return make_reg(0, 0xf); // priority replacement for menu + return make_reg(0, 0xf); // priority replacement for menu - gcWin::open if ((gameId == "islandbrain") && (currentScriptNr == 140) && (index == 3)) { + // piece::init //r[index] = make_reg(0, 255); //return r[index]; } -- cgit v1.2.3 From e45ffc68a32a13e81e7d12d3f43750f91e71cf91 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 13:17:45 +0000 Subject: SCI: created a workaround table for uninitialized reads, removing old commented out workarounds for pharkas and laura bow 2 svn-id: r50214 --- engines/sci/engine/kgraphics.cpp | 21 ----------------- engines/sci/engine/vm.cpp | 51 ++++++++++++++++++++++++++-------------- engines/sci/engine/vm.h | 9 +++++++ 3 files changed, 42 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 3d1bca320b..974e034ddb 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -639,7 +639,6 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// This here is needed to make Pharkas work reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { uint16 operation = argv[0].toUint16(); @@ -1041,26 +1040,6 @@ reg_t kDrawCel(EngineState *s, int argc, reg_t *argv) { bool hiresMode = (argc > 7) ? true : false; reg_t upscaledHiresHandle = (argc > 7) ? argv[7] : NULL_REG; -#if 0 - if (g_sci->getGameId() == "freddypharkas") { - // WORKAROUND - // Script 24 contains code that draws the game menu on screen. It uses a temp variable for setting priority that - // is not set. in Sierra sci this happens to be 8250h. In our sci temporary variables are initialized thus we would - // get 0 here resulting in broken menus. - if ((viewId == 995) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // game menu - priority = 15; - if ((viewId == 992) && (loopNo == 0) && (celNo == 0) && (priority == 0)) // quit game - priority = 15; - } - - if (g_sci->getGameId() == "laurabow2") { - // WORKAROUND - // see the one above - if ((viewId == 995) && (priority == 0)) - priority = 15; - } -#endif - g_sci->_gfxPaint16->kernelDrawCel(viewId, loopNo, celNo, x, y, priority, paletteNo, hiresMode, upscaledHiresHandle); return s->r_acc; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 4204131ad3..0e0b8308dc 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -183,16 +183,21 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in return true; } +static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { + { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "islandbrain", 140, "piece", "init", 3, 0 }, // currently unknown, new value is not right + { "", -1, "", "", 0, 0 } +}; + static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { if (validate_variable(r, stack_base, type, max, index, line)) { if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually - // FIXME: this should use a table which contains workarounds for gameId, scriptnumber and temp index and - // a replacement value EngineState *engine = g_sci->getEngineState(); Script *local_script = engine->_segMan->getScriptIfLoaded(engine->xs->local_segment); - int currentScriptNr = local_script->_nr; + int curScriptNr = local_script->_nr; Common::List::iterator callIterator = engine->_executionStack.begin(); ExecStack call = *callIterator; @@ -201,24 +206,34 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i callIterator++; } - const char *objName = engine->_segMan->getObjectName(call.sendp); - const char *selectorName = ""; + const char *curObjectName = engine->_segMan->getObjectName(call.sendp); + const char *curMethodName = ""; if (call.type == EXEC_STACK_TYPE_CALL) { - selectorName = g_sci->getKernel()->getSelectorName(call.selector).c_str(); + curMethodName = g_sci->getKernel()->getSelectorName(call.selector).c_str(); } - warning("uninitialized read for temp %d from method %s::%s (script %d)", index, objName, selectorName, currentScriptNr); - - Common::String gameId = g_sci->getGameId(); - if ((gameId == "laurabow2") && (currentScriptNr == 24) && (index == 5)) - return make_reg(0, 0xf); // priority replacement for menu - gcWin::open - if ((gameId == "freddypharkas") && (currentScriptNr == 24) && (index == 5)) - return make_reg(0, 0xf); // priority replacement for menu - gcWin::open - if ((gameId == "islandbrain") && (currentScriptNr == 140) && (index == 3)) { - // piece::init - //r[index] = make_reg(0, 255); - //return r[index]; + warning("uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName, curMethodName, curScriptNr); + + const char *gameId = g_sci->getGameId().c_str(); + + // Search if this is a known uninitialized read + const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; + while (workaround->gameId) { + if (strcmp(workaround->gameId, gameId) == 0) { + if (workaround->scriptNr == curScriptNr) { + if (strcmp(workaround->objectName, curObjectName) == 0) { + if (strcmp(workaround->methodName, curMethodName) == 0) { + if (workaround->index == index) { + // Workaround found + r[index] = make_reg(0, workaround->newValue); + return r[index]; + } + } + } + } + } + workaround++; } - error("uninitialized read!"); + error("unknown uninitialized read!"); } return r[index]; } else diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 88898cdbba..006bed4126 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -109,6 +109,15 @@ struct ExecStack { reg_t* getVarPointer(SegManager *segMan) const; }; +struct UninitializedReadWorkaround { + const char *gameId; + int scriptNr; + const char *objectName; + const char *methodName; + int index; + uint16 newValue; +}; + enum { VAR_GLOBAL = 0, VAR_LOCAL = 1, -- cgit v1.2.3 From 3fcb833148528e7f1e8b5e54668cb9bd99c17afb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 13:20:21 +0000 Subject: SCI: fixed workaround table from r50214 to have a valid terminator, also added another fix for pharkas svn-id: r50215 --- engines/sci/engine/vm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0e0b8308dc..6e59c89e9d 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -186,8 +186,9 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu { "islandbrain", 140, "piece", "init", 3, 0 }, // currently unknown, new value is not right - { "", -1, "", "", 0, 0 } + { NULL, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { -- cgit v1.2.3 From a268d3462b361588f60fba81e37d9bf5f048ccbc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 13:30:20 +0000 Subject: SCI: change fix for island to make it work svn-id: r50216 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 6e59c89e9d..7bf63e27a3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -187,7 +187,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { "islandbrain", 140, "piece", "init", 3, 0 }, // currently unknown, new value is not right + { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable { NULL, -1, NULL, NULL, 0, 0 } }; -- cgit v1.2.3 From 4b2661c06a77d36fe6e22fc9d55ab6a93b946675 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 13:38:24 +0000 Subject: SCI: removing warning for known uninitialized reads svn-id: r50217 --- engines/sci/engine/vm.cpp | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 7bf63e27a3..a1e354f092 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -212,8 +212,6 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (call.type == EXEC_STACK_TYPE_CALL) { curMethodName = g_sci->getKernel()->getSelectorName(call.selector).c_str(); } - warning("uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName, curMethodName, curScriptNr); - const char *gameId = g_sci->getGameId().c_str(); // Search if this is a known uninitialized read @@ -234,7 +232,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i } workaround++; } - error("unknown uninitialized read!"); + error("uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName, curMethodName, curScriptNr); } return r[index]; } else -- cgit v1.2.3 From 59c908e97d8c2c71e4823cb04059f7bc56e3c414 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 13:44:27 +0000 Subject: Changed a warning which seems like regular SCI behavior into a debugC svn-id: r50218 --- engines/sci/sound/soundcmd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 043f2b8516..5e0f45e166 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -678,7 +678,7 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { // If sound is not playing currently, set signal directly if (musicSlot->status != kSoundPlaying) { - warning("cmdFadeSound: fading requested, but sound is currently not playing"); + debugC(2, kDebugLevelSound, "cmdFadeSound: fading requested, but sound is currently not playing"); writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); return; } -- cgit v1.2.3 From 6a811a8ae69332bb181a65777f08a39d6f420abc Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 13:45:31 +0000 Subject: Added more information concerning the Dr. Brain uninitialized read svn-id: r50219 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a1e354f092..30c3fd18d4 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -187,7 +187,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable + { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 { NULL, -1, NULL, NULL, 0, 0 } }; -- cgit v1.2.3 From 00e88f15e3772eca43c7a8034bc4a31806eeb1dc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 17:02:55 +0000 Subject: SCI: arg5 is map for graph(updateBox), added comment svn-id: r50221 --- engines/sci/engine/kgraphics.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 974e034ddb..83637c61d0 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -301,6 +301,7 @@ reg_t kGraph(EngineState *s, int argc, reg_t *argv) { case K_GRAPH_UPDATE_BOX: { rect = kGraphCreateRect(x, y, x1, y1); bool hiresMode = (argc > 6) ? true : false; + // arg5 is the map (1 for visual, etc.) // argc == 7 on upscaled hires g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode); break; -- cgit v1.2.3 From b8e2e8e5ddf21a9b27bbc74e6658b637b092de9f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 17:10:26 +0000 Subject: SCI: added uninitialized read for room 720 in lsl1 svn-id: r50222 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 30c3fd18d4..d870eb96a6 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -187,6 +187,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 { NULL, -1, NULL, NULL, 0, 0 } }; -- cgit v1.2.3 From 7edbcc26f75e9953d3ed8225e351d398cf9099fc Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 24 Jun 2010 17:48:15 +0000 Subject: Cleanup uninitialized read workaround(s). svn-id: r50225 --- engines/sci/engine/vm.cpp | 60 +++++++++++++++++++++++------------------------ engines/sci/engine/vm.h | 9 ------- 2 files changed, 30 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d870eb96a6..0b4482e16f 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -183,13 +183,20 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in return true; } -static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room - { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { NULL, -1, NULL, NULL, 0, 0 } +struct UninitializedReadWorkaround { + const char *gameId; + int scriptNr; + const char *objectName; + const char *methodName; + int index; + uint16 newValue; +} static const uninitializedReadWorkarounds[] = { + { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room + { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { NULL, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -197,43 +204,36 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually - EngineState *engine = g_sci->getEngineState(); - Script *local_script = engine->_segMan->getScriptIfLoaded(engine->xs->local_segment); + EngineState *state = g_sci->getEngineState(); + Script *local_script = state->_segMan->getScriptIfLoaded(state->xs->local_segment); int curScriptNr = local_script->_nr; - Common::List::iterator callIterator = engine->_executionStack.begin(); + Common::List::iterator callIterator = state->_executionStack.begin(); ExecStack call = *callIterator; - while (callIterator != engine->_executionStack.end()) { + while (callIterator != state->_executionStack.end()) { call = *callIterator; callIterator++; } - const char *curObjectName = engine->_segMan->getObjectName(call.sendp); - const char *curMethodName = ""; - if (call.type == EXEC_STACK_TYPE_CALL) { - curMethodName = g_sci->getKernel()->getSelectorName(call.selector).c_str(); - } - const char *gameId = g_sci->getGameId().c_str(); + Common::String curObjectName = state->_segMan->getObjectName(call.sendp); + Common::String curMethodName; + Common::String gameId = g_sci->getGameId(); + + if (call.type == EXEC_STACK_TYPE_CALL) + curMethodName = g_sci->getKernel()->getSelectorName(call.selector); // Search if this is a known uninitialized read const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; while (workaround->gameId) { - if (strcmp(workaround->gameId, gameId) == 0) { - if (workaround->scriptNr == curScriptNr) { - if (strcmp(workaround->objectName, curObjectName) == 0) { - if (strcmp(workaround->methodName, curMethodName) == 0) { - if (workaround->index == index) { - // Workaround found - r[index] = make_reg(0, workaround->newValue); - return r[index]; - } - } - } - } + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName + && workaround->methodName == curMethodName && workaround->index == index) { + // Workaround found + r[index] = make_reg(0, workaround->newValue); + return r[index]; } workaround++; } - error("uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName, curMethodName, curScriptNr); + error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); } return r[index]; } else diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 006bed4126..88898cdbba 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -109,15 +109,6 @@ struct ExecStack { reg_t* getVarPointer(SegManager *segMan) const; }; -struct UninitializedReadWorkaround { - const char *gameId; - int scriptNr; - const char *objectName; - const char *methodName; - int index; - uint16 newValue; -}; - enum { VAR_GLOBAL = 0, VAR_LOCAL = 1, -- cgit v1.2.3 From 346c3a3230cf19a3fe9b0306634864f8dfa60faa Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 18:17:36 +0000 Subject: SCI: added uninitialized workaround for sq4cd svn-id: r50226 --- engines/sci/engine/vm.cpp | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0b4482e16f..4c039d72a0 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -191,12 +191,13 @@ struct UninitializedReadWorkaround { int index; uint16 newValue; } static const uninitializedReadWorkarounds[] = { - { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room - { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { NULL, -1, NULL, NULL, 0, 0 } + { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room + { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { "sq4", 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller + { NULL, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { -- cgit v1.2.3 From 42ca630f46f0991f58592c7b2195ff41bdd73b04 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 24 Jun 2010 18:48:50 +0000 Subject: Fixed the LSL3 binoculars scene again, by fixing the invalid varselector reference svn-id: r50227 --- engines/sci/engine/vm.cpp | 22 ++++++++++++++-------- 1 file changed, 14 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 4c039d72a0..b7da805251 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -101,23 +101,29 @@ static reg_t &validate_property(Object *obj, int index) { // A static dummy reg_t, which we return if obj or index turn out to be // invalid. Note that we cannot just return NULL_REG, because client code // may modify the value of the returned reg_t. - static reg_t dummyReg = NULL_REG; + //static reg_t dummyReg = NULL_REG; // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead // to all sorts of issues! Turned it into an error for now... // If this occurs, it means there's probably something wrong with the garbage // collector, so don't hide it with fake return values if (!obj) { - error("Sending to disposed object"); - return dummyReg; + error("validate_property: Sending to disposed object"); + //return dummyReg; } - // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead - // to all sorts of issues! Turned it into an error for now... + // This occurs in LSL3, binoculars scene. This gets called from kDoBresen, so fix + // the relevant invalid selector index. TODO: Why does this occur? This looks like + // a script bug. + EngineState *s = g_sci->getEngineState(); + if (index == 633 && s->currentRoomNumber() == 206 && g_sci->getGameId() == "lsl3") + index = 37; + if (index < 0 || (uint)index >= obj->getVarCount()) { - error("Invalid object property #%d (out of [0..%d]) requested!", - index, obj->getVarCount()); - return dummyReg; + error("Invalid object property #%d (out of [0..%d]) requested! Object: %04x:%04x, %s", + index, obj->getVarCount(), PRINT_REG(obj->getPos()), + s->_segMan->getObjectName(obj->getPos())); + //return dummyReg; } return obj->getVariableRef(index); -- cgit v1.2.3 From 381a862d61aa06c02f90071eeefffb28db3fcb4e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 20:01:31 +0000 Subject: SCI: partly reverting r50208, iceman has script code (fred::canBeHere) that asks for property 380. sierra also returned a zero when going out of bounds (see gregs engine object.cpp, ::getPropertyN - fixes iceman, lsl3 and probably more svn-id: r50229 --- engines/sci/engine/vm.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index b7da805251..3ee1256034 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -112,6 +112,7 @@ static reg_t &validate_property(Object *obj, int index) { //return dummyReg; } +<<<<<<< HEAD // This occurs in LSL3, binoculars scene. This gets called from kDoBresen, so fix // the relevant invalid selector index. TODO: Why does this occur? This looks like // a script bug. @@ -124,6 +125,14 @@ static reg_t &validate_property(Object *obj, int index) { index, obj->getVarCount(), PRINT_REG(obj->getPos()), s->_segMan->getObjectName(obj->getPos())); //return dummyReg; +======= + if (index < 0 || (uint)index >= obj->getVarCount()) { + // This is same way sierra does it and there are some games, that contain such scripts like + // iceman script 998 (fred::canBeHere, executed right at the start) + debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!", + index, obj->getVarCount()); + return dummyReg; +>>>>>>> 208309a... SCI: partly reverting r50208, iceman has script code (fred::canBeHere) that asks for property 380. sierra also returned a zero when going out of bounds (see gregs engine object.cpp, ::getPropertyN - fixes iceman, lsl3 and probably more } return obj->getVariableRef(index); @@ -929,6 +938,8 @@ void run_vm(EngineState *s, bool restoring) { s->xs->addr.pc.offset += readPMachineInstruction(code_buf + s->xs->addr.pc.offset, extOpcode, opparams); const byte opcode = extOpcode >> 1; + warning("%lx", opcode); + switch (opcode) { case op_bnot: // 0x00 (00) -- cgit v1.2.3 From b0fde0a1f6009432e1e5af8771176eea327af887 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 20:03:32 +0000 Subject: SCI: removing debug warning to show processes opcodes, accidentaly commited svn-id: r50230 --- engines/sci/engine/vm.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3ee1256034..47b0d727ad 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -938,8 +938,6 @@ void run_vm(EngineState *s, bool restoring) { s->xs->addr.pc.offset += readPMachineInstruction(code_buf + s->xs->addr.pc.offset, extOpcode, opparams); const byte opcode = extOpcode >> 1; - warning("%lx", opcode); - switch (opcode) { case op_bnot: // 0x00 (00) -- cgit v1.2.3 From e8d31ccc078b4144ae073881b79517bae2b0cb07 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 20:10:51 +0000 Subject: SCI: fixing the tortoisegit commit disaster :P svn-id: r50231 --- engines/sci/engine/vm.cpp | 17 +---------------- 1 file changed, 1 insertion(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 47b0d727ad..ba4cb2826e 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -101,7 +101,7 @@ static reg_t &validate_property(Object *obj, int index) { // A static dummy reg_t, which we return if obj or index turn out to be // invalid. Note that we cannot just return NULL_REG, because client code // may modify the value of the returned reg_t. - //static reg_t dummyReg = NULL_REG; + static reg_t dummyReg = NULL_REG; // FIXME/TODO: Where does this occur? Returning a dummy reg here could lead // to all sorts of issues! Turned it into an error for now... @@ -112,27 +112,12 @@ static reg_t &validate_property(Object *obj, int index) { //return dummyReg; } -<<<<<<< HEAD - // This occurs in LSL3, binoculars scene. This gets called from kDoBresen, so fix - // the relevant invalid selector index. TODO: Why does this occur? This looks like - // a script bug. - EngineState *s = g_sci->getEngineState(); - if (index == 633 && s->currentRoomNumber() == 206 && g_sci->getGameId() == "lsl3") - index = 37; - - if (index < 0 || (uint)index >= obj->getVarCount()) { - error("Invalid object property #%d (out of [0..%d]) requested! Object: %04x:%04x, %s", - index, obj->getVarCount(), PRINT_REG(obj->getPos()), - s->_segMan->getObjectName(obj->getPos())); - //return dummyReg; -======= if (index < 0 || (uint)index >= obj->getVarCount()) { // This is same way sierra does it and there are some games, that contain such scripts like // iceman script 998 (fred::canBeHere, executed right at the start) debugC(2, kDebugLevelVM, "[VM] Invalid property #%d (out of [0..%d]) requested!", index, obj->getVarCount()); return dummyReg; ->>>>>>> 208309a... SCI: partly reverting r50208, iceman has script code (fred::canBeHere) that asks for property 380. sierra also returned a zero when going out of bounds (see gregs engine object.cpp, ::getPropertyN - fixes iceman, lsl3 and probably more } return obj->getVariableRef(index); -- cgit v1.2.3 From 893429d092cd10a490d14beff74217a6080d1f5a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 20:40:57 +0000 Subject: SCI: correctly put NUL inside SegManager::strncpy() even when using n = 0xFFFFFFFFU svn-id: r50232 --- engines/sci/engine/seg_manager.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index b464438553..2178b42744 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -649,14 +649,15 @@ void SegManager::strncpy(reg_t dest, const char* src, size_t n) { ::strncpy((char *)dest_r.raw, src, n); } else { // raw -> non-raw - for (uint i = 0; i < n; i++) { + uint i; + for (i = 0; i < n; i++) { setChar(dest_r, i, src[i]); if (!src[i]) break; } // Put an ending NUL to terminate the string - if ((size_t)dest_r.maxSize > n) - setChar(dest_r, n, 0); + if ((size_t)dest_r.maxSize > i) + setChar(dest_r, i, 0); } } -- cgit v1.2.3 From 35b5da7e0fbc2ee3b3b81c2a0371ac57a00dc856 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 20:52:35 +0000 Subject: SCI: reverting r50232, didnt make sense. thx @ wjp for noticing svn-id: r50233 --- engines/sci/engine/seg_manager.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 2178b42744..b464438553 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -649,15 +649,14 @@ void SegManager::strncpy(reg_t dest, const char* src, size_t n) { ::strncpy((char *)dest_r.raw, src, n); } else { // raw -> non-raw - uint i; - for (i = 0; i < n; i++) { + for (uint i = 0; i < n; i++) { setChar(dest_r, i, src[i]); if (!src[i]) break; } // Put an ending NUL to terminate the string - if ((size_t)dest_r.maxSize > i) - setChar(dest_r, i, 0); + if ((size_t)dest_r.maxSize > n) + setChar(dest_r, n, 0); } } -- cgit v1.2.3 From a03afd18985ffef220ffbdce3ea4c66c035609da Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Thu, 24 Jun 2010 21:09:38 +0000 Subject: SCI: Make kStrAt clear segment when writing characters This is necessary since the uninitialized value detection from r50211, and is analogous to seg_manager.cpp's setChar. (Triggered in LSL3 age verification.) svn-id: r50234 --- engines/sci/engine/kstring.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp index 1927a79eea..f2f9543ad2 100644 --- a/engines/sci/engine/kstring.cpp +++ b/engines/sci/engine/kstring.cpp @@ -115,12 +115,14 @@ reg_t kStrAt(EngineState *s, int argc, reg_t *argv) { if (argc > 2) { /* Request to modify this char */ tmp.offset &= 0xff00; tmp.offset |= newvalue; + tmp.segment = 0; } } else { value = tmp.offset >> 8; if (argc > 2) { /* Request to modify this char */ tmp.offset &= 0x00ff; tmp.offset |= newvalue << 8; + tmp.segment = 0; } } } -- cgit v1.2.3 From 06a65d5c331bd009827f9fa711f7cdf5cc7905eb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 21:32:29 +0000 Subject: SCI: better initialize temp variables with FFFF:0 instead. foreign lsl3 uses kFileIO(readraw) and then kReadNumber directly. In that case we would produce many warnings because no terminating 0 is found svn-id: r50235 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index ba4cb2826e..87280d1f9b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1188,7 +1188,7 @@ void run_vm(EngineState *s, bool restoring) { // We shouldn't initialize temp variables at all // We put special segment 0xFFFF in there, so that uninitialized reads can get detected for (int i = 0; i < opparams[0]; i++) - s->xs->sp[i] = make_reg(0xffff, 0xffff); + s->xs->sp[i] = make_reg(0xffff, 0); // for (int i = 0; i < opparams[0]; i++) // s->xs->sp[i] = make_reg(0, 'ss'); -- cgit v1.2.3 From f014c9ed7ef5a193ce17ba870698a389a65a985a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 21:42:08 +0000 Subject: SCI: ignore segment 0xFFFF in segmanager getchar, when offset > 1 - so we dont write a warning, if the scripts use some uninitialized temp variable as terminator svn-id: r50236 --- engines/sci/engine/seg_manager.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index b464438553..6a03a959b3 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -612,8 +612,12 @@ static inline char getChar(const SegmentRef &ref, uint offset) { reg_t val = ref.reg[offset / 2]; + // segment 0xFFFF means that the scripts are using uninitialized temp-variable space + // we can safely ignore this, if it isn't one of the first 2 chars. + // foreign lsl3 uses kFileIO(readraw) and then immediately uses kReadNumber right at the start if (val.segment != 0) - warning("Attempt to read character from non-raw data"); + if ((offset > 1) && val.segment == 0xFFFF) + warning("Attempt to read character from non-raw data"); return (offset & 1 ? val.offset >> 8 : val.offset & 0xff); } -- cgit v1.2.3 From aa3bfe5489f45f922574265d21a9aa8059e5b208 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 24 Jun 2010 21:46:57 +0000 Subject: SCI: doing the exact opposite of r50236 code-wise now, as it was meant to be svn-id: r50237 --- engines/sci/engine/seg_manager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 6a03a959b3..e011de67d9 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -616,7 +616,7 @@ static inline char getChar(const SegmentRef &ref, uint offset) { // we can safely ignore this, if it isn't one of the first 2 chars. // foreign lsl3 uses kFileIO(readraw) and then immediately uses kReadNumber right at the start if (val.segment != 0) - if ((offset > 1) && val.segment == 0xFFFF) + if (!((val.segment == 0xFFFF) && (offset > 1))) warning("Attempt to read character from non-raw data"); return (offset & 1 ? val.offset >> 8 : val.offset & 0xff); -- cgit v1.2.3 From 1e29dc3641919ecca4589ba40df7789e6758c037 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Thu, 24 Jun 2010 22:55:44 +0000 Subject: Fixed use of uninitialized variable. svn-id: r50250 --- engines/cine/gfx.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/cine/gfx.cpp b/engines/cine/gfx.cpp index aa0330df84..1f747c5a01 100644 --- a/engines/cine/gfx.cpp +++ b/engines/cine/gfx.cpp @@ -837,14 +837,11 @@ void OSRenderer::savePalette(Common::OutSaveFile &fHandle) { */ void OSRenderer::restorePalette(Common::SeekableReadStream &fHandle, int version) { byte buf[kHighPalNumBytes]; - uint colorCount; - - if (version > 0) - colorCount = fHandle.readUint16LE(); + uint colorCount = (version > 0) ? fHandle.readUint16LE() : kHighPalNumBytes; fHandle.read(buf, kHighPalNumBytes); - if (colorCount == kHighPalNumBytes || version == 0) { + if (colorCount == kHighPalNumBytes) { // Load the active 256 color palette from file _activePal.load(buf, sizeof(buf), kHighPalFormat, kHighPalNumColors, CINE_LITTLE_ENDIAN); } else { -- cgit v1.2.3 From 550209d1e6468a575fa980144389eda64eddb730 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 09:57:37 +0000 Subject: Removed the game ID check for embedded priority in icon controls, and replaced it with a check for priority existence svn-id: r50260 --- engines/sci/engine/kgraphics.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 83637c61d0..756ac6ffcb 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -853,11 +853,8 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { loopNo = (l & 0x80) ? l - 256 : l; int c = readSelectorValue(s->_segMan, controlObject, SELECTOR(cel)); celNo = (c & 0x80) ? c - 256 : c; - // Game-specific: *ONLY* the jones EGA/VGA sierra interpreter contain code using priority selector - // ALL other games use a hardcoded -1 (madness!) - // We are detecting jones/talkie as "jones" as well, but the sierra interpreter of talkie doesnt have this - // "hack". Hopefully it wont cause regressions (the code causes regressions if used against kq5/floppy) - if (g_sci->getGameId() == "jones") + // Check if the control object specifies a priority selector (like in Jones) + if (lookupSelector(s->_segMan, controlObject, SELECTOR(priority), NULL, NULL) == kSelectorVariable) priority = readSelectorValue(s->_segMan, controlObject, SELECTOR(priority)); else priority = -1; -- cgit v1.2.3 From c6b0a5e8962297cfd808c708ff3e1022a875fd18 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 10:04:31 +0000 Subject: SCI: detect, if SCI1.1 game is merging or copying palette instead of using gameIds. Also prints method used, when using debug command "version" svn-id: r50261 --- engines/sci/console.cpp | 1 + engines/sci/graphics/palette.cpp | 121 +++++++++++++++++++-------------------- engines/sci/graphics/palette.h | 6 +- engines/sci/resource.cpp | 15 +++++ engines/sci/resource.h | 2 + engines/sci/sci.cpp | 11 +++- 6 files changed, 90 insertions(+), 66 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index cf87b34bba..b987450d3a 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -436,6 +436,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) { DebugPrintf("Move count type: %s\n", (_engine->_features->handleMoveCount()) ? "increment" : "ignore"); DebugPrintf("SetCursor type: %s\n", getSciVersionDesc(_engine->_features->detectSetCursorType())); DebugPrintf("View type: %s\n", viewTypeDesc[g_sci->getResMan()->getViewType()]); + DebugPrintf("Uses palette merging: %s\n", g_sci->_gfxPalette->isMerging() ? "yes" : "no"); DebugPrintf("Resource volume version: %s\n", g_sci->getResMan()->getVolVersionDesc()); DebugPrintf("Resource map version: %s\n", g_sci->getResMan()->getMapVersionDesc()); DebugPrintf("Contains selector vocabulary (vocab.997): %s\n", hasVocab997 ? "yes" : "no"); diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 28edfae24b..9c64c21743 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -38,7 +38,7 @@ namespace Sci { -GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) +GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging) : _resMan(resMan), _screen(screen) { int16 color; @@ -59,7 +59,6 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) _sysPalette.colors[255].b = 255; _sysPaletteChanged = false; - _alwaysForceRealMerge = false; // Pseudo-WORKAROUND // Quest for Glory 3 demo, Eco Quest 1 demo, Laura Bow 2 demo, Police Quest 1 vga and all Nick's Picks @@ -67,14 +66,7 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) // It's not using the SCI1.1 palette merging (copying over all the colors) but the real merging // If we use the copying over, we will get issues because some views have marked all colors as being used // and those will overwrite the current palette in that case - Common::String gameId = g_sci->getGameId(); - if (g_sci->isDemo()) { - if (gameId == "laurabow2" || gameId == "qfg3" || gameId == "ecoquest") - _alwaysForceRealMerge = true; - } else { - if (gameId == "pq1sci" || gameId == "cnick-sq" || gameId == "cnick-longbow" || gameId == "cnick-kq" || gameId == "cnick-laurabow" || gameId == "cnick-lsl") - _alwaysForceRealMerge = true; - } + _useMerging = useMerging; palVaryInit(); } @@ -82,6 +74,10 @@ GfxPalette::GfxPalette(ResourceManager *resMan, GfxScreen *screen) GfxPalette::~GfxPalette() { } +bool GfxPalette::isMerging() { + return _useMerging; +} + // meant to get called only once during init of engine void GfxPalette::setDefault() { if (_resMan->getViewType() == kViewEga) @@ -231,7 +227,14 @@ void GfxPalette::set(Palette *newPalette, bool force, bool forceRealMerge) { uint32 systime = _sysPalette.timestamp; if (force || newPalette->timestamp != systime) { - _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); + // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes + // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo) + if ((forceRealMerge) || (_useMerging)) + _sysPaletteChanged |= merge(newPalette, force, forceRealMerge); + else + _sysPaletteChanged |= insert(newPalette, &_sysPalette); + + // Adjust timestamp on newPalette, so it wont get merged/inserted w/o need newPalette->timestamp = _sysPalette.timestamp; bool updatePalette = _sysPaletteChanged && _screen->_picNotValid == 0; @@ -265,6 +268,7 @@ bool GfxPalette::insert(Palette *newPalette, Palette *destPalette) { newPalette->mapping[i] = i; } } + // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls return paletteChanged; } @@ -273,59 +277,50 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { int i,j; bool paletteChanged = false; - if ((!forceRealMerge) && (!_alwaysForceRealMerge) && (getSciVersion() >= SCI_VERSION_1_1)) { - // SCI1.1+ doesnt do real merging anymore, but simply copying over the used colors from other palettes - // There are some games with inbetween SCI1.1 interpreters, use real merging for them (e.g. laura bow 2 demo) - - // We don't update the timestamp for SCI1.1, it's only updated on kDrawPic calls - return insert(newPalette, &_sysPalette); - - } else { - // colors 0 (black) and 255 (white) are not affected by merging - for (i = 1 ; i < 255; i++) { - if (!newPalette->colors[i].used)// color is not used - so skip it - continue; - // forced palette merging or dest color is not used yet - if (force || (!_sysPalette.colors[i].used)) { - _sysPalette.colors[i].used = newPalette->colors[i].used; - if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { - _sysPalette.colors[i].r = newPalette->colors[i].r; - _sysPalette.colors[i].g = newPalette->colors[i].g; - _sysPalette.colors[i].b = newPalette->colors[i].b; - paletteChanged = true; - } - newPalette->mapping[i] = i; - continue; - } - // is the same color already at the same position? -> match it directly w/o lookup - // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would - // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) - if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) { - newPalette->mapping[i] = i; - continue; - } - // check if exact color could be matched - res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); - if (res & 0x8000) { // exact match was found - newPalette->mapping[i] = res & 0xFF; - continue; + // colors 0 (black) and 255 (white) are not affected by merging + for (i = 1 ; i < 255; i++) { + if (!newPalette->colors[i].used)// color is not used - so skip it + continue; + // forced palette merging or dest color is not used yet + if (force || (!_sysPalette.colors[i].used)) { + _sysPalette.colors[i].used = newPalette->colors[i].used; + if ((newPalette->colors[i].r != _sysPalette.colors[i].r) || (newPalette->colors[i].g != _sysPalette.colors[i].g) || (newPalette->colors[i].b != _sysPalette.colors[i].b)) { + _sysPalette.colors[i].r = newPalette->colors[i].r; + _sysPalette.colors[i].g = newPalette->colors[i].g; + _sysPalette.colors[i].b = newPalette->colors[i].b; + paletteChanged = true; } - // no exact match - see if there is an unused color - for (j = 1; j < 256; j++) - if (!_sysPalette.colors[j].used) { - _sysPalette.colors[j].used = newPalette->colors[i].used; - _sysPalette.colors[j].r = newPalette->colors[i].r; - _sysPalette.colors[j].g = newPalette->colors[i].g; - _sysPalette.colors[j].b = newPalette->colors[i].b; - newPalette->mapping[i] = j; - paletteChanged = true; - break; - } - // if still no luck - set an approximate color - if (j == 256) { - newPalette->mapping[i] = res & 0xFF; - _sysPalette.colors[res & 0xFF].used |= 0x10; + newPalette->mapping[i] = i; + continue; + } + // is the same color already at the same position? -> match it directly w/o lookup + // this fixes games like lsl1demo/sq5 where the same rgb color exists multiple times and where we would + // otherwise match the wrong one (which would result into the pixels affected (or not) by palette changes) + if ((_sysPalette.colors[i].r == newPalette->colors[i].r) && (_sysPalette.colors[i].g == newPalette->colors[i].g) && (_sysPalette.colors[i].b == newPalette->colors[i].b)) { + newPalette->mapping[i] = i; + continue; + } + // check if exact color could be matched + res = matchColor(newPalette->colors[i].r, newPalette->colors[i].g, newPalette->colors[i].b); + if (res & 0x8000) { // exact match was found + newPalette->mapping[i] = res & 0xFF; + continue; + } + // no exact match - see if there is an unused color + for (j = 1; j < 256; j++) + if (!_sysPalette.colors[j].used) { + _sysPalette.colors[j].used = newPalette->colors[i].used; + _sysPalette.colors[j].r = newPalette->colors[i].r; + _sysPalette.colors[j].g = newPalette->colors[i].g; + _sysPalette.colors[j].b = newPalette->colors[i].b; + newPalette->mapping[i] = j; + paletteChanged = true; + break; } + // if still no luck - set an approximate color + if (j == 256) { + newPalette->mapping[i] = res & 0xFF; + _sysPalette.colors[res & 0xFF].used |= 0x10; } } @@ -337,7 +332,7 @@ bool GfxPalette::merge(Palette *newPalette, bool force, bool forceRealMerge) { // This is called for SCI1.1, when kDrawPic got done. We update sysPalette timestamp this way for SCI1.1 and also load // target-palette, if palvary is active void GfxPalette::drewPicture(GuiResourceId pictureId) { - if (!_alwaysForceRealMerge) // Don't do this on inbetween SCI1.1 games + if (!_useMerging) // Don't do this on inbetween SCI1.1 games _sysPalette.timestamp++; if (_palVaryResourceId != -1) { diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index e640d9b39d..1fa8c16d26 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -36,9 +36,11 @@ class Screen; */ class GfxPalette { public: - GfxPalette(ResourceManager *resMan, GfxScreen *screen); + GfxPalette(ResourceManager *resMan, GfxScreen *screen, bool useMerging); ~GfxPalette(); + bool isMerging(); + void setDefault(); void createFromData(byte *data, int bytesLeft, Palette *paletteOut); bool setAmiga(); @@ -88,7 +90,7 @@ private: ResourceManager *_resMan; bool _sysPaletteChanged; - bool _alwaysForceRealMerge; + bool _useMerging; Common::Array _schedules; diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp index 718c675db1..2958ca1e3b 100644 --- a/engines/sci/resource.cpp +++ b/engines/sci/resource.cpp @@ -1949,6 +1949,21 @@ bool ResourceManager::detectFontExtended() { return false; } +// detects, if SCI1.1 game uses palette merging or copying - this is supposed to only get used on SCI1.1 games +bool ResourceManager::detectForPaletteMergingForSci11() { + // Load palette 999 (default palette) + Resource *res = findResource(ResourceId(kResourceTypePalette, 999), false); + + if ((res) && (res->size > 30)) { + byte *data = res->data; + // Old palette format used in palette resource? -> it's merging + if ((data[0] == 0 && data[1] == 1) || (data[0] == 0 && data[1] == 0 && READ_LE_UINT16(data + 29) == 0)) + return true; + return false; + } + return false; +} + // Functions below are based on PD code by Brian Provinciano (SCI Studio) bool ResourceManager::hasOldScriptHeader() { Resource *res = findResource(ResourceId(kResourceTypeScript, 0), 0); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 591273b252..00197876d8 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -328,6 +328,8 @@ public: bool detectHires(); // Detects, if standard font of current game includes extended characters (>0x80) bool detectFontExtended(); + // Detects, if SCI1.1 game uses palette merging + bool detectForPaletteMergingForSci11(); /** * Finds the internal Sierra ID of the current game from script 0. diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index b8c541fc03..f2ea0e67af 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -224,7 +224,16 @@ Common::Error SciEngine::run() { if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) _gfxMacIconBar = new GfxMacIconBar(); - _gfxPalette = new GfxPalette(_resMan, _gfxScreen); + bool paletteMerging = true; + if (getSciVersion() >= SCI_VERSION_1_1) { + // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying + if (getSciVersion() == SCI_VERSION_1_1) + paletteMerging = _resMan->detectForPaletteMergingForSci11(); + else + paletteMerging = false; + } + + _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging); _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen); -- cgit v1.2.3 From 279da6ac48c1d68d724cbb46e560a7439be8a4d8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 12:15:36 +0000 Subject: Added workarounds for two issues which appear when throwing the water at Orat in SQ1, room 28 svn-id: r50262 --- engines/sci/engine/vm.cpp | 13 +++++++++++++ 1 file changed, 13 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 87280d1f9b..5f59e5c547 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -931,6 +931,14 @@ void run_vm(EngineState *s, bool restoring) { case op_add: // 0x01 (01) r_temp = POP32(); + + // Happens in SQ1, room 28, when throwing the water at Orat + if (s->r_acc.segment == 0xFFFF) { + // WORKAROUND: init uninitialized variable to 0 + warning("op_add: attempt to write to uninitialized variable"); + s->r_acc = NULL_REG; + } + if (r_temp.segment || s->r_acc.segment) { reg_t r_ptr = NULL_REG; int offset; @@ -1051,6 +1059,11 @@ void run_vm(EngineState *s, bool restoring) { if (r_temp.segment != s->r_acc.segment) warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc)); s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset); + } else if (r_temp.segment && !s->r_acc.segment) { + // Happens in SQ1, room 28, when throwing the water at Orat + // WORKAROUND: return false + warning("[VM] op_gt_: comparison between a pointer and a number"); + s->r_acc = NULL_REG; } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/); break; -- cgit v1.2.3 From 494a7fa8abc41915b70f37047149e23fa1980e25 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 12:43:43 +0000 Subject: Extended validate_read_var to check for parameters too, and fixed the uninitialized variable in SQ1 there svn-id: r50263 --- engines/sci/engine/vm.cpp | 14 ++++---------- 1 file changed, 4 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 5f59e5c547..d9758650ea 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -197,12 +197,13 @@ struct UninitializedReadWorkaround { { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 { "sq4", 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller + { "sq1sci", 992, "CT", "init", 3, 0 }, // is used as cel number { NULL, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { if (validate_variable(r, stack_base, type, max, index, line)) { - if (type == VAR_TEMP && r[index].segment == 0xffff) { + if ((type == VAR_TEMP || type == VAR_PARAM) && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually EngineState *state = g_sci->getEngineState(); @@ -234,7 +235,8 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i } workaround++; } - error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); + Common::String varType = (type == VAR_TEMP) ? "temp" : "param"; + error("Uninitialized read for %s %d from method %s::%s (script %d)", varType.c_str(), index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); } return r[index]; } else @@ -931,14 +933,6 @@ void run_vm(EngineState *s, bool restoring) { case op_add: // 0x01 (01) r_temp = POP32(); - - // Happens in SQ1, room 28, when throwing the water at Orat - if (s->r_acc.segment == 0xFFFF) { - // WORKAROUND: init uninitialized variable to 0 - warning("op_add: attempt to write to uninitialized variable"); - s->r_acc = NULL_REG; - } - if (r_temp.segment || s->r_acc.segment) { reg_t r_ptr = NULL_REG; int offset; -- cgit v1.2.3 From df37aff35756e03e02b47ce3483b06679a662ce6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 14:50:10 +0000 Subject: Added the SCI2.1 kText kernel function (subop 0, kTextSize for now) svn-id: r50265 --- engines/sci/engine/kernel.cpp | 7 +++---- engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel32.cpp | 13 +++++++++++++ 3 files changed, 17 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c9b547e6f8..41a2d2dd2b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -357,6 +357,8 @@ static SciKernelFunction s_kernelFuncMap[] = { { "TextColors", kTextColors, ".*" }, { "TextFonts", kTextFonts, ".*" }, { "Portrait", kPortrait, ".*" }, + { "PalVary", kPalVary, "ii*" }, + { "AssertPalette", kAssertPalette, "i" }, { "Empty", kEmpty, ".*" }, #ifdef ENABLE_SCI32 @@ -389,13 +391,10 @@ static SciKernelFunction s_kernelFuncMap[] = { { "PlayVMD", kPlayVMD, ".*" }, { "IsOnMe", kIsOnMe, "iio.*" }, { "MulDiv", kMulDiv, "iii" }, + { "Text", kText, ".*" }, #endif - // its a stub, but its needed for Pharkas to work - { "PalVary", kPalVary, "ii*" }, - { "AssertPalette", kAssertPalette, "i" }, - #if 0 // Stub functions /*09*/ { "Show", kShow, "i" }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 802a2d5f0b..4333f6ef77 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -439,6 +439,7 @@ reg_t kOnMe(EngineState *s, int argc, reg_t *argv); reg_t kInPolygon(EngineState *s, int argc, reg_t *argv); // SCI2.1 Kernel Functions +reg_t kText(EngineState *s, int argc, reg_t *argv); reg_t kSave(EngineState *s, int argc, reg_t *argv); reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index b317719252..93191947ba 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -511,6 +511,19 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } +reg_t kText(EngineState *s, int argc, reg_t *argv) { + switch (argv[0].toUint16()) { + case 0: + return kTextSize(s, argc - 1, argv + 1); + break; + default: + warning("kText(%d)", argv[0].toUint16()); + break; + } + + return s->r_acc; +} + reg_t kString(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: { // New -- cgit v1.2.3 From 2b43c3a668485a0a382d7c627b2fb281865e0cd4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 14:50:27 +0000 Subject: SCI: changes to the op GT workaround svn-id: r50266 --- engines/sci/engine/vm.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d9758650ea..a5cacf40b3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1054,10 +1054,11 @@ void run_vm(EngineState *s, bool restoring) { warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc)); s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset); } else if (r_temp.segment && !s->r_acc.segment) { + if (s->r_acc.offset >= 1000) + error("[VM] op_gt: comparsion between a pointer and number"); + // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion // Happens in SQ1, room 28, when throwing the water at Orat - // WORKAROUND: return false - warning("[VM] op_gt_: comparison between a pointer and a number"); - s->r_acc = NULL_REG; + s->r_acc = SIGNAL_REG; } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/); break; @@ -1110,7 +1111,7 @@ void run_vm(EngineState *s, bool restoring) { // It works because in those games, the maximum resource number is 999, // so any parameter value above that threshold must be a pointer. if (r_temp.segment && (s->r_acc == make_reg(0, 1000))) - s->r_acc = make_reg(0, 1); + s->r_acc = SIGNAL_REG; else if (r_temp.segment && s->r_acc.segment) s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset); else -- cgit v1.2.3 From 159958fbe233c1b58b4df4cd3fcacffd9d40f7c2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 15:06:00 +0000 Subject: Some more info on kText(), removed dead code svn-id: r50267 --- engines/sci/engine/kernel32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 93191947ba..1773046308 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -515,8 +515,8 @@ reg_t kText(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case 0: return kTextSize(s, argc - 1, argv + 1); - break; default: + // TODO: Other subops here too, perhaps kTextColors and kTextFonts warning("kText(%d)", argv[0].toUint16()); break; } -- cgit v1.2.3 From e55686590e2ca6a6e7eeca7a73def9dd3a0722c9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 15:28:24 +0000 Subject: Removed the checking of parameters again (it's wrong, as it happens after, instead of before) and restored the workaround for SQ1 in op_add again svn-id: r50268 --- engines/sci/engine/vm.cpp | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a5cacf40b3..fa97dcf718 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -197,13 +197,12 @@ struct UninitializedReadWorkaround { { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 { "sq4", 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller - { "sq1sci", 992, "CT", "init", 3, 0 }, // is used as cel number { NULL, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { if (validate_variable(r, stack_base, type, max, index, line)) { - if ((type == VAR_TEMP || type == VAR_PARAM) && r[index].segment == 0xffff) { + if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually EngineState *state = g_sci->getEngineState(); @@ -235,8 +234,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i } workaround++; } - Common::String varType = (type == VAR_TEMP) ? "temp" : "param"; - error("Uninitialized read for %s %d from method %s::%s (script %d)", varType.c_str(), index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); + error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); } return r[index]; } else @@ -933,6 +931,14 @@ void run_vm(EngineState *s, bool restoring) { case op_add: // 0x01 (01) r_temp = POP32(); + + // Happens in SQ1, room 28, when throwing the water at Orat + if (s->r_acc.segment == 0xFFFF) { + // WORKAROUND: init uninitialized variable to 0 + warning("op_add: attempt to write to uninitialized variable"); + s->r_acc = NULL_REG; + } + if (r_temp.segment || s->r_acc.segment) { reg_t r_ptr = NULL_REG; int offset; -- cgit v1.2.3 From 8ff6a709fbe72bbd2d1ac53623558a2ed0e6c2a6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 16:04:37 +0000 Subject: SCI: when writing to a temp, check for segment 0xFFFF and remove it. This fixes a false-positive uninitialized read error in room 44 sq1 svn-id: r50269 --- engines/sci/engine/vm.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fa97dcf718..3295406745 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -273,6 +273,13 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i } } + // If we are writing an uninitialized value into a temp, we remove the uninitialized segment + // this happens at least in sq1/room 44 (slot-machine), because a send is missing parameters, then + // those parameters are taken from uninitialized stack and afterwards they are copied back into temps + // if we don't remove the segment, we would get false-positive uninitialized reads later + if (type == VAR_TEMP && value.segment == 0xffff) + value.segment = 0; + r[index] = value; } } -- cgit v1.2.3 From 7d4d58bab41249e9a29c42c0f2715ff5e1c1d6cc Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 25 Jun 2010 16:08:34 +0000 Subject: SCUMM: Set some more detection file sizes svn-id: r50270 --- engines/scumm/scumm-md5.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 8570f0c6a3..76045f42a2 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Tue Jun 22 16:01:03 2010 + This file was generated by the md5table tool on Tue Jun 22 19:42:27 2010 DO NOT EDIT MANUALLY! */ @@ -40,7 +40,7 @@ static const MD5Table md5table[] = { { "0a295b80f9a9edf818e8e161a0e83830", "freddi2", "HE 80", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, { "0a41311d462b6639fc45297b9044bf16", "monkey", "No AdLib", "EGA", -1, Common::ES_ESP, Common::kPlatformAtariST }, { "0a6d7b81b850ed4a77811c60c9b5c555", "PuttTime", "HE 99", "Mini Game", -1, Common::EN_USA, Common::kPlatformWindows }, - { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", -1, Common::EN_ANY, Common::kPlatformPCEngine }, + { "0aa050f4ad79402fbe9c4f78fb8ac494", "loom", "PC-Engine", "", 6532, Common::EN_ANY, Common::kPlatformPCEngine }, { "0ab19be9e2a3f6938226638b2a3744fe", "PuttTime", "HE 100", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "0ac41e2e3d2174e5a042a6b565328dba", "puttrace", "HE 98", "Demo", 13110, Common::EN_USA, Common::kPlatformUnknown }, { "0b3222aaa7efcf283eb621e0cefd26cc", "puttputt", "HE 60", "", -1, Common::RU_RUS, Common::kPlatformPC }, @@ -75,7 +75,7 @@ static const MD5Table md5table[] = { { "15e03ffbfeddb9c2aebc13dcb2a4a8f4", "monkey", "VGA", "VGA", 8357, Common::EN_ANY, Common::kPlatformPC }, { "15f588e887e857e8c56fe6ade4956168", "atlantis", "Floppy", "Floppy", -1, Common::ES_ESP, Common::kPlatformAmiga }, { "16542a7342a918bfe4ba512007d36c47", "FreddisFunShop", "HE 99L", "", -1, Common::EN_USA, Common::kPlatformUnknown }, - { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "166553538ff320c69edafeee29525419", "samnmax", "", "CD", 199195304, Common::EN_ANY, Common::kPlatformMacintosh }, { "16effd200aa6b8abe9c569c3e578814d", "freddi4", "HE 99", "Demo", -1, Common::NL_NLD, Common::kPlatformWindows }, { "179879b6e35c1ead0d93aab26db0951b", "fbear", "HE 70", "", 13381, Common::EN_ANY, Common::kPlatformWindows }, { "17b5d5e6af4ae89d62631641d66d5a05", "indy3", "VGA", "VGA", -1, Common::IT_ITA, Common::kPlatformPC }, @@ -413,7 +413,7 @@ static const MD5Table md5table[] = { { "9d7b67be003fea60be4dcbd193611936", "ft", "Demo", "Demo", 11164, Common::EN_ANY, Common::kPlatformMacintosh }, { "9dc02577bf50d4cfaf3de3fbac06fbe2", "puttmoon", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, { "9e5e0fb43bd22f4628719b7501adb717", "monkey", "No AdLib", "EGA", -1, Common::FR_FRA, Common::kPlatformAtariST }, - { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "9fd66fb3b04703bd50da4356e4202558", "spyfox2", "", "", 51295, Common::EN_ANY, Common::kPlatformMacintosh }, { "a00554c31d623fdb9fcb0f924b89b42b", "loom", "EGA", "EGA Demo", -1, Common::EN_ANY, Common::kPlatformPC }, { "a01fab4a64d47b96e2e58e6b0f825cc7", "monkey", "VGA", "VGA", 8347, Common::FR_FRA, Common::kPlatformPC }, { "a095616d2d23ccf43b8e257711202cba", "football2002", "", "", -1, Common::EN_ANY, Common::kPlatformUnknown }, @@ -554,7 +554,7 @@ static const MD5Table md5table[] = { { "dbf4d59d70b826733f379f998354d350", "BluesBirthday", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, { "dcf0119a90451a7d6e0f1920931ba130", "freddi4", "HE 99", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows }, { "dd30a53035393baa5a5e222e716559af", "maniac", "V2", "V2", -1, Common::FR_FRA, Common::kPlatformAtariST }, - { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "de4efb910210736813c9a1185384bace", "puttzoo", "HE 72", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows }, { "debe337f73d660e951ece7c1f1c81add", "zak", "V2", "V2", -1, Common::EN_ANY, Common::kPlatformPC }, { "defb8cb9ec4b0f91acfb6b61c6129ad9", "PuttTime", "HE 99", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "df03ee021aa9b81d90cab9c26da07614", "indy3", "EGA", "EGA", -1, Common::IT_ITA, Common::kPlatformAmiga }, -- cgit v1.2.3 From 1e9977a725ca24a2d31cac56b0587bae09ab5b3a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 25 Jun 2010 16:11:00 +0000 Subject: SCI: Restrict some 'error' exceptions to the places they occur; cleanup svn-id: r50271 --- engines/sci/engine/segment.cpp | 21 +++++++++++++++------ engines/sci/engine/static_selectors.cpp | 6 +++--- 2 files changed, 18 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 28cc03d175..6a564fcc57 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -464,10 +464,16 @@ SegmentRef LocalVariables::dereference(reg_t pointer) { if (ret.maxSize > 0) { ret.reg = &_locals[pointer.offset / 2]; } else { - // Happens in two places during the intro of LB2CD, both from kMemory(peek): - // - room 160: Heap 160 has 83 local variables (0-82), and the game asks for variables at indices 83 - 90 too - // - room 220: Heap 220 has 114 local variables (0-113), and the game asks for variables at indices 114-120 too - warning("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660) + && g_sci->getGameId() == "laurabow2") { + // Happens in two places during the intro of LB2CD, both from kMemory(peek): + // - room 160: Heap 160 has 83 local variables (0-82), and the game + // asks for variables at indices 83 - 90 too. + // - room 220: Heap 220 has 114 local variables (0-113), and the + // game asks for variables at indices 114-120 too. + } else { + error("LocalVariables::dereference: Offset at end or out of bounds %04x:%04x", PRINT_REG(pointer)); + } ret.reg = 0; } return ret; @@ -514,8 +520,11 @@ SegmentRef SystemStrings::dereference(reg_t pointer) { if (isValidOffset(pointer.offset)) ret.raw = (byte *)(_strings[pointer.offset]._value); else { - // This occurs in KQ5CD when interacting with certain objects - warning("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); + if (g_sci->getGameId() == "kq5") { + // This occurs in KQ5CD when interacting with certain objects + } else { + error("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); + } } return ret; diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index fcef04f6ad..12d61ed24a 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -150,10 +150,10 @@ Common::StringArray Kernel::checkStaticSelectorNames() { } for (const SelectorRemap *selectorRemap = sciSelectorRemap; selectorRemap->slot; ++selectorRemap) { - uint32 slot = selectorRemap->slot; - if (selectorRemap->slot >= names.size()) - names.resize(selectorRemap->slot + 1); if (getSciVersion() >= selectorRemap->minVersion && getSciVersion() <= selectorRemap->maxVersion) { + const uint32 slot = selectorRemap->slot; + if (slot >= names.size()) + names.resize(slot + 1); names[slot] = selectorRemap->name; } } -- cgit v1.2.3 From 23d384e6b88f4023b9150401a70a4efdf9bae018 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 25 Jun 2010 16:12:38 +0000 Subject: SCI: Remove SciEngine::getFlags() svn-id: r50272 --- engines/sci/sci.cpp | 6 +----- engines/sci/sci.h | 1 - 2 files changed, 1 insertion(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index f2ea0e67af..527c2d24ba 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -511,12 +511,8 @@ Common::Platform SciEngine::getPlatform() const { return _gameDescription->platform; } -uint32 SciEngine::getFlags() const { - return _gameDescription->flags; -} - bool SciEngine::isDemo() const { - return getFlags() & ADGF_DEMO; + return _gameDescription->flags & ADGF_DEMO; } Common::String SciEngine::getSavegameName(int nr) const { diff --git a/engines/sci/sci.h b/engines/sci/sci.h index ee51147a4e..68a62c5fcc 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -155,7 +155,6 @@ public: int getResourceVersion() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; - uint32 getFlags() const; bool isDemo() const; inline ResourceManager *getResMan() const { return _resMan; } -- cgit v1.2.3 From 6ee82a20276d213a06d43ff731d197f5a92a09d7 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Fri, 25 Jun 2010 16:16:29 +0000 Subject: SCI: Introduce SciGameId enum svn-id: r50273 --- engines/sci/console.cpp | 2 +- engines/sci/detection.cpp | 92 ++++++++++++++++++++++++++++++--- engines/sci/engine/kernel.cpp | 4 +- engines/sci/engine/kgraphics.cpp | 2 +- engines/sci/engine/kmisc.cpp | 4 +- engines/sci/engine/kpathing.cpp | 4 +- engines/sci/engine/segment.cpp | 4 +- engines/sci/engine/static_selectors.cpp | 2 +- engines/sci/engine/vm.cpp | 28 +++++----- engines/sci/graphics/paint16.cpp | 2 +- engines/sci/graphics/picture.cpp | 4 +- engines/sci/graphics/ports.cpp | 32 +++++++++--- engines/sci/graphics/screen.cpp | 4 +- engines/sci/resource.h | 2 +- engines/sci/resource_audio.cpp | 32 ++++++++---- engines/sci/sci.cpp | 18 ++++--- engines/sci/sci.h | 76 +++++++++++++++++++++++++-- 17 files changed, 247 insertions(+), 65 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b987450d3a..e8cbb6cf0e 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -425,7 +425,7 @@ bool Console::cmdGetVersion(int argc, const char **argv) { bool hasVocab997 = g_sci->getResMan()->testResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_SELECTORS)) ? true : false; - DebugPrintf("Game ID: %s\n", _engine->getGameId().c_str()); + DebugPrintf("Game ID: %s\n", _engine->getGameIdStr()); DebugPrintf("Emulated interpreter version: %s\n", getSciVersionDesc(getSciVersion())); DebugPrintf("\n"); DebugPrintf("Detected features:\n"); diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 3b153d3dd1..0932cb3fdc 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -40,7 +40,7 @@ namespace Sci { // Titles of the games -static const PlainGameDescriptor SciGameTitles[] = { +static const PlainGameDescriptor s_sciGameTitles[] = { {"sci", "Sierra SCI Game"}, {"sci-fanmade", "Fanmade SCI Game"}, // === SCI0 games ========================================================= @@ -119,6 +119,80 @@ static const PlainGameDescriptor SciGameTitles[] = { {0, 0} }; +struct GameIdStrToEnum { + const char *gameidStr; + SciGameId gameidEnum; +}; + +static const GameIdStrToEnum s_gameIdStrToEnum[] = { + { "astrochicken", GID_ASTROCHICKEN }, + { "camelot", GID_CAMELOT }, + { "castlebrain", GID_CASTLEBRAIN }, + { "christmas1988", GID_CHRISTMAS1988 }, + { "christmas1990", GID_CHRISTMAS1990 }, + { "christmas1992", GID_CHRISTMAS1992 }, + { "cnick-kq", GID_CNICK_KQ }, + { "cnick-laurabow", GID_CNICK_LAURABOW }, + { "cnick-longbow", GID_CNICK_LONGBOW }, + { "cnick-lsl", GID_CNICK_LSL }, + { "cnick-sq", GID_CNICK_SQ }, + { "ecoquest", GID_ECOQUEST }, + { "ecoquest2", GID_ECOQUEST2 }, + { "fairytales", GID_FAIRYTALES }, + { "freddypharkas", GID_FREDDYPHARKAS }, + { "funseeker", GID_FUNSEEKER }, + { "gk1", GID_GK1 }, + { "gk2", GID_GK2 }, + { "hoyle1", GID_HOYLE1 }, + { "hoyle2", GID_HOYLE2 }, + { "hoyle3", GID_HOYLE3 }, + { "hoyle4", GID_HOYLE4 }, + { "iceman", GID_ICEMAN }, + { "islandbrain", GID_ISLANDBRAIN }, + { "jones", GID_JONES }, + { "kq1sci", GID_KQ1 }, + { "kq4sci", GID_KQ4 }, + { "kq5", GID_KQ5 }, + { "kq6", GID_KQ6 }, + { "kq7", GID_KQ7 }, + { "laurabow", GID_LAURABOW }, + { "laurabow2", GID_LAURABOW2 }, + { "lighthouse", GID_LIGHTHOUSE }, + { "longbow", GID_LONGBOW }, + { "lsl1sci", GID_LSL1 }, + { "lsl2", GID_LSL2 }, + { "lsl3", GID_LSL3 }, + { "lsl5", GID_LSL5 }, + { "lsl6", GID_LSL6 }, + { "lsl7", GID_LSL7 }, + { "mothergoose", GID_MOTHERGOOSE }, + { "msastrochicken", GID_MSASTROCHICKEN }, + { "pepper", GID_PEPPER }, + { "phantasmagoria", GID_PHANTASMAGORIA }, + { "phantasmagoria2", GID_PHANTASMAGORIA2 }, + { "pq1sci", GID_PQ1 }, + { "pq2", GID_PQ2 }, + { "pq3", GID_PQ3 }, + { "pq4", GID_PQ4 }, + { "pqswat", GID_PQSWAT }, + { "qfg1", GID_QFG1 }, + { "qfg2", GID_QFG2 }, + { "qfg3", GID_QFG3 }, + { "qfg4", GID_QFG4 }, + { "rama", GID_RAMA }, + { "sci-fanmade", GID_FANMADE }, // FIXME: Do we really need/want this? + { "shivers", GID_SHIVERS }, + { "shivers2", GID_SHIVERS2 }, + { "slater", GID_SLATER }, + { "sq1sci", GID_SQ1 }, + { "sq3", GID_SQ3 }, + { "sq4", GID_SQ4 }, + { "sq5", GID_SQ5 }, + { "sq6", GID_SQ6 }, + { "torin", GID_TORIN }, + { NULL, (SciGameId)-1 } +}; + struct OldNewIdTableEntry { const char *oldId; const char *newId; @@ -300,7 +374,7 @@ static const ADParams detectionParams = { // Number of bytes to compute MD5 sum for 5000, // List of all engine targets - SciGameTitles, + s_sciGameTitles, // Structure for autoupgrading obsolete targets 0, // Name of single gameid (optional) @@ -523,12 +597,16 @@ const ADGameDescription *SciMetaEngine::fallbackDetect(const Common::FSList &fsl return (const ADGameDescription *)&s_fallbackDesc; } -bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const { - const ADGameDescription *desc = (const ADGameDescription *)gd; - - *engine = new SciEngine(syst, desc); +bool SciMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { + const GameIdStrToEnum *g = s_gameIdStrToEnum; + for (; g->gameidStr; ++g) { + if (0 == strcmp(desc->gameid, g->gameidStr)) { + *engine = new SciEngine(syst, desc, g->gameidEnum); + return true; + } + } - return true; + return false; } bool SciMetaEngine::hasFeature(MetaEngineFeature f) const { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 41a2d2dd2b..d6dcf650bc 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -745,7 +745,7 @@ void Kernel::setDefaultKernelNames() { // In SCI1.1, kSetSynonyms is an empty function _kernelNames[0x26] = "Empty"; - if (g_sci->getGameId() == "kq6") { + if (g_sci->getGameId() == GID_KQ6) { // In the Windows version of KQ6 CD, the empty kSetSynonyms // function has been replaced with kPortrait. In KQ6 Mac, // kPlayBack has been replaced by kShowMovie. @@ -753,7 +753,7 @@ void Kernel::setDefaultKernelNames() { _kernelNames[0x26] = "Portrait"; else if (g_sci->getPlatform() == Common::kPlatformMacintosh) _kernelNames[0x84] = "ShowMovie"; - } else if (g_sci->getGameId() == "qfg4" && g_sci->isDemo()) { + } else if (g_sci->getGameId() == GID_QFG4 && g_sci->isDemo()) { _kernelNames[0x7b] = "RemapColors"; // QFG4 Demo has this SCI2 function instead of StrSplit } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 756ac6ffcb..b1cd1451d1 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -541,7 +541,7 @@ reg_t kBaseSetter(EngineState *s, int argc, reg_t *argv) { // WORKAROUND for a problem in LSL1VGA. This allows the casino door to be opened, // till the actual problem is found - if (s->currentRoomNumber() == 300 && g_sci->getGameId() == "lsl1sci") { + if (s->currentRoomNumber() == 300 && g_sci->getGameId() == GID_LSL1) { int top = readSelectorValue(s->_segMan, object, SELECTOR(brTop)); writeSelectorValue(s->_segMan, object, SELECTOR(brTop), top + 2); } diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 4dd7df1b52..f742734ad7 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -60,9 +60,9 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { // throttling resulting in having to do 1000 pushups or something. Another // way of handling this would be delaying incrementing of "machineSpeed" // selector. - if (g_sci->getGameId() == "lsl3" && s->currentRoomNumber() == 290) + if (g_sci->getGameId() == GID_LSL3 && s->currentRoomNumber() == 290) s->_throttleTrigger = true; - else if (g_sci->getGameId() == "iceman" && s->currentRoomNumber() == 27) { + else if (g_sci->getGameId() == GID_ICEMAN && s->currentRoomNumber() == 27) { s->_throttleTrigger = true; neededSleep = 60; } diff --git a/engines/sci/engine/kpathing.cpp b/engines/sci/engine/kpathing.cpp index ba6fb9bb6e..fdaae3e121 100644 --- a/engines/sci/engine/kpathing.cpp +++ b/engines/sci/engine/kpathing.cpp @@ -1090,7 +1090,7 @@ static Polygon *convert_polygon(EngineState *s, reg_t polygon) { // WORKAROUND: broken polygon in lsl1sci, room 350, after opening elevator // Polygon has 17 points but size is set to 19 - if ((size == 19) && g_sci->getGameId() == "lsl1sci") { + if ((size == 19) && g_sci->getGameId() == GID_LSL1) { if ((s->currentRoomNumber() == 350) && (read_point(segMan, points, 18) == Common::Point(108, 137))) { debug(1, "Applying fix for broken polygon in lsl1sci, room 350"); @@ -1212,7 +1212,7 @@ static PathfindingState *convert_polygon_set(EngineState *s, reg_t poly_list, Co // WORKAROUND LSL5 room 660. Priority glitch due to us choosing a different path // than SSCI. Happens when Patti walks to the control room. - if (g_sci->getGameId() == "lsl5" && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { + if (g_sci->getGameId() == GID_LSL5 && (s->currentRoomNumber() == 660) && (Common::Point(67, 131) == *new_start) && (Common::Point(229, 101) == *new_end)) { debug(1, "[avoidpath] Applying fix for priority problem in LSL5, room 660"); pf_s->_prependPoint = new_start; new_start = new Common::Point(77, 107); diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 6a564fcc57..0a39d950b0 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -465,7 +465,7 @@ SegmentRef LocalVariables::dereference(reg_t pointer) { ret.reg = &_locals[pointer.offset / 2]; } else { if ((g_sci->getEngineState()->currentRoomNumber() == 660 || g_sci->getEngineState()->currentRoomNumber() == 660) - && g_sci->getGameId() == "laurabow2") { + && g_sci->getGameId() == GID_LAURABOW2) { // Happens in two places during the intro of LB2CD, both from kMemory(peek): // - room 160: Heap 160 has 83 local variables (0-82), and the game // asks for variables at indices 83 - 90 too. @@ -520,7 +520,7 @@ SegmentRef SystemStrings::dereference(reg_t pointer) { if (isValidOffset(pointer.offset)) ret.raw = (byte *)(_strings[pointer.offset]._value); else { - if (g_sci->getGameId() == "kq5") { + if (g_sci->getGameId() == GID_KQ5) { // This occurs in KQ5CD when interacting with certain objects } else { error("SystemStrings::dereference(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); diff --git a/engines/sci/engine/static_selectors.cpp b/engines/sci/engine/static_selectors.cpp index 12d61ed24a..85089e74c8 100644 --- a/engines/sci/engine/static_selectors.cpp +++ b/engines/sci/engine/static_selectors.cpp @@ -158,7 +158,7 @@ Common::StringArray Kernel::checkStaticSelectorNames() { } } - if (g_sci->getGameId() == "hoyle4") { + if (g_sci->getGameId() == GID_HOYLE4) { // The demo of Hoyle 4 is one of the few demos with lip syncing and no selector vocabulary. // This needs two selectors, "syncTime" and "syncCue", which keep changing positions in each // game. Usually, games with speech and lip sync have a selector vocabulary, so we don't need diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3295406745..3dad005bb2 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -169,7 +169,7 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in } else { // WORKAROUND: Mixed-Up Mother Goose tries to use an invalid parameter in Event::new(). // Just skip around it here so we don't error out in validate_arithmetic. - if (g_sci->getGameId() == "mothergoose" && getSciVersion() <= SCI_VERSION_1_1 && type == VAR_PARAM && index == 1) + if (g_sci->getGameId() == GID_MOTHERGOOSE && getSciVersion() <= SCI_VERSION_1_1 && type == VAR_PARAM && index == 1) return false; debugC(2, kDebugLevelVM, "%s", txt.c_str()); @@ -184,20 +184,22 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in } struct UninitializedReadWorkaround { - const char *gameId; + SciGameId gameId; int scriptNr; const char *objectName; const char *methodName; int index; uint16 newValue; -} static const uninitializedReadWorkarounds[] = { - { "laurabow2", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { "freddypharkas", 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { "lsl1sci", 720, "rm720", "init", 0, 0 }, // age check room - { "islandbrain", 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { "sq4", 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller - { NULL, -1, NULL, NULL, 0, 0 } +}; + +static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { + { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room + { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller + { (SciGameId)0, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -218,14 +220,14 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i Common::String curObjectName = state->_segMan->getObjectName(call.sendp); Common::String curMethodName; - Common::String gameId = g_sci->getGameId(); + const SciGameId gameId = g_sci->getGameId(); if (call.type == EXEC_STACK_TYPE_CALL) curMethodName = g_sci->getKernel()->getSelectorName(call.selector); // Search if this is a known uninitialized read const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; - while (workaround->gameId) { + while (workaround->objectName) { if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName && workaround->methodName == curMethodName && workaround->index == index) { // Workaround found @@ -481,7 +483,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt if (!strcmp(objectName, "Sq4GlobalNarrator") && selector == 606) { // SQ4 has a script bug in the Sq4GlobalNarrator object when invoking the // returnVal selector, which doesn't affect gameplay, thus don't diplay it - } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == "qfg1") { + } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == GID_QFG1) { // QFG1VGA has a script bug in the longSong object when invoking the // loop selector, which doesn't affect gameplay, thus don't diplay it } else { diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 4cf3cc16e5..c5b97ad216 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -524,7 +524,7 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { // 2 Dummy functions, longbow-demo is using those several times but sierra sci doesn't support them at all case SCI_DISPLAY_DUMMY1: case SCI_DISPLAY_DUMMY2: - if (!((g_sci->getGameId() == "longbow") && (g_sci->isDemo()))) + if (!((g_sci->getGameId() == GID_LONGBOW) && (g_sci->isDemo()))) error("Unknown kDisplay argument %X", displayArg); if (displayArg == SCI_DISPLAY_DUMMY2) { if (argc) { diff --git a/engines/sci/graphics/picture.cpp b/engines/sci/graphics/picture.cpp index b410fc47f1..7cd37b6f46 100644 --- a/engines/sci/graphics/picture.cpp +++ b/engines/sci/graphics/picture.cpp @@ -437,7 +437,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { memcpy(&EGApalettes[i], &vector_defaultEGApalette, sizeof(vector_defaultEGApalette)); memcpy(&EGApriority, &vector_defaultEGApriority, sizeof(vector_defaultEGApriority)); - if (g_sci->getGameId() == "iceman") { + if (g_sci->getGameId() == GID_ICEMAN) { // WORKAROUND: we remove certain visual&priority lines in underwater rooms of iceman, when not dithering the // picture. Normally those lines aren't shown, because they share the same color as the dithered // fill color combination. When not dithering, those lines would appear and get distracting. @@ -532,7 +532,7 @@ void GfxPicture::drawVectorData(byte *data, int dataSize) { // inside picture data for such games case PIC_OP_SET_PATTERN: if (_resourceType >= SCI_PICTURE_TYPE_SCI11) { - if (g_sci->getGameId() == "sq4") { + if (g_sci->getGameId() == GID_SQ4) { // WORKAROUND: For SQ4 / for some pictures handle this like a terminator // This picture includes garbage data, first a set pattern w/o parameter and then short pattern // I guess that garbage is a left over from the sq4-floppy (sci1) to sq4-cd (sci1.1) conversion diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index a9bf81f013..6e53ef44c4 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -55,7 +55,7 @@ GfxPorts::~GfxPorts() { } void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) { - int16 offTop = 10; + int16 offTop; _usesOldGfxFunctions = usesOldGfxFunctions; _paint16 = paint16; @@ -84,15 +84,33 @@ void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *te else _styleUser = SCI_WINDOWMGR_STYLE_USER | SCI_WINDOWMGR_STYLE_TRANSPARENT; - // Jones, Slater, Hoyle 3&4 and Crazy Nicks Laura Bow/Kings Quest were called with parameter -Nw 0 0 200 320. - // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use SetPort so we don't need to set the other fields. + // Jones, Slater, Hoyle 3&4 and Crazy Nicks Laura Bow/Kings Quest were + // called with parameter -Nw 0 0 200 320. + // Mother Goose (SCI1) uses -Nw 0 0 159 262. The game will later use + // SetPort so we don't need to set the other fields. // This actually meant not skipping the first 10 pixellines in windowMgrPort - Common::String gameId = g_sci->getGameId(); - if (gameId == "jones" || gameId == "slater" || gameId == "hoyle3" || gameId == "hoyle4" || gameId == "cnick-laurabow" || gameId == "cnick-kq" || (gameId == "mothergoose" && getSciVersion() == SCI_VERSION_1_EARLY)) + switch (g_sci->getGameId()) { + case GID_JONES: + case GID_SLATER: + case GID_HOYLE3: + case GID_HOYLE4: + case GID_CNICK_LAURABOW: + case GID_CNICK_KQ: offTop = 0; - // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't also do this we will get not-fully-removed windows everywhere - if (gameId == "fairytales") + break; + case GID_MOTHERGOOSE: + if (getSciVersion() == SCI_VERSION_1_EARLY) + offTop = 0; + break; + case GID_FAIRYTALES: + // Mixed-Up Fairy Tales (& its demo) uses -w 26 0 200 320. If we don't + // also do this we will get not-fully-removed windows everywhere. offTop = 26; + break; + default: + offTop = 10; + break; + } openPort(_wmgrPort); setPort(_wmgrPort); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 82ff478da2..bcb86e2d6f 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -97,9 +97,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int ups if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) { // For SCI1.1 Mac, we need to expand the screen to accommodate for // the icon bar. Of course, both KQ6 and QFG1 VGA differ in size. - if (g_sci->getGameId() == "kq6") + if (g_sci->getGameId() == GID_KQ6) initGraphics(_displayWidth, _displayHeight + 26, _displayWidth > 320); - else if (g_sci->getGameId() == "qfg1") + else if (g_sci->getGameId() == GID_QFG1) initGraphics(_displayWidth, _displayHeight + 20, _displayWidth > 320); else error("Unknown SCI1.1 Mac game"); diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 00197876d8..584c61dbd6 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -323,7 +323,7 @@ public: * archive can be extracted in the extras directory, and the GM patches can be * applied per game, if applicable. */ - void addNewGMPatch(const Common::String &gameId); + void addNewGMPatch(SciGameId gameId); bool detectHires(); // Detects, if standard font of current game includes extended characters (>0x80) diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 909f1d6480..8629fecfa7 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -143,27 +143,37 @@ bool Resource::loadFromAudioVolumeSCI1(Common::SeekableReadStream *file) { return true; } -void ResourceManager::addNewGMPatch(const Common::String &gameId) { +void ResourceManager::addNewGMPatch(SciGameId gameId) { Common::String gmPatchFile; - if (gameId == "ecoquest") + switch (gameId) { + case GID_ECOQUEST: gmPatchFile = "ECO1GM.PAT"; - else if (gameId == "hoyle3") - gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "hoyle3") + break; + case GID_HOYLE3: gmPatchFile = "HOY3GM.PAT"; - else if (gameId == "lsl1sci") + break; + case GID_LSL1: gmPatchFile = "LL1_GM.PAT"; - else if (gameId == "lsl5") + break; + case GID_LSL5: gmPatchFile = "LL5_GM.PAT"; - else if (gameId == "longbow") + break; + case GID_LONGBOW: gmPatchFile = "ROBNGM.PAT"; - else if (gameId == "sq1sci") + break; + case GID_SQ1: gmPatchFile = "SQ1_GM.PAT"; - else if (gameId == "sq4") + break; + case GID_SQ4: gmPatchFile = "SQ4_GM.PAT"; - else if (gameId == "fairytales") + break; + case GID_FAIRYTALES: gmPatchFile = "TALEGM.PAT"; + break; + default: + break; + } if (!gmPatchFile.empty() && Common::File::exists(gmPatchFile)) { ResourceSource *psrcPatch = new PatchResourceSource(gmPatchFile); diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 527c2d24ba..6decfc7c27 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -71,8 +71,8 @@ SciEngine *g_sci = 0; class GfxDriver; -SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) - : Engine(syst), _gameDescription(desc), _gameId(_gameDescription->gameid) { +SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId) + : Engine(syst), _gameDescription(desc), _gameId(gameId) { assert(g_sci == 0); g_sci = this; @@ -128,7 +128,7 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc) // Add the patches directory, except for KQ6CD; The patches folder in some versions of KQ6CD // is for the demo of Phantasmagoria, included in the disk - if (_gameId != "kq6") + if (_gameId != GID_KQ6) SearchMan.addSubDirectoryMatching(gameDataDir, "patches"); // resource patches } @@ -179,10 +179,10 @@ Common::Error SciEngine::run() { // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit // it to platform windows. if (getPlatform() == Common::kPlatformWindows) { - if (_gameId == "kq6") + if (_gameId == GID_KQ6) upscaledHires = GFX_SCREEN_UPSCALED_640x440; #ifdef ENABLE_SCI32 - if (_gameId == "gk1") + if (_gameId == GID_GK1) upscaledHires = GFX_SCREEN_UPSCALED_640x480; #endif } @@ -503,6 +503,10 @@ Console *SciEngine::getSciDebugger() { return _console; } +const char *SciEngine::getGameIdStr() const { + return _gameDescription->gameid; +} + Common::Language SciEngine::getLanguage() const { return _gameDescription->language; } @@ -524,12 +528,12 @@ Common::String SciEngine::getSavegamePattern() const { } Common::String SciEngine::getFilePrefix() const { - if (_gameId == "qfg2") { + if (_gameId == GID_QFG2) { // Quest for Glory 2 wants to read files from Quest for Glory 1 (EGA/VGA) to import character data if (_gamestate->currentRoomNumber() == 805) return "qfg1"; // TODO: Include import-room for qfg1vga - } else if (_gameId == "qfg3") { + } else if (_gameId == GID_QFG3) { // Quest for Glory 3 wants to read files from Quest for Glory 2 to import character data if (_gamestate->currentRoomNumber() == 54) return "qfg2"; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 68a62c5fcc..f60aad67a7 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -104,6 +104,75 @@ enum kDebugLevels { kDebugLevelOnStartup = 1 << 23 }; +enum SciGameId { + GID_ASTROCHICKEN, + GID_CAMELOT, + GID_CASTLEBRAIN, + GID_CHRISTMAS1988, + GID_CHRISTMAS1990, + GID_CHRISTMAS1992, + GID_CNICK_KQ, + GID_CNICK_LAURABOW, + GID_CNICK_LONGBOW, + GID_CNICK_LSL, + GID_CNICK_SQ, + GID_ECOQUEST, + GID_ECOQUEST2, + GID_FAIRYTALES, + GID_FREDDYPHARKAS, + GID_FUNSEEKER, + GID_GK1, + GID_GK2, + GID_HOYLE1, + GID_HOYLE2, + GID_HOYLE3, + GID_HOYLE4, + GID_ICEMAN, + GID_ISLANDBRAIN, + GID_JONES, + GID_KQ1, + GID_KQ4, + GID_KQ5, + GID_KQ6, + GID_KQ7, + GID_LAURABOW, + GID_LAURABOW2, + GID_LIGHTHOUSE, + GID_LONGBOW, + GID_LSL1, + GID_LSL2, + GID_LSL3, + GID_LSL5, + GID_LSL6, + GID_LSL7, + GID_MOTHERGOOSE, + GID_MSASTROCHICKEN, + GID_PEPPER, + GID_PHANTASMAGORIA, + GID_PHANTASMAGORIA2, + GID_PQ1, + GID_PQ2, + GID_PQ3, + GID_PQ4, + GID_PQSWAT, + GID_QFG1, + GID_QFG2, + GID_QFG3, + GID_QFG4, + GID_RAMA, + GID_SHIVERS, + GID_SHIVERS2, + GID_SLATER, + GID_SQ1, + GID_SQ3, + GID_SQ4, + GID_SQ5, + GID_SQ6, + GID_TORIN, + + GID_FANMADE // FIXME: Do we really need/want this? +}; + /** SCI versions */ enum SciVersion { SCI_VERSION_NONE, @@ -136,7 +205,7 @@ enum kLanguage { class SciEngine : public Engine { friend class Console; public: - SciEngine(OSystem *syst, const ADGameDescription *desc); + SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gameId); ~SciEngine(); // Engine APIs @@ -151,7 +220,8 @@ public: bool canSaveGameStateCurrently(); void syncSoundSettings(); - const Common::String &getGameId() const { return _gameId; } + const SciGameId &getGameId() const { return _gameId; } + const char *getGameIdStr() const; int getResourceVersion() const; Common::Language getLanguage() const; Common::Platform getPlatform() const; @@ -264,7 +334,7 @@ private: void initStackBaseWithSelector(Selector selector); const ADGameDescription *_gameDescription; - const Common::String _gameId; + const SciGameId _gameId; ResourceManager *_resMan; /**< The resource manager */ EngineState *_gamestate; Kernel *_kernel; -- cgit v1.2.3 From b188fc14a2591e480c0fb4a16558ef0a2aacd3a3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 16:43:09 +0000 Subject: SCI: only send new volume to currently mapped channels, fixes assert in sq1 because setVolume is called on an object that's currently not playing. added fixme svn-id: r50274 --- engines/sci/sound/midiparser_sci.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 4766118f52..cb43f6c3a1 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -672,9 +672,11 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: - // sending volume change to all used channels + // sending volume change to all currently mapped channels + // FIXME?: maybe we should better store new volume if music isn't playing currently and adjust volume + // when playing for (int i = 0; i < 15; i++) - if (_channelUsed[i]) + if (_channelRemap[i] != -1) sendToDriver(0xB0 + i, 7, _volume); break; -- cgit v1.2.3 From ab19e874147da865aab63ee89c50ef21bb687613 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 16:54:03 +0000 Subject: Removed all of the non-validating code - there's no real point in removing script validations svn-id: r50275 --- engines/sci/engine/kernel.h | 1 - engines/sci/engine/vm.cpp | 37 ------------------------------------- 2 files changed, 38 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 4333f6ef77..a347e90d1a 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -94,7 +94,6 @@ struct SelectorCache; // from selector.h //@{ //#define DEBUG_PARSER // enable for parser debugging -//#define DISABLE_VALIDATIONS // enable to stop validation checks // ---- Kernel signatures ----------------------------------------------------- diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3dad005bb2..2da414c9f9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -95,8 +95,6 @@ static ExecStack *add_exec_stack_varselector(Common::List &execStack, // validation functionality -#ifndef DISABLE_VALIDATIONS - static reg_t &validate_property(Object *obj, int index) { // A static dummy reg_t, which we return if obj or index turn out to be // invalid. Note that we cannot just return NULL_REG, because client code @@ -286,19 +284,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i } } -#else -// Non-validating alternatives - -# define validate_stack_addr(s, sp) sp -# define validate_arithmetic(r) ((r).offset) -# define signed_validate_arithmetic(r) ((int16)(r).offset) -# define validate_variable(r, sb, t, m, i, l) -# define validate_read_var(r, sb, t, m, i, l, dv) ((r)[i]) -# define validate_write_var(r, sb, t, m, i, l, v, sm, k) ((r)[i] = (v)) -# define validate_property(o, p) ((o)->_variables[p]) - -#endif - #define READ_VAR(type, index, def) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, def) #define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); @@ -607,10 +592,6 @@ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t return &(execStack.back()); } -#ifdef DISABLE_VALIDATIONS -# define kernel_matches_signature(a, b, c, d) 1 -#endif - static reg_t pointer_add(EngineState *s, reg_t base, int offset) { SegmentObj *mobj = s->_segMan->getSegmentObj(base.segment); @@ -804,9 +785,7 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) void run_vm(EngineState *s, bool restoring) { assert(s); -#ifndef DISABLE_VALIDATIONS unsigned int code_buf_size = 0 ; // (Avoid spurious warning) -#endif int temp; int16 aux_acc; // Auxiliary 16 bit accumulator reg_t r_temp; // Temporary register @@ -857,9 +836,7 @@ void run_vm(EngineState *s, bool restoring) { // FIXME: Why does this happen? Are there leftover calls in the call stack? warning("Running on non-existant script in segment %x", s->xs->addr.pc.segment); code_buf = _fake_return_buffer; -#ifndef DISABLE_VALIDATIONS code_buf_size = 2; -#endif s->xs->addr.pc.offset = 1; scr = NULL; @@ -867,18 +844,14 @@ void run_vm(EngineState *s, bool restoring) { } else { obj = s->_segMan->getObject(s->xs->objp); code_buf = scr->_buf; -#ifndef DISABLE_VALIDATIONS code_buf_size = scr->getBufSize(); -#endif local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); if (!local_script) { // FIXME: Why does this happen? Is the script not loaded yet at this point? warning("Could not find local script from segment %x", s->xs->local_segment); local_script = NULL; s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; -#ifndef DISABLE_VALIDATIONS s->variablesMax[VAR_LOCAL] = 0; -#endif } else { s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; @@ -886,14 +859,12 @@ void run_vm(EngineState *s, bool restoring) { s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); else s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; -#ifndef DISABLE_VALIDATIONS if (local_script->_localsBlock) s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); else s->variablesMax[VAR_LOCAL] = 0; s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; s->variablesMax[VAR_PARAM] = s->xs->argc + 1; -#endif } s->variables[VAR_TEMP] = s->xs->fp; s->variables[VAR_PARAM] = s->xs->variables_argp; @@ -915,7 +886,6 @@ void run_vm(EngineState *s, bool restoring) { con->onFrame(); } -#ifndef DISABLE_VALIDATIONS if (s->xs->sp < s->xs->fp) error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp)); @@ -925,7 +895,6 @@ void run_vm(EngineState *s, bool restoring) { if (s->xs->addr.pc.offset >= code_buf_size) error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", s->xs->addr.pc.offset, code_buf_size); -#endif // Get opcode byte extOpcode; @@ -1517,12 +1486,10 @@ void run_vm(EngineState *s, bool restoring) { s->r_acc.offset = s->xs->addr.pc.offset + opparams[0]; } -#ifndef DISABLE_VALIDATIONS if (s->r_acc.offset >= code_buf_size) { error("VM: lofsa operation overflowed: %04x:%04x beyond end" " of script (at %04x)\n", PRINT_REG(s->r_acc), code_buf_size); } -#endif break; case op_lofss: // 0x3a (58) @@ -1539,12 +1506,10 @@ void run_vm(EngineState *s, bool restoring) { r_temp.offset = s->xs->addr.pc.offset + opparams[0]; } -#ifndef DISABLE_VALIDATIONS if (r_temp.offset >= code_buf_size) { error("VM: lofss operation overflowed: %04x:%04x beyond end" " of script (at %04x)", PRINT_REG(r_temp), code_buf_size); } -#endif PUSH32(r_temp); break; @@ -1781,13 +1746,11 @@ void run_vm(EngineState *s, bool restoring) { if (s->_executionStackPosChanged) // Force initialization s->xs = xs_new; -//#ifndef DISABLE_VALIDATIONS if (s->xs != &(s->_executionStack.back())) { error("xs is stale (%p vs %p); last command was %02x", (void *)s->xs, (void *)&(s->_executionStack.back()), opcode); } -//#endif ++s->scriptStepCounter; } } -- cgit v1.2.3 From b6d1b3bc0b2c4e3edbc49a73cb629313eb84c889 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 17:13:47 +0000 Subject: Do not allow the VM to run on non-existent scripts (which shouldn't be happening anymore) svn-id: r50276 --- engines/sci/engine/vm.cpp | 61 +++++++++++++++++++---------------------------- 1 file changed, 24 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 2da414c9f9..068259224d 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -826,50 +826,37 @@ void run_vm(EngineState *s, bool restoring) { return; // Stop processing if (s->_executionStackPosChanged) { - Script *scr; + Script *scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); + if (!scr) + error("No script in segment %d", s->xs->addr.pc.segment); s->xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; - scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); - if (!scr) { - // No script? Implicit return via fake instruction buffer - // FIXME: Why does this happen? Are there leftover calls in the call stack? - warning("Running on non-existant script in segment %x", s->xs->addr.pc.segment); - code_buf = _fake_return_buffer; - code_buf_size = 2; - s->xs->addr.pc.offset = 1; - - scr = NULL; - obj = NULL; + obj = s->_segMan->getObject(s->xs->objp); + code_buf = scr->_buf; + code_buf_size = scr->getBufSize(); + local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); + if (!local_script) { + // FIXME: Why does this happen? Is the script not loaded yet at this point? + warning("Could not find local script from segment %x", s->xs->local_segment); + local_script = NULL; + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + s->variablesMax[VAR_LOCAL] = 0; } else { - obj = s->_segMan->getObject(s->xs->objp); - code_buf = scr->_buf; - code_buf_size = scr->getBufSize(); - local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); - if (!local_script) { - // FIXME: Why does this happen? Is the script not loaded yet at this point? - warning("Could not find local script from segment %x", s->xs->local_segment); - local_script = NULL; + s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; + if (local_script->_localsBlock) + s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); + else s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; + if (local_script->_localsBlock) + s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); + else s->variablesMax[VAR_LOCAL] = 0; - } else { - - s->variablesSegment[VAR_LOCAL] = local_script->_localsSegment; - if (local_script->_localsBlock) - s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = local_script->_localsBlock->_locals.begin(); - else - s->variablesBase[VAR_LOCAL] = s->variables[VAR_LOCAL] = NULL; - if (local_script->_localsBlock) - s->variablesMax[VAR_LOCAL] = local_script->_localsBlock->_locals.size(); - else - s->variablesMax[VAR_LOCAL] = 0; - s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; - s->variablesMax[VAR_PARAM] = s->xs->argc + 1; - } - s->variables[VAR_TEMP] = s->xs->fp; - s->variables[VAR_PARAM] = s->xs->variables_argp; + s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; + s->variablesMax[VAR_PARAM] = s->xs->argc + 1; } - + s->variables[VAR_TEMP] = s->xs->fp; + s->variables[VAR_PARAM] = s->xs->variables_argp; } if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) -- cgit v1.2.3 From aedc77f0bddcfcd11e465ee29c5fc66973ef9f9b Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 17:25:00 +0000 Subject: When loading a game, stop all running VMs recursively, and also stop kAnimate's current recursion. This fixes the invalid execution stack frame in SQ1, when loading from the death screen after dying from the acid drops in Kerona. This should also fix the invalid hunk pointers, thus the warning about invalid hunk pointers has been turned into an error, as it shouldn't occur anymore svn-id: r50277 --- engines/sci/engine/seg_manager.cpp | 2 +- engines/sci/engine/vm.cpp | 5 +++++ engines/sci/graphics/animate.cpp | 5 +++++ 3 files changed, 11 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index e011de67d9..d356c9a3fc 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -454,7 +454,7 @@ byte *SegManager::getHunkPointer(reg_t addr) { HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); if (!ht || !ht->isValidEntry(addr.offset)) { - warning("getHunkPointer() with invalid handle %04x:%04x", PRINT_REG(addr)); + error("getHunkPointer() with invalid handle %04x:%04x", PRINT_REG(addr)); return NULL; } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 068259224d..f54cddc253 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1226,6 +1226,11 @@ void run_vm(EngineState *s, bool restoring) { xs_new = &(s->_executionStack.back()); s->_executionStackPosChanged = true; + + // If a game is being loaded, stop processing + if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return; // Stop processing + break; } diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 9018a6f62e..08ff3bfc80 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -98,6 +98,11 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { if (!(signal & kSignalFrozen)) { // Call .doit method of that object invokeSelector(_s, curObject, SELECTOR(doit), argc, argv, 0); + + // If a game is being loaded, stop processing + if (_s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) + return true; // Stop processing + // Lookup node again, since the nodetable it was in may have been reallocated curNode = _s->_segMan->lookupNode(curAddress); } -- cgit v1.2.3 From 69694f361977d8ae1908957e5fb9d4ad242bbf98 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 17:59:48 +0000 Subject: SCI: changing workaround results for opcodes from signal_reg to make_reg(0, 1) svn-id: r50278 --- engines/sci/engine/vm.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f54cddc253..9ebf8ca53d 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1029,7 +1029,7 @@ void run_vm(EngineState *s, bool restoring) { error("[VM] op_gt: comparsion between a pointer and number"); // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion // Happens in SQ1, room 28, when throwing the water at Orat - s->r_acc = SIGNAL_REG; + s->r_acc = make_reg(0, 1); } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) > (int16)/*acc*/); break; @@ -1082,7 +1082,7 @@ void run_vm(EngineState *s, bool restoring) { // It works because in those games, the maximum resource number is 999, // so any parameter value above that threshold must be a pointer. if (r_temp.segment && (s->r_acc == make_reg(0, 1000))) - s->r_acc = SIGNAL_REG; + s->r_acc = make_reg(0, 1); else if (r_temp.segment && s->r_acc.segment) s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset > s->r_acc.offset); else -- cgit v1.2.3 From 784f52a677aed3877b47371f6bbcb3e3ffa97393 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 17:59:49 +0000 Subject: Removed the getHunkPointer error - it's valid SCI behavior (e.g. when loading/quitting sometimes, since hunks are not saved). We check for valid hunk pointers anyway, so there's no reason for the warning/error svn-id: r50279 --- engines/sci/engine/seg_manager.cpp | 2 +- engines/sci/graphics/paint16.cpp | 3 ++- 2 files changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index d356c9a3fc..3740e53339 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -454,7 +454,7 @@ byte *SegManager::getHunkPointer(reg_t addr) { HunkTable *ht = (HunkTable *)getSegment(addr.segment, SEG_TYPE_HUNK); if (!ht || !ht->isValidEntry(addr.offset)) { - error("getHunkPointer() with invalid handle %04x:%04x", PRINT_REG(addr)); + // Valid SCI behavior, e.g. when loading/quitting return NULL; } diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index c5b97ad216..88fa467b3a 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -330,7 +330,8 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) { memoryId = _segMan->allocateHunkEntry("SaveBits()", size); memoryPtr = _segMan->getHunkPointer(memoryId); - _screen->bitsSave(workerRect, screenMask, memoryPtr); + if (memoryPtr) + _screen->bitsSave(workerRect, screenMask, memoryPtr); return memoryId; } -- cgit v1.2.3 From be8a59666894364c04b127b7b97bfd6efdd08b35 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 25 Jun 2010 18:20:31 +0000 Subject: Add support for the third inventory case in Riven: you have the two journals but not the trap book (happens at the end of the game). svn-id: r50280 --- engines/mohawk/graphics.cpp | 22 +++++++++++-------- engines/mohawk/riven.cpp | 51 ++++++++++++++++++++++++++++++--------------- engines/mohawk/riven.h | 10 +++++---- 3 files changed, 53 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp index 2ddfb47575..00de6dba11 100644 --- a/engines/mohawk/graphics.cpp +++ b/engines/mohawk/graphics.cpp @@ -607,19 +607,23 @@ void RivenGraphics::showInventory() { if (_vm->getFeatures() & GF_DEMO || _vm->getCurStack() == aspit) return; - // There are three books and three vars. However, there's only - // a possible two combinations. Either you have only Atrus' - // journal or you have all three books. - // bool hasAtrusBook = *_vm->matchVarToString("aatrusbook") != 0; + // There are three books and three vars. We have three different + // combinations. At the start you have just Atrus' journal. Later, + // you get Catherine's journal and the trap book. Near the end, + // you lose the trap book and have just the two journals. + bool hasCathBook = *_vm->matchVarToString("acathbook") != 0; - // bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0; + bool hasTrapBook = *_vm->matchVarToString("atrapbook") != 0; if (!hasCathBook) { - drawInventoryImage(101, g_atrusJournalRectSolo); + drawInventoryImage(101, g_atrusJournalRect1); + } else if (!hasTrapBook) { + drawInventoryImage(101, g_atrusJournalRect2); + drawInventoryImage(102, g_cathJournalRect2); } else { - drawInventoryImage(101, g_atrusJournalRect); - drawInventoryImage(102, g_cathJournalRect); - drawInventoryImage(100, g_trapBookRect); + drawInventoryImage(101, g_atrusJournalRect3); + drawInventoryImage(102, g_cathJournalRect3); + drawInventoryImage(100, g_trapBookRect3); } _vm->_system->updateScreen(); diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index fa7ffd7c45..1e7f006be1 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -37,10 +37,12 @@ namespace Mohawk { -Common::Rect *g_atrusJournalRectSolo; -Common::Rect *g_atrusJournalRect; -Common::Rect *g_cathJournalRect; -Common::Rect *g_trapBookRect; +Common::Rect *g_atrusJournalRect1; +Common::Rect *g_atrusJournalRect2; +Common::Rect *g_cathJournalRect2; +Common::Rect *g_atrusJournalRect3; +Common::Rect *g_cathJournalRect3; +Common::Rect *g_trapBookRect3; MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescription *gamedesc) : MohawkEngine(syst, gamedesc) { _showHotspots = false; @@ -58,10 +60,12 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio SearchMan.addSubDirectoryMatching(gameDataDir, "exe"); SearchMan.addSubDirectoryMatching(gameDataDir, "assets1"); - g_atrusJournalRectSolo = new Common::Rect(295, 402, 313, 426); - g_atrusJournalRect = new Common::Rect(222, 402, 240, 426); - g_cathJournalRect = new Common::Rect(291, 408, 311, 419); - g_trapBookRect = new Common::Rect(363, 396, 386, 432); + g_atrusJournalRect1 = new Common::Rect(295, 402, 313, 426); + g_atrusJournalRect2 = new Common::Rect(259, 402, 278, 426); + g_cathJournalRect2 = new Common::Rect(328, 408, 348, 419); + g_atrusJournalRect3 = new Common::Rect(222, 402, 240, 426); + g_cathJournalRect3 = new Common::Rect(291, 408, 311, 419); + g_trapBookRect3 = new Common::Rect(363, 396, 386, 432); } MohawkEngine_Riven::~MohawkEngine_Riven() { @@ -74,10 +78,12 @@ MohawkEngine_Riven::~MohawkEngine_Riven() { delete _loadDialog; delete _optionsDialog; delete _rnd; - delete g_atrusJournalRectSolo; - delete g_atrusJournalRect; - delete g_cathJournalRect; - delete g_trapBookRect; + delete g_atrusJournalRect1; + delete g_atrusJournalRect2; + delete g_cathJournalRect2; + delete g_atrusJournalRect3; + delete g_cathJournalRect3; + delete g_trapBookRect3; _cardData.scripts.clear(); } @@ -479,26 +485,37 @@ void MohawkEngine_Riven::checkInventoryClick() { *matchVarToString("returncardid") = _curCard; // See RivenGraphics::showInventory() for an explanation - // of why only this variable is used. + // of the variables' meanings. bool hasCathBook = *matchVarToString("acathbook") != 0; + bool hasTrapBook = *matchVarToString("atrapbook") != 0; // Go to the book if a hotspot contains the mouse if (!hasCathBook) { - if (g_atrusJournalRectSolo->contains(_mousePos)) { + if (g_atrusJournalRect1->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(5); } + } else if (!hasTrapBook) { + if (g_atrusJournalRect2->contains(_mousePos)) { + _gfx->hideInventory(); + changeToStack(aspit); + changeToCard(5); + } else if (g_cathJournalRect2->contains(_mousePos)) { + _gfx->hideInventory(); + changeToStack(aspit); + changeToCard(6); + } } else { - if (g_atrusJournalRect->contains(_mousePos)) { + if (g_atrusJournalRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(5); - } else if (g_cathJournalRect->contains(_mousePos)) { + } else if (g_cathJournalRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(6); - } else if (g_trapBookRect->contains(_mousePos)) { + } else if (g_trapBookRect3->contains(_mousePos)) { _gfx->hideInventory(); changeToStack(aspit); changeToCard(7); diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 11c3a4c0cb..5fe0de00e9 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -68,10 +68,12 @@ enum { // Rects for the inventory object positions (initialized in // MohawkEngine_Riven's constructor). -extern Common::Rect *g_atrusJournalRectSolo; -extern Common::Rect *g_atrusJournalRect; -extern Common::Rect *g_cathJournalRect; -extern Common::Rect *g_trapBookRect; +extern Common::Rect *g_atrusJournalRect1; +extern Common::Rect *g_atrusJournalRect2; +extern Common::Rect *g_cathJournalRect2; +extern Common::Rect *g_atrusJournalRect3; +extern Common::Rect *g_cathJournalRect3; +extern Common::Rect *g_trapBookRect3; struct RivenHotspot { uint16 blstID; -- cgit v1.2.3 From 3962f8ba59925ea3ffa5e27e738c2edc9434b74c Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 18:47:52 +0000 Subject: AUDIO: some fixes in the audio device code (no sound option, new GUIO flags) svn-id: r50281 --- engines/gob/gob.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index fba616b166..ddeac25baa 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -346,7 +346,7 @@ void GobEngine::pauseGame() { bool GobEngine::initGameParts() { // just detect some devices some of which will be always there if the music is not disabled - _noMusic = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB) ? false : true; + _noMusic = MidiDriver::getMusicType(MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB)) == MT_NULL ? true : false; _saveLoad = 0; _global = new Global(this); -- cgit v1.2.3 From e34d7342f54ff5d23273eeec15fe5d4934492749 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 18:57:50 +0000 Subject: KYRA: implement new gui option flags svn-id: r50282 --- engines/kyra/detection_tables.h | 113 +++++++++++++++++++++------------------- 1 file changed, 58 insertions(+), 55 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index 9f40cc3b1f..b73b4c09dc 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -56,6 +56,9 @@ namespace { #define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) #define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) +#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_EOB1) +#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_EOB2) + const KYRAGameDescription adGameDescs[] = { /* disable these targets until they get supported { @@ -66,7 +69,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_CMP_FLAGS }, @@ -79,7 +82,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_CMP_FLAGS }, @@ -93,7 +96,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -105,7 +108,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -117,7 +120,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -129,7 +132,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -141,7 +144,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -153,7 +156,7 @@ const KYRAGameDescription adGameDescs[] = { Common::ES_ESP, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -165,7 +168,7 @@ const KYRAGameDescription adGameDescs[] = { Common::ES_ESP, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -177,7 +180,7 @@ const KYRAGameDescription adGameDescs[] = { Common::IT_ITA, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_FLOPPY_FLAGS }, @@ -245,7 +248,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformFMTowns, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS }, KYRA1_TOWNS_FLAGS }, @@ -261,7 +264,7 @@ const KYRAGameDescription adGameDescs[] = { Common::JA_JPN, Common::kPlatformFMTowns, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS }, KYRA1_TOWNS_SJIS_FLAGS }, @@ -280,7 +283,7 @@ const KYRAGameDescription adGameDescs[] = { Common::JA_JPN, Common::kPlatformPC98, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 }, KYRA1_TOWNS_SJIS_FLAGS }, @@ -293,7 +296,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_CD_FLAGS }, @@ -305,7 +308,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_CD_FLAGS }, @@ -317,7 +320,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_CD_FLAGS }, @@ -330,7 +333,7 @@ const KYRAGameDescription adGameDescs[] = { Common::IT_ITA, Common::kPlatformPC, ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_CD_FLAGS }, @@ -392,7 +395,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_DEMO_FLAGS }, @@ -405,7 +408,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIPCSPK }, KYRA1_DEMO_CD_FLAGS }, @@ -418,7 +421,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_CMP_FLAGS }, @@ -431,7 +434,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_CMP_FLAGS }, @@ -444,7 +447,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_FLAGS }, @@ -457,7 +460,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_FLAGS }, @@ -470,7 +473,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_FLAGS }, @@ -483,7 +486,7 @@ const KYRAGameDescription adGameDescs[] = { Common::IT_ITA, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_FLOPPY_FLAGS }, @@ -496,7 +499,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FLAGS }, @@ -508,7 +511,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FLAGS }, @@ -520,7 +523,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FLAGS }, @@ -534,7 +537,7 @@ const KYRAGameDescription adGameDescs[] = { Common::IT_ITA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -546,7 +549,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -558,7 +561,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -571,7 +574,7 @@ const KYRAGameDescription adGameDescs[] = { Common::IT_ITA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -584,7 +587,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -597,7 +600,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_FAN_FLAGS(Common::IT_ITA, Common::EN_ANY) }, @@ -610,7 +613,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_DEMO_FLAGS }, @@ -623,7 +626,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_DEMO_FLAGS }, @@ -636,7 +639,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD | ADGF_DEMO, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_CD_DEMO_FLAGS }, @@ -649,7 +652,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, KYRA2_DEMO_FLAGS }, @@ -662,7 +665,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformFMTowns, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS }, KYRA2_TOWNS_FLAGS }, @@ -674,7 +677,7 @@ const KYRAGameDescription adGameDescs[] = { Common::JA_JPN, Common::kPlatformFMTowns, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDITOWNS }, KYRA2_TOWNS_SJIS_FLAGS }, @@ -686,7 +689,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC98, ADGF_CD, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 }, KYRA2_TOWNS_FLAGS }, @@ -698,7 +701,7 @@ const KYRAGameDescription adGameDescs[] = { Common::JA_JPN, Common::kPlatformPC98, ADGF_CD, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 }, KYRA2_TOWNS_SJIS_FLAGS }, @@ -969,7 +972,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -986,7 +989,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -1003,7 +1006,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -1020,7 +1023,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -1037,7 +1040,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -1054,7 +1057,7 @@ const KYRAGameDescription adGameDescs[] = { Common::FR_FRA, Common::kPlatformPC, ADGF_DROPLANGUAGE | ADGF_CD, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_CD_FLAGS }, @@ -1070,7 +1073,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_FLOPPY_CMP_FLAGS }, @@ -1086,7 +1089,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_FLOPPY_CMP_FLAGS }, @@ -1103,7 +1106,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_FLOPPY_FLAGS }, @@ -1120,7 +1123,7 @@ const KYRAGameDescription adGameDescs[] = { Common::DE_DEU, Common::kPlatformPC, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_FLOPPY_FLAGS }, @@ -1137,7 +1140,7 @@ const KYRAGameDescription adGameDescs[] = { Common::JA_JPN, Common::kPlatformPC98, ADGF_NO_FLAGS, - Common::GUIO_NOSPEECH + Common::GUIO_NOSPEECH | Common::GUIO_MIDIPC98 }, LOL_PC98_SJIS_FLAGS }, @@ -1154,7 +1157,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, - Common::GUIO_NONE + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_DEMO_FLAGS }, @@ -1170,7 +1173,7 @@ const KYRAGameDescription adGameDescs[] = { Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, - Common::GUIO_NOSPEECH + Common::GUIO_MIDIADLIB | Common::GUIO_MIDIMT32 | Common::GUIO_MIDIGM | Common::GUIO_MIDIPCSPK }, LOL_KYRA2_DEMO_FLAGS }, -- cgit v1.2.3 From 6561b93f1e15e4b78bbf62044ea145e866978eeb Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 19:06:10 +0000 Subject: KYRA: fixed typo svn-id: r50283 --- engines/kyra/detection_tables.h | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/kyra/detection_tables.h b/engines/kyra/detection_tables.h index b73b4c09dc..390281c356 100644 --- a/engines/kyra/detection_tables.h +++ b/engines/kyra/detection_tables.h @@ -56,9 +56,6 @@ namespace { #define LOL_DEMO_FLAGS FLAGS(true, true, false, false, false, false, false, Kyra::GI_LOL) #define LOL_KYRA2_DEMO_FLAGS FLAGS(true, false, false, false, false, false, false, Kyra::GI_KYRA2) -#define EOB_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_EOB1) -#define EOB2_FLAGS FLAGS(false, false, false, false, false, false, false, Kyra::GI_EOB2) - const KYRAGameDescription adGameDescs[] = { /* disable these targets until they get supported { -- cgit v1.2.3 From 4785e1fd3ffe2dbe862e9aafcf18eb2a10602bc4 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 25 Jun 2010 19:09:19 +0000 Subject: Renamed some variables svn-id: r50284 --- engines/sci/console.cpp | 14 ++--- engines/sci/console.h | 2 +- engines/sci/engine/klists.cpp | 122 ++++++++++++++++++------------------- engines/sci/engine/seg_manager.cpp | 6 +- 4 files changed, 72 insertions(+), 72 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e8cbb6cf0e..e50ae171c1 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2173,12 +2173,12 @@ bool Console::cmdViewReference(int argc, const char **argv) { case 0: break; case KSIG_LIST: { - List *l = _engine->_gamestate->_segMan->lookupList(reg); + List *list = _engine->_gamestate->_segMan->lookupList(reg); DebugPrintf("list\n"); - if (l) - printList(l); + if (list) + printList(list); else DebugPrintf("Invalid list.\n"); } @@ -3173,8 +3173,8 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV return 0; } -void Console::printList(List *l) { - reg_t pos = l->first; +void Console::printList(List *list) { + reg_t pos = list->first; reg_t my_prev = NULL_REG; DebugPrintf("\t<\n"); @@ -3201,9 +3201,9 @@ void Console::printList(List *l) { pos = node->succ; } - if (my_prev != l->last) + if (my_prev != list->last) DebugPrintf(" WARNING: Last node was expected to be %04x:%04x, was %04x:%04x!\n", - PRINT_REG(l->last), PRINT_REG(my_prev)); + PRINT_REG(list->last), PRINT_REG(my_prev)); DebugPrintf("\t>\n"); } diff --git a/engines/sci/console.h b/engines/sci/console.h index 5f3b0e3951..e353958a0d 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -147,7 +147,7 @@ private: bool cmdViewAccumulatorObject(int argc, const char **argv); bool segmentInfo(int nr); - void printList(List *l); + void printList(List *list); int printNode(reg_t addr); private: diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 1fd34849ea..eb5334c3b9 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -58,20 +58,20 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) { } static void checkListPointer(SegManager *segMan, reg_t addr) { - List *l = segMan->lookupList(addr); + List *list = segMan->lookupList(addr); - if (!l) { + if (!list) { warning("isSaneListPointer (list %04x:%04x): The requested list wasn't found", PRINT_REG(addr)); return; } - if (l->first.isNull() && l->last.isNull()) { + if (list->first.isNull() && list->last.isNull()) { // Empty list is fine - } else if (!l->first.isNull() && !l->last.isNull()) { + } else if (!list->first.isNull() && !list->last.isNull()) { // Normal list - Node *node_a = segMan->lookupNode(l->first); - Node *node_z = segMan->lookupNode(l->last); + Node *node_a = segMan->lookupNode(list->first); + Node *node_z = segMan->lookupNode(list->last); if (!node_a) { warning("isSaneListPointer (list %04x:%04x): missing first node", PRINT_REG(addr)); @@ -101,25 +101,25 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { return; } - isSaneNodePointer(segMan, l->first); + isSaneNodePointer(segMan, list->first); } else { // Not sane list... it's missing pointers to the first or last element - if (l->first.isNull()) + if (list->first.isNull()) warning("isSaneListPointer (list %04x:%04x): missing pointer to first element", PRINT_REG(addr)); - if (l->last.isNull()) + if (list->last.isNull()) warning("isSaneListPointer (list %04x:%04x): missing pointer to last element", PRINT_REG(addr)); } } reg_t kNewList(EngineState *s, int argc, reg_t *argv) { - reg_t listbase; - List *l = s->_segMan->allocateList(&listbase); - l->first = l->last = NULL_REG; - debugC(2, kDebugLevelNodes, "New listbase at %04x:%04x", PRINT_REG(listbase)); + reg_t listRef; + List *list = s->_segMan->allocateList(&listRef); + list->first = list->last = NULL_REG; + debugC(2, kDebugLevelNodes, "New listRef at %04x:%04x", PRINT_REG(listRef)); - return listbase; // Return list base address + return listRef; // Return list base address } reg_t kDisposeList(EngineState *s, int argc, reg_t *argv) { @@ -136,7 +136,7 @@ reg_t kNewNode(EngineState *s, int argc, reg_t *argv) { reg_t nodeKey = (argc == 2) ? argv[1] : argv[0]; s->r_acc = s->_segMan->newNode(nodeValue, nodeKey); - debugC(2, kDebugLevelNodes, "New nodebase at %04x:%04x", PRINT_REG(s->r_acc)); + debugC(2, kDebugLevelNodes, "New nodeRef at %04x:%04x", PRINT_REG(s->r_acc)); return s->r_acc; } @@ -145,11 +145,11 @@ reg_t kFirstNode(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); - if (l) { + if (list) { checkListPointer(s->_segMan, argv[0]); - return l->first; + return list->first; } else { return NULL_REG; } @@ -159,11 +159,11 @@ reg_t kLastNode(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); - if (l) { + if (list) { checkListPointer(s->_segMan, argv[0]); - return l->last; + return list->last; } else { return NULL_REG; } @@ -173,54 +173,56 @@ reg_t kEmptyList(EngineState *s, int argc, reg_t *argv) { if (argv[0].isNull()) return NULL_REG; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); checkListPointer(s->_segMan, argv[0]); - return make_reg(0, ((l) ? l->first.isNull() : 0)); + return make_reg(0, ((list) ? list->first.isNull() : 0)); } -static void _k_add_to_front(EngineState *s, reg_t listbase, reg_t nodebase) { - List *l = s->_segMan->lookupList(listbase); - Node *new_n = s->_segMan->lookupNode(nodebase); +static void _k_add_to_front(EngineState *s, reg_t listRef, reg_t nodeRef) { + List *list = s->_segMan->lookupList(listRef); + Node *newNode = s->_segMan->lookupNode(nodeRef); + + debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); - debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + if (!newNode) + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); + checkListPointer(s->_segMan, listRef); - if (!new_n) - error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - checkListPointer(s->_segMan, listbase); + newNode->pred = NULL_REG; + newNode->succ = list->first; - new_n->succ = l->first; - new_n->pred = NULL_REG; // Set node to be the first and last node if it's the only node of the list - if (l->first.isNull()) - l->last = nodebase; + if (list->first.isNull()) + list->last = nodeRef; else { - Node *old_n = s->_segMan->lookupNode(l->first); - old_n->pred = nodebase; + Node *oldNode = s->_segMan->lookupNode(list->first); + oldNode->pred = nodeRef; } - l->first = nodebase; + list->first = nodeRef; } -static void _k_add_to_end(EngineState *s, reg_t listbase, reg_t nodebase) { - List *l = s->_segMan->lookupList(listbase); - Node *new_n = s->_segMan->lookupNode(nodebase); +static void _k_add_to_end(EngineState *s, reg_t listRef, reg_t nodeRef) { + List *list = s->_segMan->lookupList(listRef); + Node *newNode = s->_segMan->lookupNode(nodeRef); - debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); + debugC(2, kDebugLevelNodes, "Adding node %04x:%04x to end of list %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); - if (!new_n) - error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodebase), PRINT_REG(listbase)); - checkListPointer(s->_segMan, listbase); + if (!newNode) + error("Attempt to add non-node (%04x:%04x) to list at %04x:%04x", PRINT_REG(nodeRef), PRINT_REG(listRef)); + checkListPointer(s->_segMan, listRef); + + newNode->pred = list->last; + newNode->succ = NULL_REG; - new_n->succ = NULL_REG; - new_n->pred = l->last; // Set node to be the first and last node if it's the only node of the list - if (l->last.isNull()) - l->first = nodebase; + if (list->last.isNull()) + list->first = nodeRef; else { - Node *old_n = s->_segMan->lookupNode(l->last); - old_n->succ = nodebase; + Node *old_n = s->_segMan->lookupNode(list->last); + old_n->succ = nodeRef; } - l->last = nodebase; + list->last = nodeRef; } reg_t kNextNode(EngineState *s, int argc, reg_t *argv) { @@ -253,7 +255,7 @@ reg_t kAddToFront(EngineState *s, int argc, reg_t *argv) { } reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); Node *firstnode = argv[1].isNull() ? NULL : s->_segMan->lookupNode(argv[1]); Node *newnode = s->_segMan->lookupNode(argv[2]); @@ -281,7 +283,7 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { if (oldnext.isNull()) // Appended after last node? // Set new node as last list node - l->last = argv[2]; + list->last = argv[2]; else s->_segMan->lookupNode(oldnext)->pred = argv[2]; @@ -328,16 +330,16 @@ reg_t kFindKey(EngineState *s, int argc, reg_t *argv) { reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { reg_t node_pos = kFindKey(s, 2, argv); Node *n; - List *l = s->_segMan->lookupList(argv[0]); + List *list = s->_segMan->lookupList(argv[0]); if (node_pos.isNull()) return NULL_REG; // Signal failure n = s->_segMan->lookupNode(node_pos); - if (l->first == node_pos) - l->first = n->succ; - if (l->last == node_pos) - l->last = n->pred; + if (list->first == node_pos) + list->first = n->succ; + if (list->last == node_pos) + list->last = n->pred; if (!n->pred.isNull()) s->_segMan->lookupNode(n->pred)->succ = n->succ; @@ -374,8 +376,6 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { reg_t order_func = argv[2]; int input_size = (int16)readSelectorValue(segMan, source, SELECTOR(size)); - int i; - reg_t input_data = readSelector(segMan, source, SELECTOR(elements)); reg_t output_data = readSelector(segMan, dest, SELECTOR(elements)); @@ -398,7 +398,7 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { sort_temp_t *temp_array = (sort_temp_t *)malloc(sizeof(sort_temp_t) * input_size); - i = 0; + int i = 0; while (node) { reg_t params[1] = { node->value }; invokeSelector(s, order_func, SELECTOR(doit), argc, argv, 1, params); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 3740e53339..9394e717ec 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -505,13 +505,13 @@ Node *SegManager::allocateNode(reg_t *addr) { } reg_t SegManager::newNode(reg_t value, reg_t key) { - reg_t nodebase; - Node *n = allocateNode(&nodebase); + reg_t nodeRef; + Node *n = allocateNode(&nodeRef); n->pred = n->succ = NULL_REG; n->key = key; n->value = value; - return nodebase; + return nodeRef; } List *SegManager::lookupList(reg_t addr) { -- cgit v1.2.3 From 683d54a74660745d6bd408788170b19adb08581e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 20:46:08 +0000 Subject: SCI: adding workaround for uninitialized read in sq1 svn-id: r50287 --- engines/sci/engine/vm.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9ebf8ca53d..29def1765b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -191,13 +191,14 @@ struct UninitializedReadWorkaround { }; static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room - { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller - { (SciGameId)0, -1, NULL, NULL, 0, 0 } + { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room + { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { GID_SQ1, 703, "fromAirlock", "", 0, 0 }, // sub that's called from fromAirlock::changeState + { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller + { (SciGameId)0, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { -- cgit v1.2.3 From c35e3505319977e56d1c413b39133dfedf6c1105 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 20:51:57 +0000 Subject: AUDIO: get rid of MDT_PREFER_MIDI since it should be sufficient to either select MDT_PREFER_MT32 or MDT_PREFER_GM svn-id: r50288 --- engines/agos/agos.cpp | 2 +- engines/draci/draci.cpp | 2 +- engines/groovie/music.cpp | 4 ++-- engines/groovie/script.cpp | 2 +- engines/kyra/kyra_v1.cpp | 2 +- engines/lure/sound.cpp | 2 +- engines/m4/m4.cpp | 2 +- engines/made/made.cpp | 2 +- engines/parallaction/parallaction_br.cpp | 2 +- engines/parallaction/parallaction_ns.cpp | 2 +- engines/queen/music.cpp | 2 +- engines/saga/music.cpp | 2 +- engines/sci/engine/vm.cpp | 6 ++++++ engines/sci/sound/music.cpp | 2 +- engines/scumm/detection_tables.h | 20 ++++++++++---------- engines/sky/sky.cpp | 2 +- engines/tinsel/tinsel.cpp | 2 +- engines/touche/midi.cpp | 2 +- 18 files changed, 33 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 481c73dc5c..3ccf6fc18f 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -557,7 +557,7 @@ Common::Error AGOSEngine::init() { (getPlatform() == Common::kPlatformPC)) { // Setup midi driver - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM)); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | (getGameType() == GType_SIMON1 ? MDT_PREFER_MT32 : MDT_PREFER_GM)); _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); _driver = MidiDriver::createMidi(dev); diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index 9e1e7033bb..a87e9a476d 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -127,7 +127,7 @@ int DraciEngine::init() { _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency); _sound = new Sound(_mixer); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index 9b46af1483..f226ef3397 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -386,7 +386,7 @@ MusicPlayerXMI::MusicPlayerXMI(GroovieEngine *vm, const Common::String >lName) _midiParser = MidiParser::createParser_XMIDI(); // Create the driver - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); _driver = createMidi(dev); this->open(); @@ -682,7 +682,7 @@ MusicPlayerMac::MusicPlayerMac(GroovieEngine *vm) : MusicPlayerMidi(vm) { _midiParser = MidiParser::createParser_SMF(); // Create the driver - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); _driver = createMidi(dev); this->open(); diff --git a/engines/groovie/script.cpp b/engines/groovie/script.cpp index 08df5e7a83..9fd7fa7d63 100644 --- a/engines/groovie/script.cpp +++ b/engines/groovie/script.cpp @@ -86,7 +86,7 @@ Script::Script(GroovieEngine *vm, EngineVersion version) : } // Initialize the music type variable - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); if (MidiDriver::getMusicType(dev) == MT_ADLIB) { // MIDI through AdLib setVariable(0x100, 0); diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index 970851c127..be8f976053 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -106,7 +106,7 @@ Common::Error KyraEngine_v1::init() { if (!_flags.useDigSound) { // We prefer AdLib over MIDI, since generally AdLib is better supported - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI | MDT_PREFER_MT32); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) diff --git a/engines/lure/sound.cpp b/engines/lure/sound.cpp index 1b306b5021..cd539dfab4 100644 --- a/engines/lure/sound.cpp +++ b/engines/lure/sound.cpp @@ -50,7 +50,7 @@ SoundManager::SoundManager() { _soundData = NULL; _paused = false; - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); _isRoland = MidiDriver::getMusicType(dev) != MT_ADLIB; _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 8063044205..f1506598d2 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -156,7 +156,7 @@ Common::Error MadsM4Engine::run() { // Initialize backend _screen = new M4Surface(true); // Special form for creating screen reference - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); _driver = MidiDriver::createMidi(dev); diff --git a/engines/made/made.cpp b/engines/made/made.cpp index b983e87cc2..94926014d3 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -97,7 +97,7 @@ MadeEngine::MadeEngine(OSystem *syst, const MadeGameDescription *gameDesc) : Eng _script = new ScriptInterpreter(this); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); diff --git a/engines/parallaction/parallaction_br.cpp b/engines/parallaction/parallaction_br.cpp index 6dbf526c96..470c698a21 100644 --- a/engines/parallaction/parallaction_br.cpp +++ b/engines/parallaction/parallaction_br.cpp @@ -61,7 +61,7 @@ Common::Error Parallaction_br::init() { _disk = new DosDisk_br(this); } _disk->setLanguage(2); // NOTE: language is now hardcoded to English. Original used command-line parameters. - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_br(this, driver); } else { diff --git a/engines/parallaction/parallaction_ns.cpp b/engines/parallaction/parallaction_ns.cpp index 7e06aaa5ab..f1e7b14583 100644 --- a/engines/parallaction/parallaction_ns.cpp +++ b/engines/parallaction/parallaction_ns.cpp @@ -166,7 +166,7 @@ Common::Error Parallaction_ns::init() { _disk->init(); if (getPlatform() == Common::kPlatformPC) { - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); MidiDriver *driver = MidiDriver::createMidi(dev); _soundManI = new DosSoundMan_ns(this, driver); _soundManI->setMusicVolume(ConfMan.getInt("music_volume")); diff --git a/engines/queen/music.cpp b/engines/queen/music.cpp index 2bbbd53568..3d859c8335 100644 --- a/engines/queen/music.cpp +++ b/engines/queen/music.cpp @@ -46,7 +46,7 @@ MidiMusic::MidiMusic(QueenEngine *vm) _queuePos = _lastSong = _currentSong = 0; queueClear(); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI | MDT_PREFER_MT32); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); _adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index dbe79a3e72..8b7654d689 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -47,7 +47,7 @@ MusicDriver::MusicDriver() : _isGM(false) { _masterVolume = 0; _nativeMT32 = ConfMan.getBool("native_mt32"); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); _driver = MidiDriver::createMidi(dev); if (isMT32()) _driver->property(MidiDriver::PROP_CHANNEL_MASK, 0x03FE); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 29def1765b..452ccde2da 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -386,6 +386,12 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt // Returns a pointer to the TOS exec_stack element assert(s); + //if (send_obj.segment == 27 && send_obj.offset == 190 && s->resmgr->_protectionCountSpec > 20) { + //if (s->resmgr->_protectionCountSpec == 21) + // s->resmgr->_protectionCountSpec--; + //send_obj.offset = 1388; + //} + reg_t funcp; int selector; int argc; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 0d1f0f4db9..400189ee2e 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -68,7 +68,7 @@ void SciMusic::init() { // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we // default to MIDI in those games to let them run. Common::Platform platform = g_sci->getPlatform(); - uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); + uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); switch (MidiDriver::getMusicType(dev)) { case MT_ADLIB: diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index e9dfce8057..d8987c816f 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -224,7 +224,7 @@ static const GameSettings gameVariantsTable[] = { {"indy3", "VGA", "vga", GID_INDY3, 3, 0, MDT_PCSPK | MDT_ADLIB, GF_OLD256 | GF_FEW_LOCALS, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"indy3", "FM-TOWNS", 0, GID_INDY3, 3, 0, MDT_TOWNS, GF_OLD256 | GF_FEW_LOCALS | GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"loom", "EGA", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, {"loom", "No AdLib", "ega", GID_LOOM, 3, 0, MDT_PCSPK | MDT_CMS, 0, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, #ifdef USE_RGB_COLOR {"loom", "PC-Engine", 0, GID_LOOM, 3, 0, MDT_NONE, GF_AUDIOTRACKS | GF_OLD256 | GF_16BIT_COLOR, Common::kPlatformPCEngine, GUIO_NOSPEECH | GUIO_NOMIDI}, @@ -234,24 +234,24 @@ static const GameSettings gameVariantsTable[] = { {"pass", 0, 0, GID_PASS, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, + {"monkey", "VGA", "vga", GID_MONKEY_VGA, 4, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"monkey", "EGA", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_CMS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH}, {"monkey", "No AdLib", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK, GF_16COLOR, Common::kPlatformAtariST, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "Demo", "ega", GID_MONKEY_EGA, 4, 0, MDT_PCSPK | MDT_ADLIB, GF_16COLOR, Common::kPlatformPC, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO_NOSPEECH | GUIO_NOMIDI}, {"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO_NOSPEECH | GUIO_NOMIDI}, - {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"monkey2", 0, 0, GID_MONKEY2, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE}, - {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, + {"atlantis", "" , 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NONE}, + {"atlantis", "Floppy", 0, GID_INDY4, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO_NOSPEECH}, - {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, - {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"tentacle", "", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"tentacle", "Floppy", 0, GID_TENTACLE, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, - {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, - {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, + {"samnmax", "", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NONE}, + {"samnmax", "Floppy", 0, GID_SAMNMAX, 6, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM, GF_USE_KEY, UNK, GUIO_NOSPEECH}, #ifdef ENABLE_SCUMM_7_8 {"ft", 0, 0, GID_FT, 7, 0, MDT_NONE, 0, UNK, GUIO_NOMIDI}, diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index 58e3f5be2c..45b3cab947 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -259,7 +259,7 @@ Common::Error SkyEngine::init() { _systemVars.gameVersion = _skyDisk->determineGameVersion(); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MIDI | MDT_PREFER_MT32); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32); if (MidiDriver::getMusicType(dev) == MT_ADLIB) { _systemVars.systemFlags |= SF_SBLASTER; _skyMusic = new AdLibMusic(_mixer, _skyDisk); diff --git a/engines/tinsel/tinsel.cpp b/engines/tinsel/tinsel.cpp index e5a39308da..195066cac1 100644 --- a/engines/tinsel/tinsel.cpp +++ b/engines/tinsel/tinsel.cpp @@ -856,7 +856,7 @@ TinselEngine::TinselEngine(OSystem *syst, const TinselGameDescription *gameDesc) if (cd_num >= 0) _system->openCD(cd_num); - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); bool native_mt32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); //bool adlib = (MidiDriver::getMusicType(dev) == MT_ADLIB); diff --git a/engines/touche/midi.cpp b/engines/touche/midi.cpp index 5c1d687827..439d3b9ac2 100644 --- a/engines/touche/midi.cpp +++ b/engines/touche/midi.cpp @@ -92,7 +92,7 @@ void MidiPlayer::setVolume(int volume) { } int MidiPlayer::open() { - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_MIDI); + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); _nativeMT32 = ((MidiDriver::getMusicType(dev) == MT_MT32) || ConfMan.getBool("native_mt32")); _driver = MidiDriver::createMidi(dev); int ret = _driver->open(); -- cgit v1.2.3 From e1a333570eb127fd9d16c1272cc9772d6f6b9559 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 20:58:52 +0000 Subject: SCI: set MDT_PREFER_GM instead od MDT_PREFER_MT32 svn-id: r50289 --- engines/sci/sound/music.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 400189ee2e..32f1869e33 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -68,7 +68,7 @@ void SciMusic::init() { // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we // default to MIDI in those games to let them run. Common::Platform platform = g_sci->getPlatform(); - uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); + uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); switch (MidiDriver::getMusicType(dev)) { case MT_ADLIB: -- cgit v1.2.3 From b96c0a1f0797812e45d1ee135d291556f9c60866 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 25 Jun 2010 21:04:22 +0000 Subject: SCI: fix typo svn-id: r50291 --- engines/sci/engine/vm.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 452ccde2da..29def1765b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -386,12 +386,6 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt // Returns a pointer to the TOS exec_stack element assert(s); - //if (send_obj.segment == 27 && send_obj.offset == 190 && s->resmgr->_protectionCountSpec > 20) { - //if (s->resmgr->_protectionCountSpec == 21) - // s->resmgr->_protectionCountSpec--; - //send_obj.offset = 1388; - //} - reg_t funcp; int selector; int argc; -- cgit v1.2.3 From fc4fa25ec4272f6117ca32e3c3998b15de30eca3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 22:34:53 +0000 Subject: SCI: adding capability for detecting export-calls into valgrind-sci, adding workaround for export 1 of script 703 in sq1 (gets called from various objects) svn-id: r50292 --- engines/sci/engine/vm.cpp | 55 +++++++++++++++++++++++++---------------------- engines/sci/engine/vm.h | 1 + 2 files changed, 30 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 29def1765b..f7c38e0e2b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -60,6 +60,8 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; * @param[in] argp Heap pointer to the first parameter * @param[in] selector The selector by which it was called or * NULL_SELECTOR if n.a. For debugging. + * @param[in] exportId The exportId by which it was called or + * -1 if n.a. For debugging. * @param[in] sendp Pointer to the object which the message was * sent to. Equal to objp for anything but super. * @param[in] origin Number of the execution stack element this @@ -70,7 +72,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; * @return A pointer to the new exec stack TOS entry */ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t pc, StackPtr sp, - reg_t objp, int argc, StackPtr argp, Selector selector, + reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, reg_t sendp, int origin, SegmentId local_segment); @@ -191,14 +193,14 @@ struct UninitializedReadWorkaround { }; static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room - { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { GID_SQ1, 703, "fromAirlock", "", 0, 0 }, // sub that's called from fromAirlock::changeState - { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller - { (SciGameId)0, -1, NULL, NULL, 0, 0 } + { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu + { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room + { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { GID_SQ1, 703, "", "export 1", 0, 0 }, // sub that's called from several objects + { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller + { (SciGameId)0, -1, NULL, NULL, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -207,22 +209,22 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i // Uninitialized read on a temp // We need to find correct replacements for each situation manually EngineState *state = g_sci->getEngineState(); - Script *local_script = state->_segMan->getScriptIfLoaded(state->xs->local_segment); + ExecStack *call = state->xs; + Script *local_script = state->_segMan->getScriptIfLoaded(call->local_segment); int curScriptNr = local_script->_nr; - Common::List::iterator callIterator = state->_executionStack.begin(); - ExecStack call = *callIterator; - while (callIterator != state->_executionStack.end()) { - call = *callIterator; - callIterator++; - } - - Common::String curObjectName = state->_segMan->getObjectName(call.sendp); + Common::String curObjectName = state->_segMan->getObjectName(call->sendp); Common::String curMethodName; const SciGameId gameId = g_sci->getGameId(); - if (call.type == EXEC_STACK_TYPE_CALL) - curMethodName = g_sci->getKernel()->getSelectorName(call.selector); + if (call->type == EXEC_STACK_TYPE_CALL) { + if (call->selector != -1) { + curMethodName = g_sci->getKernel()->getSelectorName(call->selector); + } else if (call->exportId != -1) { + curObjectName = ""; + curMethodName = curMethodName.printf("export %d", call->exportId); + } + } // Search if this is a known uninitialized read const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; @@ -343,7 +345,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } } - return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, calling_obj, s->_executionStack.size()-1, seg); + return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, calling_obj, s->_executionStack.size()-1, seg); } @@ -541,7 +543,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt else add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj, call.argc, call.argp, - call.selector, send_obj, origin, SCI_XS_CALLEE_LOCALS); + call.selector, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); } _exec_varselectors(s); @@ -550,7 +552,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } static ExecStack *add_exec_stack_varselector(Common::List &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) { - ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, objp, origin, SCI_XS_CALLEE_LOCALS); + ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, objp, origin, SCI_XS_CALLEE_LOCALS); // Store selector address in sp xstack->addr.varp = address; @@ -560,7 +562,7 @@ static ExecStack *add_exec_stack_varselector(Common::List &execStack, } static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc, - StackPtr argp, Selector selector, reg_t sendp, int origin, SegmentId _localsSegment) { + StackPtr argp, Selector selector, int exportId, reg_t sendp, int origin, SegmentId _localsSegment) { // Returns new TOS element for the execution stack // _localsSegment may be -1 if derived from the called object @@ -585,6 +587,7 @@ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t // Additional debug information xstack.selector = selector; + xstack.exportId = exportId; xstack.origin = origin; xstack.type = EXEC_STACK_TYPE_CALL; // Normal call @@ -639,7 +642,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { // This is useful in debugger backtraces if this // kernel function calls a script itself. ExecStack *xstack; - xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, NULL_REG, + xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, NULL_REG, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); xstack->selector = kernelFuncNum; xstack->type = EXEC_STACK_TYPE_KERNEL; @@ -1194,7 +1197,7 @@ void run_vm(EngineState *s, bool restoring) { s->xs->addr.pc.offset + opparams[0]), s->xs->sp, s->xs->objp, (validate_arithmetic(*call_base)) + s->restAdjust, - call_base, NULL_SELECTOR, s->xs->objp, + call_base, NULL_SELECTOR, -1, s->xs->objp, s->_executionStack.size()-1, s->xs->local_segment); s->restAdjust = 0; // Used up the &rest adjustment s->xs->sp = call_base; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 88898cdbba..ed3d5483b6 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -103,6 +103,7 @@ struct ExecStack { SegmentId local_segment; // local variables etc Selector selector; // The selector which was used to call or -1 if not applicable + int exportId; // The exportId which was called or -1 if not applicable int origin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; -- cgit v1.2.3 From 56d9acad90588453837710775ab8fbb7649884a5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 25 Jun 2010 22:48:55 +0000 Subject: SCI: implementing workaround for issue in room 58 sq1 (operation lt, doing comparsion against pointer) svn-id: r50294 --- engines/sci/engine/vm.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f7c38e0e2b..70c4f3d996 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1056,6 +1056,12 @@ void run_vm(EngineState *s, bool restoring) { if (r_temp.segment != s->r_acc.segment) warning("[VM] Comparing pointers in different segments (%04x:%04x vs. %04x:%04x)", PRINT_REG(r_temp), PRINT_REG(s->r_acc)); s->r_acc = make_reg(0, (r_temp.segment == s->r_acc.segment) && r_temp.offset < s->r_acc.offset); + } else if (r_temp.segment && !s->r_acc.segment) { + if (s->r_acc.offset >= 1000) + error("[VM] op_lt: comparsion between a pointer and number"); + // Pseudo-WORKAROUND: sierra allows any pointer <-> value comparsion + // Happens in SQ1, room 58, when giving id-card to robot + s->r_acc = make_reg(0, 1); } else s->r_acc = ACC_ARITHMETIC_L(signed_validate_arithmetic(r_temp) < (int16)/*acc*/); break; -- cgit v1.2.3 From e328bd8f7f95ae18be4ec6796baf14c1c8b17728 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Fri, 25 Jun 2010 23:43:07 +0000 Subject: Added support for Fab compressed sprite sets svn-id: r50295 --- engines/m4/assets.cpp | 42 ++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 40 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index c329373add..0c0bf330a7 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -234,12 +234,15 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre spriteStream = sprite.getItemStream(1); Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3); SpriteAssetFrame frame; + Common::Array frameSizes; for (curFrame = 0; curFrame < _frameCount; curFrame++) { frame.stream = 0; frame.comp = 0; frameOffset = spriteStream->readUint32LE(); _frameOffsets.push_back(frameOffset); - spriteStream->readUint32LE(); // frame size + uint32 frameSize = spriteStream->readUint32LE(); + frameSizes.push_back(frameSize); + frame.x = spriteStream->readUint16LE(); frame.y = spriteStream->readUint16LE(); frame.w = spriteStream->readUint16LE(); @@ -247,9 +250,44 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre if (curFrame == 0) debugC(1, kDebugGraphics, "%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h); - frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); + if (_mode == 0) { + // Create a frame and decompress the raw pixel data + uint32 currPos = (uint32)spriteDataStream->pos(); + frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false); + assert((uint32)spriteDataStream->pos() == (currPos + frameSize)); + } + _frames.push_back(frame); } + + if (_mode != 0) { + // Handle decompressing Fab encoded data + for (curFrame = 0; curFrame < _frameCount; curFrame++) { + FabDecompressor fab; + + int srcSize = (curFrame == (_frameCount - 1)) ? spriteDataStream->size() - _frameOffsets[curFrame] : + _frameOffsets[curFrame + 1] - _frameOffsets[curFrame]; + byte *srcData = (byte *)malloc(srcSize); + assert(srcData); + spriteDataStream->read(srcData, srcSize); + + byte *destData = (byte *)malloc(frameSizes[curFrame]); + assert(destData); + + fab.decompress(srcData, srcSize, destData, frameSizes[curFrame]); + + // Load the frame + Common::MemoryReadStream *rs = new Common::MemoryReadStream(destData, frameSizes[curFrame]); + _frames[curFrame].frame = new M4Sprite(rs, _frames[curFrame].x, _frames[curFrame].y, + _frames[curFrame].w, _frames[curFrame].h, false); + delete rs; + + free(srcData); + free(destData); + } + } + + delete spriteStream; delete spriteDataStream; } -- cgit v1.2.3 From ab261facee90ede5dd7dd5bf38262745eef3e946 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Jun 2010 00:36:43 +0000 Subject: Added extra validation for sprite decoding svn-id: r50297 --- engines/m4/sprite.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/sprite.cpp b/engines/m4/sprite.cpp index 4ce1b75b35..641b93baea 100644 --- a/engines/m4/sprite.cpp +++ b/engines/m4/sprite.cpp @@ -121,6 +121,8 @@ void M4Sprite::loadDeltaRle(Common::SeekableReadStream* rleData, int destX, int // TODO: The sprite outlines (pixel value 0xFD) are not shown void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { + bool spriteEnd = false; + // Set entire sprite contents to transparent pixels fillRect(bounds(), TRANSPARENT_COLOUR_INDEX); @@ -131,10 +133,14 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { byte cmd = source->readByte(); int x2 = 0; - if (cmd == 0xff) + if (cmd == 0xfc) { + // End of entire sprite + spriteEnd = true; + break; + } else if (cmd == 0xff) { // The entire line is empty newLine = true; - else if (cmd == 0xFD) { + } else if (cmd == 0xFD) { // Lines contains only run lenghs of pixels while (x2 < w) { cmd = source->readByte(); @@ -189,6 +195,11 @@ void M4Sprite::loadMadsSprite(Common::SeekableReadStream* source) { } while (source->readByte() != 0xff); } } + + if (!spriteEnd) { + byte v = source->readByte(); + assert(v == 0xFC); + } } byte M4Sprite::getTransparencyIndex() const { -- cgit v1.2.3 From 70e4a8605b85abf3edb83afe2df0ca8992e79f20 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Jun 2010 00:37:44 +0000 Subject: Minor bugfix for correctly positioning where background sprites are drawn svn-id: r50298 --- engines/m4/mads_views.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 1184ab81e7..dd5eb7a266 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -158,11 +158,11 @@ void MadsSpriteSlots::drawBackground(int yOffset) { if (slot.depth > 1) { // Draw the frame with depth processing - _owner._bgSurface->copyFrom(frame, xp, yp, Common::Point(0, yOffset), slot.depth, + _owner._bgSurface->copyFrom(frame, xp, yp, Common::Point(), slot.depth, _owner._depthSurface, 100, frame->getTransparencyIndex()); } else { // No depth, so simply draw the image - frame->copyTo(_owner._bgSurface, xp, yp + yOffset, frame->getTransparencyIndex()); + frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex()); } } } -- cgit v1.2.3 From 258494f03694362e2d0e63b6803dcb7eaabfaa21 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 08:29:55 +0000 Subject: SCI: adding capability to resolve local calls as well for valgrind-sci, adding another workaround for a script bug in sq1 (this time export 1 gets called locally) svn-id: r50308 --- engines/sci/engine/vm.cpp | 72 ++++++++++++++++++++++++++++++----------------- engines/sci/engine/vm.h | 1 + 2 files changed, 47 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 70c4f3d996..d1fcbbd1f9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -72,7 +72,7 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; * @return A pointer to the new exec stack TOS entry */ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t pc, StackPtr sp, - reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, + reg_t objp, int argc, StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId local_segment); @@ -188,19 +188,22 @@ struct UninitializedReadWorkaround { int scriptNr; const char *objectName; const char *methodName; + int localCallOffset; int index; uint16 newValue; }; static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, "gcWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, "quitWin", "open", 5, 0xf }, // is used as priority for game menu - { GID_LSL1, 720, "rm720", "init", 0, 0 }, // age check room - { GID_ISLANDBRAIN, 140, "piece", "init", 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 - { GID_SQ1, 703, "", "export 1", 0, 0 }, // sub that's called from several objects - { GID_SQ4, 928, "Narrator", "startText", 1000, 1 }, // sq4cd: method returns this to the caller - { (SciGameId)0, -1, NULL, NULL, 0, 0 } + { GID_LAURABOW2, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room + { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects + { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally + { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // export 1 sub, but called locally + { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller + { (SciGameId)0, -1, NULL, NULL, -1, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -209,20 +212,34 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i // Uninitialized read on a temp // We need to find correct replacements for each situation manually EngineState *state = g_sci->getEngineState(); - ExecStack *call = state->xs; - Script *local_script = state->_segMan->getScriptIfLoaded(call->local_segment); + ExecStack *lastCall = state->xs; + Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); int curScriptNr = local_script->_nr; - Common::String curObjectName = state->_segMan->getObjectName(call->sendp); + if (lastCall->localCallOffset != -1) { + // if lastcall was actually a local call search back for a real call + Common::List::iterator callIterator = state->_executionStack.end(); + while (callIterator != state->_executionStack.begin()) { + callIterator--; + ExecStack loopCall = *callIterator; + if ((loopCall.selector != -1) || (loopCall.exportId != -1)) { + lastCall->selector = loopCall.selector; + lastCall->exportId = loopCall.exportId; + break; + } + } + } + + Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp); Common::String curMethodName; const SciGameId gameId = g_sci->getGameId(); - if (call->type == EXEC_STACK_TYPE_CALL) { - if (call->selector != -1) { - curMethodName = g_sci->getKernel()->getSelectorName(call->selector); - } else if (call->exportId != -1) { + if (lastCall->type == EXEC_STACK_TYPE_CALL) { + if (lastCall->selector != -1) { + curMethodName = g_sci->getKernel()->getSelectorName(lastCall->selector); + } else if (lastCall->exportId != -1) { curObjectName = ""; - curMethodName = curMethodName.printf("export %d", call->exportId); + curMethodName = curMethodName.printf("export %d", lastCall->exportId); } } @@ -230,14 +247,14 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; while (workaround->objectName) { if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName - && workaround->methodName == curMethodName && workaround->index == index) { + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) { // Workaround found r[index] = make_reg(0, workaround->newValue); return r[index]; } workaround++; } - error("Uninitialized read for temp %d from method %s::%s (script %d)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr); + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %lx)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset); } return r[index]; } else @@ -345,7 +362,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } } - return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, calling_obj, s->_executionStack.size()-1, seg); + return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg); } @@ -543,7 +560,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt else add_exec_stack_entry(s->_executionStack, call.address.func, call.sp, work_obj, call.argc, call.argp, - call.selector, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); + call.selector, -1, -1, send_obj, origin, SCI_XS_CALLEE_LOCALS); } _exec_varselectors(s); @@ -552,7 +569,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } static ExecStack *add_exec_stack_varselector(Common::List &execStack, reg_t objp, int argc, StackPtr argp, Selector selector, const ObjVarRef& address, int origin) { - ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, objp, origin, SCI_XS_CALLEE_LOCALS); + ExecStack *xstack = add_exec_stack_entry(execStack, NULL_REG, 0, objp, argc, argp, selector, -1, -1, objp, origin, SCI_XS_CALLEE_LOCALS); // Store selector address in sp xstack->addr.varp = address; @@ -562,7 +579,7 @@ static ExecStack *add_exec_stack_varselector(Common::List &execStack, } static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t pc, StackPtr sp, reg_t objp, int argc, - StackPtr argp, Selector selector, int exportId, reg_t sendp, int origin, SegmentId _localsSegment) { + StackPtr argp, Selector selector, int exportId, int localCallOffset, reg_t sendp, int origin, SegmentId _localsSegment) { // Returns new TOS element for the execution stack // _localsSegment may be -1 if derived from the called object @@ -588,6 +605,7 @@ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t // Additional debug information xstack.selector = selector; xstack.exportId = exportId; + xstack.localCallOffset = localCallOffset; xstack.origin = origin; xstack.type = EXEC_STACK_TYPE_CALL; // Normal call @@ -642,7 +660,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { // This is useful in debugger backtraces if this // kernel function calls a script itself. ExecStack *xstack; - xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, NULL_REG, + xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); xstack->selector = kernelFuncNum; xstack->type = EXEC_STACK_TYPE_KERNEL; @@ -1199,11 +1217,13 @@ void run_vm(EngineState *s, bool restoring) { StackPtr call_base = s->xs->sp - argc; s->xs->sp[1].offset += s->restAdjust; + uint16 localCallOffset = s->xs->addr.pc.offset + opparams[0]; + xs_new = add_exec_stack_entry(s->_executionStack, make_reg(s->xs->addr.pc.segment, - s->xs->addr.pc.offset + opparams[0]), + localCallOffset), s->xs->sp, s->xs->objp, (validate_arithmetic(*call_base)) + s->restAdjust, - call_base, NULL_SELECTOR, -1, s->xs->objp, + call_base, NULL_SELECTOR, -1, localCallOffset, s->xs->objp, s->_executionStack.size()-1, s->xs->local_segment); s->restAdjust = 0; // Used up the &rest adjustment s->xs->sp = call_base; diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index ed3d5483b6..d747ddd113 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -104,6 +104,7 @@ struct ExecStack { Selector selector; // The selector which was used to call or -1 if not applicable int exportId; // The exportId which was called or -1 if not applicable + int localCallOffset; // Local call offset or -1 if not applicable int origin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; -- cgit v1.2.3 From cf3a37585cfd333a10acfd5d2eae853c6c47ed6d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 09:34:14 +0000 Subject: SCI: making hack inside kAbs hoyle1 specific, added fixme svn-id: r50309 --- engines/sci/engine/kmath.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 6d4b9a2a04..3c0ab814f1 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -36,9 +36,12 @@ reg_t kRandom(EngineState *s, int argc, reg_t *argv) { } reg_t kAbs(EngineState *s, int argc, reg_t *argv) { - // This is a hack, but so is the code in Hoyle1 that needs it. - if (argv[0].segment) - return make_reg(0, 0x3e9); // Yes people, this is an object + if (g_sci->getGameId() == GID_HOYLE1) { + // This is a hack, but so is the code in Hoyle1 that needs it. + // FIXME: where is this exactly needed? + if (argv[0].segment) + return make_reg(0, 0x3e9); // Yes people, this is an object + } return make_reg(0, abs(argv[0].toSint16())); } -- cgit v1.2.3 From 16f854ba644aff930236d4f3ed5c8e6be35a970b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 10:47:38 +0000 Subject: SCI: dont call midiparser->stop() if paused sound gets stopped svn-id: r50310 --- engines/sci/sound/music.cpp | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 32f1869e33..d1555ca7a6 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -365,6 +365,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { } void SciMusic::soundStop(MusicEntry *pSnd) { + SoundStatus previousStatus = pSnd->status; pSnd->status = kSoundStopped; if (_soundVersion <= SCI_VERSION_0_LATE) pSnd->isQueued = false; @@ -374,7 +375,9 @@ void SciMusic::soundStop(MusicEntry *pSnd) { if (pSnd->pMidiParser) { _mutex.lock(); pSnd->pMidiParser->mainThreadBegin(); - pSnd->pMidiParser->stop(); + // We shouldn't call stop in case it's paused, otherwise we would send allNotesOff() again + if (previousStatus == kSoundPlaying) + pSnd->pMidiParser->stop(); freeChannels(pSnd); pSnd->pMidiParser->mainThreadEnd(); _mutex.unlock(); -- cgit v1.2.3 From 906b3221f58d71c0c73a9c60f9fd3feb7fcafaab Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 10:51:38 +0000 Subject: SCI: removing fixme (issue got already solved) svn-id: r50311 --- engines/sci/sound/midiparser_sci.cpp | 6 ------ 1 file changed, 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index cb43f6c3a1..0bcafc8075 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -382,12 +382,6 @@ void MidiParser_SCI::allNotesOff() { int i, j; - // Note: we send to driver here directly, because in this case we would free previously mapped channels - // and onTimer() wouldn't send them to driver anymore afterwards anyway - - // FIXME: the common midiparser/driver code doesn't really like getting called from various threads - // but we don't have an option here... i guess midiparser/driver code should be made thread-safe - // Turn off all active notes for (i = 0; i < 128; ++i) { for (j = 0; j < 16; ++j) { -- cgit v1.2.3 From d7fe98825154ede7beb0987ee3177ed46f1a3fa4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Jun 2010 11:14:38 +0000 Subject: Bugfix to dirty area handling to prevent creation of invalid rects svn-id: r50312 --- engines/m4/mads_views.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index dd5eb7a266..08b579cfb0 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -738,9 +738,12 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) --bounds.left; ++width; } - int right = bounds.left + width; + if (bounds.left < 0) bounds.left = 0; + else if (bounds.left > maxWidth) + bounds.left = maxWidth; + int right = bounds.left + width; if (right < 0) right = 0; if (right > maxWidth) @@ -752,6 +755,8 @@ void MadsDirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) if (bounds.top < 0) bounds.top = 0; + else if (bounds.top > maxHeight) + bounds.top = maxHeight; int bottom = bounds.top + height; if (bottom < 0) bottom = 0; -- cgit v1.2.3 From 18d9f917a0be68327ed3b06da588a5804f42e54f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 11:16:25 +0000 Subject: SCI: set _driver to 0 in MidiParser_SCI destructor to stop the MidiParser destructor call allNotesOff() which would affect all channels all the time - fixes sq1 ship flying away sound getting stopped when ladder falls down svn-id: r50313 --- engines/sci/sound/midiparser_sci.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 0bcafc8075..ebb2a172cc 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -65,6 +65,9 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : MidiParser_SCI::~MidiParser_SCI() { unloadMusic(); + // we do this, so that MidiParser won't be able to call his own ::allNotesOff() + // this one would affect all channels and we can't let that happen + _driver = 0; } void MidiParser_SCI::mainThreadBegin() { -- cgit v1.2.3 From 8eb206b6b97d172617902f92ea241af89dd22b5f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 26 Jun 2010 11:31:04 +0000 Subject: Bugfix to correctly handle transparency when rendering scaled sprites svn-id: r50314 --- engines/m4/graphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 55c16cb9e7..43df6e1b5f 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -547,7 +547,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, Common::Point des // Not a display pixel continue; - if (depth <= *depthP) + if ((*srcP != transparentColour) && (depth <= *depthP)) *destP = *srcP; ++destP; -- cgit v1.2.3 From be75870100e7e411b35f70cd96a851d7e50c20da Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 11:43:14 +0000 Subject: SCI: fixing deadlock possiblity on samples (sq3 deadlocked on door opening/where am i on me) svn-id: r50315 --- engines/sci/sound/music.h | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index a29b6edee2..ec9cbd8506 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -164,11 +164,13 @@ public: uint32 soundGetTempo() const { return _dwTempo; } bool soundIsActive(MusicEntry *pSnd) { + Common::StackLock lock(_mutex); assert(pSnd->pStreamAud != 0); return _pMixer->isSoundHandleActive(pSnd->hCurrentAud); } void updateAudioStreamTicker(MusicEntry *pSnd) { + Common::StackLock lock(_mutex); assert(pSnd->pStreamAud != 0); pSnd->ticker = (uint16)(_pMixer->getSoundElapsedTime(pSnd->hCurrentAud) * 0.06); } -- cgit v1.2.3 From e4153044d42ec976699389956441020cc52d9005 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 11:48:42 +0000 Subject: SCI: reverting r50315 - had the deadlock just again... svn-id: r50316 --- engines/sci/sound/music.h | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index ec9cbd8506..a29b6edee2 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -164,13 +164,11 @@ public: uint32 soundGetTempo() const { return _dwTempo; } bool soundIsActive(MusicEntry *pSnd) { - Common::StackLock lock(_mutex); assert(pSnd->pStreamAud != 0); return _pMixer->isSoundHandleActive(pSnd->hCurrentAud); } void updateAudioStreamTicker(MusicEntry *pSnd) { - Common::StackLock lock(_mutex); assert(pSnd->pStreamAud != 0); pSnd->ticker = (uint16)(_pMixer->getSoundElapsedTime(pSnd->hCurrentAud) * 0.06); } -- cgit v1.2.3 From cb5d9f6af5f2c44907215490dff0ace4b2b134c6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 12:04:15 +0000 Subject: SCI: added workaround for island of dr. brain elements puzzle svn-id: r50317 --- engines/sci/engine/vm.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d1fcbbd1f9..9565c82f16 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -198,10 +198,11 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room - { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally - { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // export 1 sub, but called locally + { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // export 1 sub, but called locally (when shooting at aliens) { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller { (SciGameId)0, -1, NULL, NULL, -1, 0, 0 } }; -- cgit v1.2.3 From a4f139c4d23845b622a2df427a375ca2953bbf66 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 12:20:40 +0000 Subject: SCI: adding more comment for export workaround (sq1) svn-id: r50318 --- engines/sci/engine/vm.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9565c82f16..485319a564 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -200,9 +200,8 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon - { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects - { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally - { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // export 1 sub, but called locally (when shooting at aliens) + { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller { (SciGameId)0, -1, NULL, NULL, -1, 0, 0 } }; -- cgit v1.2.3 From 783b71d58562c5a9a8eac23690e658931b086f1a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 13:28:22 +0000 Subject: Load the correct speech file pack for the intro of Rex Nebular svn-id: r50321 --- engines/m4/mads_menus.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index d7d9cf4150..0addfc57cb 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -309,6 +309,7 @@ void RexMainMenuView::handleAction(MadsGameAction action) { return; case SHOW_INTRO: + vm->_sound->loadDSRFile("act002.dsr"); vm->_viewManager->showAnimView("@rexopen"); break; -- cgit v1.2.3 From 691323f16e9661b50e0178046bd3b423bb79dc22 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 26 Jun 2010 15:55:40 +0000 Subject: Fix format string warning svn-id: r50325 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 485319a564..3d43ae3eb2 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -254,7 +254,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i } workaround++; } - error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %lx)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset); + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset); } return r[index]; } else -- cgit v1.2.3 From 79b5e7d77e26da5b27a2dd6d8527ca47fd873b09 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 16:21:28 +0000 Subject: SCI: fixing stupid torturegit conflict merge svn-id: r50329 --- engines/sci/engine/vm.cpp | 35 ++++++++++++++++++----------------- 1 file changed, 18 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 3d43ae3eb2..46aeca1a68 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -200,6 +200,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 25, "rm025", "doit", -1, 0, 0 }, // inside witch forest { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller @@ -218,17 +219,17 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (lastCall->localCallOffset != -1) { // if lastcall was actually a local call search back for a real call - Common::List::iterator callIterator = state->_executionStack.end(); - while (callIterator != state->_executionStack.begin()) { - callIterator--; - ExecStack loopCall = *callIterator; - if ((loopCall.selector != -1) || (loopCall.exportId != -1)) { - lastCall->selector = loopCall.selector; - lastCall->exportId = loopCall.exportId; - break; - } - } - } + Common::List::iterator callIterator = state->_executionStack.end(); + while (callIterator != state->_executionStack.begin()) { + callIterator--; + ExecStack loopCall = *callIterator; + if ((loopCall.selector != -1) || (loopCall.exportId != -1)) { + lastCall->selector = loopCall.selector; + lastCall->exportId = loopCall.exportId; + break; + } + } + } Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp); Common::String curMethodName; @@ -497,7 +498,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt reg_t newReg = argp[1]; const char *selectorName = g_sci->getKernel()->getSelectorName(selector).c_str(); warning("send_selector(): argc = %d while modifying variable selector " - "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", + "%x (%s) of object %04x:%04x (%s) from %04x:%04x to %04x:%04x", argc, selector, selectorName, PRINT_REG(send_obj), objectName, PRINT_REG(oldReg), PRINT_REG(newReg)); } @@ -695,7 +696,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { // Used for debugging Common::String debugMsg = kernelFunc.origName + Common::String::printf("[0x%x]", kernelFuncNum) + - Common::String::printf(", %d params: ", argc) + + Common::String::printf(", %d params: ", argc) + " ("; for (int i = 0; i < argc; i++) { @@ -896,13 +897,13 @@ void run_vm(EngineState *s, bool restoring) { } if (s->xs->sp < s->xs->fp) - error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", + error("run_vm(): stack underflow, sp: %04x:%04x, fp: %04x:%04x", PRINT_REG(*s->xs->sp), PRINT_REG(*s->xs->fp)); s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; if (s->xs->addr.pc.offset >= code_buf_size) - error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", + error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", s->xs->addr.pc.offset, code_buf_size); // Get opcode @@ -1107,8 +1108,8 @@ void run_vm(EngineState *s, bool restoring) { // (Print "foo") // Pointer to a string // (Print 420 5) // Reference to the fifth message in text resource 420 - // It works because in those games, the maximum resource number is 999, - // so any parameter value above that threshold must be a pointer. + // It works because in those games, the maximum resource number is 999, + // so any parameter value above that threshold must be a pointer. if (r_temp.segment && (s->r_acc == make_reg(0, 1000))) s->r_acc = make_reg(0, 1); else if (r_temp.segment && s->r_acc.segment) -- cgit v1.2.3 From 41aca44b037c129d837021eb0d0e91990e41856a Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 16:27:01 +0000 Subject: SCI: another commit for adding a workaround for islang room 300 again (although i already commited it already, stupid torturegit) svn-id: r50330 --- engines/sci/graphics/paint16.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 88fa467b3a..c2e8d2c5d0 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -536,6 +536,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { } break; default: + if ((g_sci->getGameId() == GID_ISLANDBRAIN) && (g_sci->getEngineState()->currentRoomNumber() == 300)) + break; // WORKAROUND: we are called there with an forwarded 0 as additional parameter (script bug) error("Unknown kDisplay argument %X", displayArg); break; } -- cgit v1.2.3 From 61295bcc4ef0426e772211fc0a5212796acab83f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 16:54:09 +0000 Subject: SCI: pseudo-adding workaround for kq5 room 25 witch forest svn-id: r50332 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 46aeca1a68..1778d6e339 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -200,7 +200,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon - { GID_KQ5, 25, "rm025", "doit", -1, 0, 0 }, // inside witch forest + { GID_KQ5, 25, "rm025", "doit", -1, 0, 0 }, // inside witch forest, where the walking rock is { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller -- cgit v1.2.3 From 554640ee8a41fdfd29bbb4a710b7eae4255a2d8e Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 26 Jun 2010 17:21:50 +0000 Subject: Fix saving while viewing the inventory in Riven and cleanup the save/load code. svn-id: r50333 --- engines/mohawk/resource.cpp | 2 +- engines/mohawk/riven.cpp | 1 + engines/mohawk/riven_saveload.cpp | 67 +++++++++++++++++++++++---------------- engines/mohawk/riven_saveload.h | 3 -- 4 files changed, 41 insertions(+), 32 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/resource.cpp b/engines/mohawk/resource.cpp index 62a857b90b..74efd6770f 100644 --- a/engines/mohawk/resource.cpp +++ b/engines/mohawk/resource.cpp @@ -103,7 +103,7 @@ void MohawkArchive::open(Common::SeekableReadStream *stream) { else debug (3, "Type[%02d]: Tag = \'%s\' ResTable Offset = %04x NameTable Offset = %04x", i, tag2str(_types[i].tag), _types[i].resource_table_offset, _types[i].name_table_offset); - //Resource Table + // Resource Table _mhk->seek(_rsrc.abs_offset + _types[i].resource_table_offset); _types[i].resTable.resources = _mhk->readUint16BE(); diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 1e7f006be1..44b7868373 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -29,6 +29,7 @@ #include "common/keyboard.h" #include "mohawk/graphics.h" +#include "mohawk/resource.h" #include "mohawk/riven.h" #include "mohawk/riven_external.h" #include "mohawk/riven_saveload.h" diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp index 3c989838da..d73b4ec0dc 100644 --- a/engines/mohawk/riven_saveload.cpp +++ b/engines/mohawk/riven_saveload.cpp @@ -23,6 +23,7 @@ * */ +#include "mohawk/resource.h" #include "mohawk/riven.h" #include "mohawk/riven_saveload.h" @@ -31,11 +32,9 @@ namespace Mohawk { RivenSaveLoad::RivenSaveLoad(MohawkEngine_Riven *vm, Common::SaveFileManager *saveFileMan) : _vm(vm), _saveFileMan(saveFileMan) { - _loadFile = new MohawkArchive(); } RivenSaveLoad::~RivenSaveLoad() { - delete _loadFile; } Common::StringArray RivenSaveLoad::generateSaveGameList() { @@ -63,7 +62,8 @@ static uint16 mapOldStackIDToNew(uint16 oldID) { case 8: return aspit; } - error ("Unknown old stack ID %d", oldID); + + error("Unknown old stack ID %d", oldID); return 0; } @@ -86,7 +86,8 @@ static uint16 mapNewStackIDToOld(uint16 newID) { case tspit: return 4; } - error ("Unknown new stack ID %d", newID); + + error("Unknown new stack ID %d", newID); return 0; } @@ -94,26 +95,28 @@ bool RivenSaveLoad::loadGame(Common::String filename) { if (_vm->getFeatures() & GF_DEMO) // Don't load games in the demo return false; - Common::InSaveFile *loadFile; - if (!(loadFile = _saveFileMan->openForLoading(filename.c_str()))) + Common::InSaveFile *loadFile = _saveFileMan->openForLoading(filename); + if (!loadFile) return false; - debug (0, "Loading game from \'%s\'", filename.c_str()); - _loadFile->open(loadFile); + debug(0, "Loading game from \'%s\'", filename.c_str()); + + MohawkArchive *mhk = new MohawkArchive(); + mhk->open(loadFile); // First, let's make sure we're using a saved game file from this version of Riven by checking the VERS resource - Common::SeekableReadStream *vers = _loadFile->getRawData(ID_VERS, 1); + Common::SeekableReadStream *vers = mhk->getRawData(ID_VERS, 1); uint32 saveGameVersion = vers->readUint32BE(); delete vers; if ((saveGameVersion == kCDSaveGameVersion && (_vm->getFeatures() & GF_DVD)) || (saveGameVersion == kDVDSaveGameVersion && !(_vm->getFeatures() & GF_DVD))) { - warning ("Incompatible saved game versions. No support for this yet."); - delete _loadFile; + warning("Incompatible saved game versions. No support for this yet."); + delete mhk; return false; } // Now, we'll read in the variable values. - Common::SeekableReadStream *vars = _loadFile->getRawData(ID_VARS, 1); + Common::SeekableReadStream *vars = mhk->getRawData(ID_VARS, 1); Common::Array rawVariables; while (!vars->eos()) { @@ -126,7 +129,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) { // Next, we set the variables based on the name found by the index in the VARS resource. // TODO: Merge with code in mohawk.cpp for loading names? - Common::SeekableReadStream *names = _loadFile->getRawData(ID_NAME, 1); + Common::SeekableReadStream *names = mhk->getRawData(ID_NAME, 1); uint16 namesCount = names->readUint16BE(); uint16 *stringOffsets = new uint16[namesCount]; @@ -151,9 +154,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) { c = (char)names->readByte(); } - // WORKAROUND: Some versions have two extra variables. However, the saves are - // still compatible with other saves of the same version. Are these used in the - // original interpreter anywhere? (They come from DVD v1.1) + // TODO: Some versions have two extra variables. However, the saves are + // still compatible with other saves of the same version (they come from DVD v1.1). + // There are used in the whark number puzzle. I thought jleftpos and jrightpos were + // for this purpose. if (name == "dropLeftStart" || name == "dropRightStart") continue; @@ -161,11 +165,11 @@ bool RivenSaveLoad::loadGame(Common::String filename) { *var = rawVariables[i]; - if (!scumm_stricmp(name.c_str(), "CurrentStackID")) + if (name.equalsIgnoreCase("CurrentStackID")) stackID = mapOldStackIDToNew(rawVariables[i]); - else if (!scumm_stricmp(name.c_str(), "CurrentCardID")) + else if (name.equalsIgnoreCase("CurrentCardID")) cardID = rawVariables[i]; - else if (!scumm_stricmp(name.c_str(), "ReturnStackID")) + else if (name.equalsIgnoreCase("ReturnStackID")) *var = mapOldStackIDToNew(rawVariables[i]); } @@ -179,7 +183,7 @@ bool RivenSaveLoad::loadGame(Common::String filename) { _vm->_zipModeData.clear(); // Finally, we load in zip mode data. - Common::SeekableReadStream *zips = _loadFile->getRawData(ID_ZIPS, 1); + Common::SeekableReadStream *zips = mhk->getRawData(ID_ZIPS, 1); uint16 zipsRecordCount = zips->readUint16BE(); for (uint16 i = 0; i < zipsRecordCount; i++) { ZipMode zip; @@ -189,10 +193,10 @@ bool RivenSaveLoad::loadGame(Common::String filename) { zip.id = zips->readUint16BE(); _vm->_zipModeData.push_back(zip); } + delete zips; + delete mhk; - delete _loadFile; - _loadFile = NULL; return true; } @@ -211,7 +215,14 @@ Common::MemoryWriteStreamDynamic *RivenSaveLoad::genVARSSection() { for (uint32 i = 0; i < _vm->getVarCount(); i++) { stream->writeUint32BE(0); // Unknown stream->writeUint32BE(0); // Unknown - stream->writeUint32BE(_vm->getGlobalVar(i)); + + // Remap returnstackid here because we don't actually want to change + // our internal returnstackid. + uint32 variable = _vm->getGlobalVar(i); + if (_vm->getGlobalVarName(i) == "returnstackid") + variable = mapNewStackIDToOld(variable); + + stream->writeUint32BE(variable); } return stream; @@ -257,17 +268,17 @@ bool RivenSaveLoad::saveGame(Common::String filename) { // Note, this code is still WIP. It works quite well for now. // Make sure we have the right extension - if (!filename.hasSuffix(".rvn") && !filename.hasSuffix(".RVN")) + if (!filename.matchString("*.rvn", true)) filename += ".rvn"; // Convert class variables to variable numbers *_vm->matchVarToString("currentstackid") = mapNewStackIDToOld(_vm->getCurStack()); *_vm->matchVarToString("currentcardid") = _vm->getCurCard(); - *_vm->matchVarToString("returnstackid") = mapNewStackIDToOld(*_vm->matchVarToString("returnstackid")); - Common::OutSaveFile *saveFile; - if (!(saveFile = _saveFileMan->openForSaving(filename.c_str()))) + Common::OutSaveFile *saveFile = _saveFileMan->openForSaving(filename); + if (!saveFile) return false; + debug (0, "Saving game to \'%s\'", filename.c_str()); Common::MemoryWriteStreamDynamic *versSection = genVERSSection(); @@ -392,7 +403,7 @@ bool RivenSaveLoad::saveGame(Common::String filename) { void RivenSaveLoad::deleteSave(Common::String saveName) { debug (0, "Deleting save file \'%s\'", saveName.c_str()); - _saveFileMan->removeSavefile(saveName.c_str()); + _saveFileMan->removeSavefile(saveName); } } // End of namespace Mohawk diff --git a/engines/mohawk/riven_saveload.h b/engines/mohawk/riven_saveload.h index c708f9d35d..9cc9bc3737 100644 --- a/engines/mohawk/riven_saveload.h +++ b/engines/mohawk/riven_saveload.h @@ -29,8 +29,6 @@ #include "common/savefile.h" #include "common/str.h" -#include "mohawk/resource.h" - namespace Mohawk { class MohawkEngine_Riven; @@ -53,7 +51,6 @@ public: private: MohawkEngine_Riven *_vm; Common::SaveFileManager *_saveFileMan; - MohawkArchive *_loadFile; Common::MemoryWriteStreamDynamic *genVERSSection(); Common::MemoryWriteStreamDynamic *genNAMESection(); -- cgit v1.2.3 From 9a0e2e9c461547b1a2d8bf32a3e7ba52853358f5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 17:37:28 +0000 Subject: SCI: add another unint temp workaround for kq5 - when playing harp for the harpies svn-id: r50334 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 1778d6e339..e69048dbc4 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -200,6 +200,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio { GID_KQ5, 25, "rm025", "doit", -1, 0, 0 }, // inside witch forest, where the walking rock is { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) -- cgit v1.2.3 From c2cb3bb79917c8a2993a3895deadae590107a1ec Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 26 Jun 2010 18:27:18 +0000 Subject: Add the page turning sound for the Riven journals and stub off the swipe transition used when turning pages. svn-id: r50336 --- engines/mohawk/graphics.cpp | 19 ++++++---------- engines/mohawk/riven_external.cpp | 46 ++++++++++++++++++++++++++++++++++----- 2 files changed, 47 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/graphics.cpp b/engines/mohawk/graphics.cpp index 00de6dba11..1974aec9c2 100644 --- a/engines/mohawk/graphics.cpp +++ b/engines/mohawk/graphics.cpp @@ -466,27 +466,22 @@ void RivenGraphics::runScheduledTransition() { // transitions were found by hacking scripts. switch (_scheduledTransition) { + case 0: // Swipe Left + case 1: // Swipe Right + case 2: // Swipe Up + case 3: // Swipe Down case 12: // Pan Left - warning ("STUB: Pan left"); - break; case 13: // Pan Right - warning ("STUB: Pan right"); - break; case 14: // Pan Up - warning ("STUB: Pan up"); - break; case 15: // Pan Down - warning ("STUB: Pan down"); - break; case 16: // Dissolve case 17: // Dissolve (tspit CARD 155) - warning ("STUB: Dissolve"); break; default: - if (_scheduledTransition < 12) - error ("Found unused transition %d", _scheduledTransition); + if (_scheduledTransition >= 4 && _scheduledTransition <= 11) + error("Found unused transition %d", _scheduledTransition); else - error ("Found unknown transition %d", _scheduledTransition); + error("Found unknown transition %d", _scheduledTransition); } // For now, just copy the image to screen without doing any transition. diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 5b5163dbb3..24466305fe 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -284,9 +284,14 @@ void RivenExternal::xaatrusbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + if (_vm->getFeatures() & GF_DEMO) + _vm->_sound->playSound(4, false); + else + _vm->_sound->playSound(3, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -299,9 +304,14 @@ void RivenExternal::xaatrusbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + if (_vm->getFeatures() & GF_DEMO) + _vm->_sound->playSound(5, false); + else + _vm->_sound->playSound(4, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } @@ -349,9 +359,11 @@ void RivenExternal::xacathbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(5, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(3); _vm->_gfx->updateScreen(); } @@ -364,9 +376,11 @@ void RivenExternal::xacathbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(6, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(2); _vm->_gfx->updateScreen(); } @@ -380,12 +394,20 @@ void RivenExternal::xtrapbookback(uint16 argc, uint16 *argv) { void RivenExternal::xatrapbookclose(uint16 argc, uint16 *argv) { // Close the trap book *_vm->matchVarToString("atrap") = 0; + + // Play the page turning sound + _vm->_sound->playSound(8, false); + _vm->refreshCard(); } void RivenExternal::xatrapbookopen(uint16 argc, uint16 *argv) { // Open the trap book *_vm->matchVarToString("atrap") = 1; + + // Play the page turning sound + _vm->_sound->playSound(9, false); + _vm->refreshCard(); } @@ -437,7 +459,11 @@ void RivenExternal::xblabbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; + // Play the page turning sound + _vm->_sound->playSound(22, false); + // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -450,7 +476,11 @@ void RivenExternal::xblabbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; + // Play the page turning sound + _vm->_sound->playSound(23, false); + // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } @@ -1270,9 +1300,11 @@ void RivenExternal::xogehnbookprevpage(uint16 argc, uint16 *argv) { return; (*page)--; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(12, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(1); _vm->_gfx->updateScreen(); } @@ -1285,9 +1317,11 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) { return; (*page)++; - // TODO: Play the page turning sound + // Play the page turning sound + _vm->_sound->playSound(13, false); // Now update the screen :) + _vm->_gfx->scheduleTransition(0); _vm->_gfx->updateScreen(); } -- cgit v1.2.3 From 2b9f4e5068081b3b172ac859648555f1f9bdecdb Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 26 Jun 2010 18:44:32 +0000 Subject: Gehn's cage should be closed initially, so initialize ocage to 1. svn-id: r50337 --- engines/mohawk/riven_vars.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mohawk/riven_vars.cpp b/engines/mohawk/riven_vars.cpp index 163626203a..b6d2dff315 100644 --- a/engines/mohawk/riven_vars.cpp +++ b/engines/mohawk/riven_vars.cpp @@ -320,6 +320,7 @@ void MohawkEngine_Riven::initVars() { *matchVarToString("waterenabled") = 1; *matchVarToString("ogehnpage") = 1; *matchVarToString("bblrsw") = 1; + *matchVarToString("ocage") = 1; // Randomize the telescope combination uint32 *teleCombo = matchVarToString("tcorrectorder"); -- cgit v1.2.3 From e5e90eb8a8078d108d9985e6303b3975f1b6da55 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sat, 26 Jun 2010 19:09:45 +0000 Subject: Add a debug console command to Riven for displaying combinations to puzzles. svn-id: r50338 --- engines/mohawk/console.cpp | 29 +++++++++++++++++++++++++++++ engines/mohawk/console.h | 1 + engines/mohawk/riven_external.cpp | 2 +- engines/mohawk/riven_external.h | 1 + 4 files changed, 32 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index 149b6b6eba..abdcf42dc0 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -28,6 +28,7 @@ #include "mohawk/myst_scripts.h" #include "mohawk/graphics.h" #include "mohawk/riven.h" +#include "mohawk/riven_external.h" #include "mohawk/livingbooks.h" #include "mohawk/sound.h" #include "mohawk/video.h" @@ -307,6 +308,7 @@ RivenConsole::RivenConsole(MohawkEngine_Riven *vm) : GUI::Debugger(), _vm(vm) { DCmd_Register("dumpScript", WRAP_METHOD(RivenConsole, Cmd_DumpScript)); DCmd_Register("listZipCards", WRAP_METHOD(RivenConsole, Cmd_ListZipCards)); DCmd_Register("getRMAP", WRAP_METHOD(RivenConsole, Cmd_GetRMAP)); + DCmd_Register("combos", WRAP_METHOD(RivenConsole, Cmd_Combos)); } RivenConsole::~RivenConsole() { @@ -608,6 +610,33 @@ bool RivenConsole::Cmd_GetRMAP(int argc, const char **argv) { return true; } +bool RivenConsole::Cmd_Combos(int argc, const char **argv) { + // In the vain of SCUMM's 'drafts' command, this command will list + // out all combinations needed in Riven, decoded from the variables. + // You'll need to look up the Rebel Tunnel puzzle on your own; the + // solution is constant. + + uint32 teleCombo = *_vm->matchVarToString("tcorrectorder"); + uint32 prisonCombo = *_vm->matchVarToString("pcorrectorder"); + uint32 domeCombo = *_vm->matchVarToString("adomecombo"); + + DebugPrintf("Telescope Combo:\n "); + for (int i = 0; i < 5; i++) + DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(teleCombo, i)); + + DebugPrintf("\nPrison Combo:\n "); + for (int i = 0; i < 5; i++) + DebugPrintf("%d ", _vm->_externalScriptHandler->getComboDigit(prisonCombo, i)); + + DebugPrintf("\nDome Combo:\n "); + for (int i = 1; i <= 25; i++) + if (domeCombo & (1 << (25 - i))) + DebugPrintf("%d ", i); + + DebugPrintf("\n"); + return true; +} + LivingBooksConsole::LivingBooksConsole(MohawkEngine_LivingBooks *vm) : GUI::Debugger(), _vm(vm) { DCmd_Register("playSound", WRAP_METHOD(LivingBooksConsole, Cmd_PlaySound)); DCmd_Register("stopSound", WRAP_METHOD(LivingBooksConsole, Cmd_StopSound)); diff --git a/engines/mohawk/console.h b/engines/mohawk/console.h index 9a30d46225..1806c61027 100644 --- a/engines/mohawk/console.h +++ b/engines/mohawk/console.h @@ -88,6 +88,7 @@ private: bool Cmd_DumpScript(int argc, const char **argv); bool Cmd_ListZipCards(int argc, const char **argv); bool Cmd_GetRMAP(int argc, const char **argv); + bool Cmd_Combos(int argc, const char **argv); }; class LivingBooksConsole : public GUI::Debugger { diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 24466305fe..67d621a54c 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -1325,7 +1325,7 @@ void RivenExternal::xogehnbooknextpage(uint16 argc, uint16 *argv) { _vm->_gfx->updateScreen(); } -static uint16 getComboDigit(uint32 correctCombo, uint32 digit) { +uint16 RivenExternal::getComboDigit(uint32 correctCombo, uint32 digit) { static const uint32 powers[] = { 100000, 10000, 1000, 100, 10, 1 }; return (correctCombo % powers[digit]) / powers[digit + 1]; } diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 14bb51340c..bdf3fa01bc 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -38,6 +38,7 @@ public: ~RivenExternal(); void runCommand(uint16 argc, uint16 *argv); + uint16 getComboDigit(uint32 correctCombo, uint32 digit); private: MohawkEngine_Riven *_vm; -- cgit v1.2.3 From 710fc6c71e21bb0b3b9f7f89cdaf9445450df2e2 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 19:55:49 +0000 Subject: SCI: do boundary checking when loading sci1 sounds and mixing them together. The final end credits song (resource 699) in kq5 has some channels with invalid offsets, crashing ScummVM before svn-id: r50339 --- engines/sci/resource.h | 1 + engines/sci/resource_audio.cpp | 52 +++++++++++++++++++++++------------- engines/sci/sound/midiparser_sci.cpp | 21 ++++++++------- 3 files changed, 47 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/resource.h b/engines/sci/resource.h index 584c61dbd6..a13781b157 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -492,6 +492,7 @@ public: uint16 prio; uint16 size; byte *data; + uint16 curPos; long time; byte prev; }; diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp index 8629fecfa7..13aa81cb24 100644 --- a/engines/sci/resource_audio.cpp +++ b/engines/sci/resource_audio.cpp @@ -480,8 +480,8 @@ int ResourceManager::getAudioLanguage() const { return (_audioMapSCI1 ? _audioMapSCI1->_volumeNumber : 0); } -SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { - Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resNumber), true); +SoundResource::SoundResource(uint32 resourceNr, ResourceManager *resMan, SciVersion soundVersion) : _resMan(resMan), _soundVersion(soundVersion) { + Resource *resource = _resMan->findResource(ResourceId(kResourceTypeSound, resourceNr), true); int trackNr, channelNr; if (!resource) return; @@ -554,6 +554,9 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi } _tracks = new Track[_trackCount]; data = resource->data; + + byte channelCount; + for (trackNr = 0; trackNr < _trackCount; trackNr++) { // Track info starts with track type:BYTE // Then the channel information gets appended Unknown:WORD, ChannelOffset:WORD, ChannelSize:WORD @@ -563,34 +566,47 @@ SoundResource::SoundResource(uint32 resNumber, ResourceManager *resMan, SciVersi _tracks[trackNr].type = *data++; // Counting # of channels used data2 = data; - _tracks[trackNr].channelCount = 0; + channelCount = 0; while (*data2 != 0xFF) { data2 += 6; + channelCount++; _tracks[trackNr].channelCount++; } - _tracks[trackNr].channels = new Channel[_tracks[trackNr].channelCount]; + _tracks[trackNr].channels = new Channel[channelCount]; + _tracks[trackNr].channelCount = 0; _tracks[trackNr].digitalChannelNr = -1; // No digital sound associated _tracks[trackNr].digitalSampleRate = 0; _tracks[trackNr].digitalSampleSize = 0; _tracks[trackNr].digitalSampleStart = 0; _tracks[trackNr].digitalSampleEnd = 0; if (_tracks[trackNr].type != 0xF0) { // Digital track marker - not supported currently - for (channelNr = 0; channelNr < _tracks[trackNr].channelCount; channelNr++) { + channelNr = 0; + while (channelCount--) { channel = &_tracks[trackNr].channels[channelNr]; channel->prio = READ_LE_UINT16(data); - channel->data = resource->data + READ_LE_UINT16(data + 2) + 2; - channel->size = READ_LE_UINT16(data + 4) - 2; // Not counting channel header - channel->number = *(channel->data - 2); - channel->poly = *(channel->data - 1); - channel->time = channel->prev = 0; - if (channel->number == 0xFE) { // Digital channel - _tracks[trackNr].digitalChannelNr = channelNr; - _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); - _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); - _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); - _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); - channel->data += 8; // Skip over header - channel->size -= 8; + uint dataOffset = READ_LE_UINT16(data + 2); + if (dataOffset < resource->size) { + channel->data = resource->data + dataOffset; + channel->size = READ_LE_UINT16(data + 4); + channel->curPos = 0; + channel->number = *channel->data; + channel->poly = *(channel->data + 1); + channel->time = channel->prev = 0; + channel->data += 2; // skip over header + channel->size -= 2; // remove header size + if (channel->number == 0xFE) { // Digital channel + _tracks[trackNr].digitalChannelNr = channelNr; + _tracks[trackNr].digitalSampleRate = READ_LE_UINT16(channel->data); + _tracks[trackNr].digitalSampleSize = READ_LE_UINT16(channel->data + 2); + _tracks[trackNr].digitalSampleStart = READ_LE_UINT16(channel->data + 4); + _tracks[trackNr].digitalSampleEnd = READ_LE_UINT16(channel->data + 6); + channel->data += 8; // Skip over header + channel->size -= 8; + } + _tracks[trackNr].channelCount++; + channelNr++; + } else { + warning("Invalid offset inside sound resource %d: track %d, channel %d", resourceNr, trackNr, channelNr); } data += 6; } diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index ebb2a172cc..5f361c02ec 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -422,7 +422,10 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) { for (int i = 0; i < _track->channelCount; i++) { if (_track->channels[i].time == -1) // channel ended continue; - next = *_track->channels[i].data; // when the next event should occur + SoundResource::Channel *curChannel = &_track->channels[i]; + if (curChannel->curPos >= curChannel->size) + continue; + next = curChannel->data[curChannel->curPos]; // when the next event should occur if (next == 0xF8) // 0xF8 means 240 ticks delay next = 240; next += _track->channels[i].time; @@ -449,21 +452,21 @@ byte *MidiParser_SCI::midiMixChannels() { byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data _mixedData = outData; long ticker = 0; - byte curr, curDelta; + byte channelNr, curDelta; byte command = 0, par1, global_prev = 0; long new_delta; SoundResource::Channel *channel; - while ((curr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel - channel = &_track->channels[curr]; - curDelta = *channel->data++; + while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel + channel = &_track->channels[channelNr]; + curDelta = channel->data[channel->curPos++]; channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur if (curDelta == 0xF8) continue; new_delta = channel->time - ticker; ticker += new_delta; - command = *channel->data++; + command = channel->data[channel->curPos++]; if (command != kEndOfTrack) { debugC(4, kDebugLevelSound, "\nDELTA "); // Write delta @@ -481,7 +484,7 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = command; debugC(4, kDebugLevelSound, "%02X ", command); do { - par1 = *channel->data++; + par1 = channel->data[channel->curPos++]; *outData++ = par1; // out } while (par1 != 0xF7); break; @@ -492,7 +495,7 @@ byte *MidiParser_SCI::midiMixChannels() { break; default: // MIDI command if (command & 0x80) { - par1 = *channel->data++; + par1 = channel->data[channel->curPos++]; } else {// running status par1 = command; command = channel->prev; @@ -506,7 +509,7 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = command; // out command *outData++ = par1;// pout par1 if (nMidiParams[(command >> 4) - 8] == 2) - *outData++ = *channel->data++; // out par2 + *outData++ = channel->data[channel->curPos++]; // out par2 channel->prev = command; global_prev = command; }// switch(command) -- cgit v1.2.3 From caded4f892905eb8821ba9431ec2119aab6facd9 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 26 Jun 2010 20:28:42 +0000 Subject: Improve readability svn-id: r50340 --- engines/sci/graphics/animate.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 08ff3bfc80..2f1e1e726c 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -331,7 +331,8 @@ void GfxAnimate::update() { writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0); } signal &= 0xFFFF ^ kSignalForceUpdate; - signal &= signal & kSignalViewUpdated ? 0xFFFF ^ (kSignalViewUpdated | kSignalNoUpdate) : 0xFFFF; + if (signal & kSignalViewUpdated) + signal &= ~(kSignalViewUpdated | kSignalNoUpdate); } else if (signal & kSignalStopUpdate) { signal = (signal & (0xFFFF ^ kSignalStopUpdate)) | kSignalNoUpdate; } -- cgit v1.2.3 From 1ca0cdc8b105d4b6f033e1c0b8b0cdee996903fd Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 20:47:28 +0000 Subject: SCI: fix warning svn-id: r50341 --- engines/sci/sound/midiparser_sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 5f361c02ec..46459522a3 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -522,7 +522,7 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = 0x00; *outData++ = 0x00; - for (int channelNr = 0; channelNr < _track->channelCount; channelNr++) + for (channelNr = 0; channelNr < _track->channelCount; channelNr++) _track->channels[channelNr].data = dataPtr[channelNr]; delete[] dataPtr; -- cgit v1.2.3 From af755b0b3d732a0976b4c008b849ca907421d6eb Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Sat, 26 Jun 2010 21:36:25 +0000 Subject: Further improve readability svn-id: r50345 --- engines/sci/graphics/animate.cpp | 17 +++++++++-------- 1 file changed, 9 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 2f1e1e726c..491553cebe 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -290,11 +290,11 @@ void GfxAnimate::fill(byte &old_picNotValid) { || (!(signal & kSignalHidden) && signal & kSignalRemoveView) || (signal & kSignalAlwaysUpdate)) old_picNotValid++; - signal &= 0xFFFF ^ kSignalStopUpdate; + signal &= ~kSignalStopUpdate; } else { if (signal & kSignalStopUpdate || signal & kSignalAlwaysUpdate) old_picNotValid++; - signal &= 0xFFFF ^ kSignalForceUpdate; + signal &= ~kSignalForceUpdate; } listEntry->signal = signal; @@ -330,11 +330,12 @@ void GfxAnimate::update() { } writeSelectorValue(_s->_segMan, curObject, SELECTOR(underBits), 0); } - signal &= 0xFFFF ^ kSignalForceUpdate; + signal &= ~kSignalForceUpdate; if (signal & kSignalViewUpdated) signal &= ~(kSignalViewUpdated | kSignalNoUpdate); } else if (signal & kSignalStopUpdate) { - signal = (signal & (0xFFFF ^ kSignalStopUpdate)) | kSignalNoUpdate; + signal &= ~kSignalStopUpdate; + signal |= kSignalNoUpdate; } listEntry->signal = signal; listIterator--; @@ -352,7 +353,7 @@ void GfxAnimate::update() { _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); listEntry->showBitsFlag = true; - signal &= 0xFFFF ^ (kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); + signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); if ((signal & kSignalIgnoreActor) == 0) { rect = listEntry->celRect; rect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); @@ -374,7 +375,7 @@ void GfxAnimate::update() { if (signal & kSignalHidden) { signal |= kSignalRemoveView; } else { - signal &= 0xFFFF ^ kSignalRemoveView; + signal &= ~kSignalRemoveView; if (signal & kSignalIgnoreActor) bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); else @@ -398,7 +399,7 @@ void GfxAnimate::update() { _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); listEntry->showBitsFlag = true; - if ((signal & kSignalIgnoreActor) == 0) { + if (!(signal & kSignalIgnoreActor)) { rect = listEntry->celRect; rect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); @@ -434,7 +435,7 @@ void GfxAnimate::drawCels() { listEntry->showBitsFlag = true; if (signal & kSignalRemoveView) { - signal &= 0xFFFF ^ kSignalRemoveView; + signal &= ~kSignalRemoveView; } listEntry->signal = signal; -- cgit v1.2.3 From 09b4f7cbed4f258a00822f2b135df475f6e1b398 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sat, 26 Jun 2010 21:55:52 +0000 Subject: Define WIN32_LEAN_AND_MEAN before including windows.h. This will cause our code to include less functionality, but might on the other hand fasten up the compilation. svn-id: r50346 --- engines/engine.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/engine.cpp b/engines/engine.cpp index 0f42cd493d..84fc0bbe4e 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -23,6 +23,7 @@ */ #if defined(WIN32) && !defined(_WIN32_WCE) && !defined(__SYMBIAN32__) +#define WIN32_LEAN_AND_MEAN #include #include // winnt.h defines ARRAYSIZE, but we want our own one... -- cgit v1.2.3 From 25cb3092f4f2ee84fa26e0f31f81bccb861efe39 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 26 Jun 2010 21:57:13 +0000 Subject: SCI: added comment to vm-workaround table svn-id: r50347 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e69048dbc4..c4c77e16de 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -193,6 +193,7 @@ struct UninitializedReadWorkaround { uint16 newValue; }; +// gameID, scriptNr, object-name, method-name, call,index,replace static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_LAURABOW2, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu -- cgit v1.2.3 From e2026f4a26c648482b1823938c2d4a496ed56375 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 22:48:47 +0000 Subject: Zero out the memory pointer of a hunk when freeing it svn-id: r50351 --- engines/sci/engine/segment.h | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 253d94cc53..58f016a654 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -669,7 +669,10 @@ struct HunkTable : public Table { virtual void freeEntry(int idx) { Table::freeEntry(idx); + if (!_table[idx].mem) + warning("Attempt to free an already freed hunk"); free(_table[idx].mem); + _table[idx].mem = 0; } virtual void saveLoadWithSerializer(Common::Serializer &ser); -- cgit v1.2.3 From b2f2c48c7e31d322399997f30d4e32369806f60e Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 22:50:39 +0000 Subject: Added a workaround for broken script 377 in Castle of Dr. Brain, room 320. It constantly tries to free the saved area rectangle (underbits) underneath the popup window svn-id: r50352 --- engines/sci/engine/kscripts.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index de8710bd83..ed2ce6ed9e 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -80,6 +80,14 @@ reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); reg_t resnr = argv[1]; + // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain. + // Script 377 tries to free the hunk memory allocated for the saved area + // (underbits) beneath the pop up window, which results in having the + // window stay on screen even when it's closed. Ignore this request here. + if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN && + s->currentRoomNumber() == 320) + return s->r_acc; + if (restype == kResourceTypeMemory) s->_segMan->freeHunkEntry(resnr); -- cgit v1.2.3 From 3dcebcb1bcf69bafc61ca4466b01237000533656 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 23:01:22 +0000 Subject: Shuffled some functions around. Also, the filename in kResCheck can never be bigger than 9 characters, when dealing with VMD videos svn-id: r50355 --- engines/sci/engine/kscripts.cpp | 54 ++++++++++++++++++++--------------------- 1 file changed, 27 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index ed2ce6ed9e..4e6be15760 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -46,6 +46,32 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) { return make_reg(0, ((restype << 11) | resnr)); // Return the resource identifier as handle } +// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' +reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { + if (argc >= 2) { + ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); + reg_t resnr = argv[1]; + + // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain. + // Script 377 tries to free the hunk memory allocated for the saved area + // (underbits) beneath the pop up window, which results in having the + // window stay on screen even when it's closed. Ignore this request here. + if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN && + s->currentRoomNumber() == 320) + return s->r_acc; + + if (restype == kResourceTypeMemory) + s->_segMan->freeHunkEntry(resnr); + + if (argc > 2) + warning("kUnload called with more than 2 parameters (%d)", argc); + } else { + warning("kUnload called with less than 2 parameters (%d) - ignoring", argc); + } + + return s->r_acc; +} + reg_t kLock(EngineState *s, int argc, reg_t *argv) { int state = argc > 2 ? argv[2].toUint16() : 1; ResourceType type = (ResourceType)(argv[0].toUint16() & 0x7f); @@ -74,38 +100,12 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } -// Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' -reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { - if (argc >= 2) { - ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); - reg_t resnr = argv[1]; - - // WORKAROUND for a broken script in room 320 in Castle of Dr. Brain. - // Script 377 tries to free the hunk memory allocated for the saved area - // (underbits) beneath the pop up window, which results in having the - // window stay on screen even when it's closed. Ignore this request here. - if (restype == kResourceTypeMemory && g_sci->getGameId() == GID_CASTLEBRAIN && - s->currentRoomNumber() == 320) - return s->r_acc; - - if (restype == kResourceTypeMemory) - s->_segMan->freeHunkEntry(resnr); - - if (argc > 2) - warning("kUnload called with more than 2 parameters (%d)", argc); - } else { - warning("kUnload called with less than 2 parameters (%d) - ignoring", argc); - } - - return s->r_acc; -} - reg_t kResCheck(EngineState *s, int argc, reg_t *argv) { Resource *res = NULL; ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); if (restype == kResourceTypeVMD) { - char fileName[50]; + char fileName[10]; sprintf(fileName, "%d.vmd", argv[1].toUint16()); return make_reg(0, Common::File::exists(fileName)); } -- cgit v1.2.3 From 3cf0114164aa07cdd2ae557ea49cf59a31ea5f67 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 23:13:05 +0000 Subject: Moved script_instantiate_sci0() inside the segment manager, and renamed it to scriptInitialiseObjectsSci0() svn-id: r50357 --- engines/sci/engine/script.cpp | 128 +++++++++++++++++++-------------------- engines/sci/engine/seg_manager.h | 1 + 2 files changed, 65 insertions(+), 64 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 8f3792552f..5916428432 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -176,61 +176,8 @@ void SegManager::scriptInitialiseLocals(SegmentId segmentId) { } } -void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { +void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart;; - uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; - seeker += entrySize; // skip first entry - seeker += 4; // skip header - - while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) { // -info- selector - int classpos = seeker - scr->_buf; - int species = READ_SCI11ENDIAN_UINT16(seeker + 10); - - if (species < 0 || species >= (int)_classTable.size()) { - error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d", - species, species, _classTable.size(), scr->_nr); - return; - } - - setClassOffset(species, make_reg(seg, classpos)); - } - seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; - } - - seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; - while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - reg_t reg = make_reg(seg, seeker - scr->_buf); - Object *obj = scr->scriptObjInit(reg); - - // Copy base from species class, as we need its selector IDs - obj->setSuperClassSelector( - getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); - - // If object is instance, get -propDict- from class and set it for this object - // This is needed for ::isMemberOf() to work. - // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, talk-clicks on the robot will act like - // clicking on ego - if (!obj->isClass()) { - reg_t classObject = obj->getSuperClassSelector(); - Object *classObj = getObject(classObject); - obj->setPropDictSelector(classObj->getPropDictSelector()); - } - - // Set the -classScript- selector to the script number. - // FIXME: As this selector is filled in at run-time, it is likely - // that it is supposed to hold a pointer. The Obj::isKindOf method - // uses this selector together with -propDict- to compare classes. - // For the purpose of Obj::isKindOf, using the script number appears - // to be sufficient. - obj->setClassScriptSelector(make_reg(0, scr->_nr)); - - seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; - } -} - -void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { int objType; reg_t addr; bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); @@ -250,7 +197,7 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { objLength = scr->getHeap(curOffset + 2); curOffset += 4; // skip header - addr = make_reg(segmentId, curOffset);; + addr = make_reg(seg, curOffset);; switch (objType) { case SCI_OBJ_OBJECT: @@ -259,24 +206,24 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { int classpos = curOffset + 8; // SCRIPT_OBJECT_MAGIC_OFFSET int species = scr->getHeap(classpos); - if (species == (int)segMan->classTableSize()) { + if (species == (int)classTableSize()) { // Happens in the LSL2 demo warning("Applying workaround for an off-by-one invalid species access"); - segMan->resizeClassTable(segMan->classTableSize() + 1); - } else if (species < 0 || species > (int)segMan->classTableSize()) { + resizeClassTable(classTableSize() + 1); + } else if (species < 0 || species > (int)classTableSize()) { error("Invalid species %d(0x%x) not in interval " "[0,%d) while instantiating script at segment %d\n", - species, species, segMan->classTableSize(), - segmentId); + species, species, classTableSize(), + seg); return; } - segMan->setClassOffset(species, make_reg(segmentId, classpos)); + setClassOffset(species, make_reg(seg, classpos)); } else if (pass == 1) { Object *obj = scr->scriptObjInit(addr); - obj->initSpecies(segMan, addr); + obj->initSpecies(this, addr); - if (!obj->initBaseObject(segMan, addr)) { + if (!obj->initBaseObject(this, addr)) { error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); //scr->scriptObjRemove(addr); } @@ -290,7 +237,60 @@ void script_instantiate_sci0(Script *scr, int segmentId, SegManager *segMan) { curOffset += objLength - 4; } while (objType != 0 && curOffset < scr->getScriptSize() - 2); } // for +} + +void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { + Script *scr = getScript(seg); + const byte *seeker = scr->_heapStart;; + uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + seeker += entrySize; // skip first entry + seeker += 4; // skip header + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { + if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) { // -info- selector + int classpos = seeker - scr->_buf; + int species = READ_SCI11ENDIAN_UINT16(seeker + 10); + + if (species < 0 || species >= (int)_classTable.size()) { + error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d", + species, species, _classTable.size(), scr->_nr); + return; + } + + setClassOffset(species, make_reg(seg, classpos)); + } + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + } + + seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { + reg_t reg = make_reg(seg, seeker - scr->_buf); + Object *obj = scr->scriptObjInit(reg); + + // Copy base from species class, as we need its selector IDs + obj->setSuperClassSelector( + getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); + + // If object is instance, get -propDict- from class and set it for this object + // This is needed for ::isMemberOf() to work. + // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, talk-clicks on the robot will act like + // clicking on ego + if (!obj->isClass()) { + reg_t classObject = obj->getSuperClassSelector(); + Object *classObj = getObject(classObject); + obj->setPropDictSelector(classObj->getPropDictSelector()); + } + + // Set the -classScript- selector to the script number. + // FIXME: As this selector is filled in at run-time, it is likely + // that it is supposed to hold a pointer. The Obj::isKindOf method + // uses this selector together with -propDict- to compare classes. + // For the purpose of Obj::isKindOf, using the script number appears + // to be sufficient. + obj->setClassScriptSelector(make_reg(0, scr->_nr)); + + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; + } } int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) { @@ -315,7 +315,7 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNu segMan->scriptInitialiseObjectsSci11(segmentId); scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); } else { - script_instantiate_sci0(scr, segmentId, segMan); + segMan->scriptInitialiseObjectsSci0(segmentId); byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); if (relocationBlock) scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 990836992c..037f3f0819 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -426,6 +426,7 @@ public: */ reg_t findObjectByName(const Common::String &name, int index = -1); + void scriptInitialiseObjectsSci0(SegmentId seg); void scriptInitialiseObjectsSci11(SegmentId seg); uint32 classTableSize() { return _classTable.size(); } -- cgit v1.2.3 From 7a14846bdd99dc81a70baa43836282af47205e16 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sat, 26 Jun 2010 23:48:27 +0000 Subject: Removed the misleading getHeap() function (only valid for SCI0-SCI1), plus removed some unused defines svn-id: r50358 --- engines/sci/engine/script.cpp | 17 +++++++---------- engines/sci/engine/segment.cpp | 6 ------ engines/sci/engine/segment.h | 8 -------- engines/sci/engine/vm.h | 5 ----- 4 files changed, 7 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 5916428432..c548ce5cdc 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -191,11 +191,11 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { uint16 curOffset = oldScriptHeader ? 2 : 0; do { - objType = scr->getHeap(curOffset); + objType = READ_SCI11ENDIAN_UINT16(scr->_buf + curOffset); if (!objType) break; - objLength = scr->getHeap(curOffset + 2); + objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + curOffset + 2); curOffset += 4; // skip header addr = make_reg(seg, curOffset);; @@ -204,7 +204,7 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { case SCI_OBJ_CLASS: if (pass == 0 && objType == SCI_OBJ_CLASS) { int classpos = curOffset + 8; // SCRIPT_OBJECT_MAGIC_OFFSET - int species = scr->getHeap(classpos); + int species = READ_SCI11ENDIAN_UINT16(scr->_buf + classpos); if (species == (int)classTableSize()) { // Happens in the LSL2 demo @@ -335,19 +335,16 @@ void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) do { reg.offset += objLength; // Step over the last checked object - objType = scr->getHeap(reg.offset); + objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset); if (!objType) break; - objLength = scr->getHeap(reg.offset + 2); // use SEG_UGET_HEAP ?? + objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); reg.offset += 4; // Step over header if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? - int superclass; - - reg.offset -= SCRIPT_OBJECT_MAGIC_OFFSET; - - superclass = scr->getHeap(reg.offset + SCRIPT_SUPERCLASS_OFFSET); // Get superclass... + reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + int superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); if (superclass >= 0) { int superclass_script = segMan->getClass(superclass).script; diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 0a39d950b0..4524241110 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -417,12 +417,6 @@ void Script::mcpyInOut(int dst, const void *src, size_t n) { } } -int16 Script::getHeap(uint16 offset) const { - assert(offset + 1 < (int)_bufSize); - return READ_SCI11ENDIAN_UINT16(_buf + offset); -// return (_buf[offset] | (_buf[offset+1]) << 8); -} - SegmentRef SegmentObj::dereference(reg_t pointer) { error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", PRINT_REG(pointer)); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 58f016a654..24d27e367f 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -501,14 +501,6 @@ public: */ void mcpyInOut(int dst, const void *src, size_t n); - - /** - * Retrieves a 16 bit value from within a script's heap representation. - * @param offset offset to read from - * @return the value read from the specified location - */ - int16 getHeap(uint16 offset) const; - /** * Finds the pointer where a block of a specific type starts from */ diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index d747ddd113..0938520525 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -49,11 +49,6 @@ class ResourceManager; /** Offset of this identifier */ #define SCRIPT_OBJECT_MAGIC_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? -8 : 0) -/** Script-relative offset of the species ID */ -#define SCRIPT_SPECIES_OFFSET 8 -8 - -#define SCRIPT_SUPERCLASS_OFFSET (getSciVersion() < SCI_VERSION_1_1 ? 10 -8 : 12) - /** Stack pointer value: Use predecessor's value */ #define CALL_SP_CARRY NULL -- cgit v1.2.3 From daab502028761f8da7a4f75a7bbd265f8127892d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 00:08:00 +0000 Subject: Cleanup svn-id: r50359 --- engines/sci/engine/script.cpp | 24 ++++++++++++------------ engines/sci/engine/segment.cpp | 6 ++---- 2 files changed, 14 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index c548ce5cdc..f26a2e53af 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -178,9 +178,10 @@ void SegManager::scriptInitialiseLocals(SegmentId segmentId) { void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { Script *scr = getScript(seg); + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + const byte *seeker = 0; int objType; reg_t addr; - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); // The script is initialized in 2 passes. // Pass 1: creates a lookup table of all used classes @@ -188,23 +189,22 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { for (uint16 pass = 0; pass <= 1; pass++) { uint16 objLength = 0; - uint16 curOffset = oldScriptHeader ? 2 : 0; + seeker = scr->_buf + (oldScriptHeader ? 2 : 0); do { - objType = READ_SCI11ENDIAN_UINT16(scr->_buf + curOffset); + objType = READ_SCI11ENDIAN_UINT16(seeker); if (!objType) break; - objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + curOffset + 2); - curOffset += 4; // skip header - addr = make_reg(seg, curOffset);; + objLength = READ_SCI11ENDIAN_UINT16(seeker + 2); + seeker += 4; // skip header + addr = make_reg(seg, seeker - scr->_buf); switch (objType) { case SCI_OBJ_OBJECT: case SCI_OBJ_CLASS: if (pass == 0 && objType == SCI_OBJ_CLASS) { - int classpos = curOffset + 8; // SCRIPT_OBJECT_MAGIC_OFFSET - int species = READ_SCI11ENDIAN_UINT16(scr->_buf + classpos); + int species = READ_SCI11ENDIAN_UINT16(seeker + 8); // SCRIPT_OBJECT_MAGIC_OFFSET if (species == (int)classTableSize()) { // Happens in the LSL2 demo @@ -218,7 +218,7 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { return; } - setClassOffset(species, make_reg(seg, classpos)); + setClassOffset(species, make_reg(seg, seeker - scr->_buf + 8)); } else if (pass == 1) { Object *obj = scr->scriptObjInit(addr); obj->initSpecies(this, addr); @@ -234,14 +234,14 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { break; } - curOffset += objLength - 4; - } while (objType != 0 && curOffset < scr->getScriptSize() - 2); + seeker += objLength - 4; + } while (objType != 0 && (uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2); } // for } void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart;; + const byte *seeker = scr->_heapStart; uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; seeker += entrySize; // skip first entry seeker += 4; // skip header diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 4524241110..13c7904726 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -588,11 +588,9 @@ void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { #ifdef GC_DEBUG - Object *victim_obj; + // assert(addr.segment == _segId); -// assert(addr.segment == _segId); - - victim_obj = &(_table[addr.offset]); + Object *victim_obj = &(_table[addr.offset]); if (!(victim_obj->_flags & OBJECT_FLAG_FREED)) warning("[GC] Clone %04x:%04x not reachable and not freed (freeing now)", PRINT_REG(addr)); -- cgit v1.2.3 From b161310193713f262dec017e11997ef77eac20c6 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 01:06:51 +0000 Subject: Script workaround fix for bug #2917661 - Crash when interacting with D'Blah svn-id: r50360 --- engines/tinsel/pcode.cpp | 7 +++++++ 1 file changed, 7 insertions(+) (limited to 'engines') diff --git a/engines/tinsel/pcode.cpp b/engines/tinsel/pcode.cpp index c472a770d2..98fb078459 100644 --- a/engines/tinsel/pcode.cpp +++ b/engines/tinsel/pcode.cpp @@ -148,6 +148,7 @@ static const byte fragment12[] = {OP_JMPTRUE | OPSIZE16, FRAGMENT_WORD(1491), OP_ONE, OP_LIBCALL | OPSIZE8, 14, // Re-show the cursor OP_IMM | OPSIZE16, FRAGMENT_WORD(322), OP_LIBCALL | OPSIZE8, 46, // Give back the whistle OP_JUMP | OPSIZE16, FRAGMENT_WORD(1568)}; +static const byte fragment13[] = {OP_ZERO, OP_GSTORE | OPSIZE16, FRAGMENT_WORD(306)}; #undef FRAGMENT_WORD @@ -207,6 +208,12 @@ const WorkaroundEntry workaroundList[] = { // See bug report #2934211. {TINSEL_V1, true, 352601285, 1569, sizeof(fragment11), fragment11}, {TINSEL_V1, false, 352602304, 1488, sizeof(fragment12), fragment12}, + + // DW2: Corrects a bug with global 306 not being cleared if you leave + // the marketplace scene whilst D'Blah is talking (even if it's not + // actually audible); returning to the scene and clicking on him multiple + // times would cause the game to crash + {TINSEL_V2, true, 1109294728, 0, sizeof(fragment13), fragment13}, {TINSEL_V0, false, 0, 0, 0, NULL} }; -- cgit v1.2.3 From ae332b620e13d554563a3a6f9b435ebde6761f7a Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Sun, 27 Jun 2010 04:19:55 +0000 Subject: Run possible cut-scenes before each location change. This is the behavior of the original player. It is not necessary to click on the hero. svn-id: r50361 --- engines/draci/game.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 0e4b3386ec..23cb4700c1 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -174,8 +174,17 @@ void Game::start() { // Call the outer loop doing all the hard job. loop(kOuterLoop, false); - } + if (!isReloaded()) { + // We are changing location. Run the hero's LOOK + // program to trigger a possible cut-scene. This is + // the behavior of the original game player, whose + // intention was to run the cut sequences after the + // certain location change. + const GameObject *dragon = getObject(kDragonObject); + _vm->_script->run(dragon->_program, dragon->_look); + } + } } void Game::init() { -- cgit v1.2.3 From 6a6091f6d7547d750985f6ee757d5b7c9c2d78b3 Mon Sep 17 00:00:00 2001 From: Nicola Mettifogo Date: Sun, 27 Jun 2010 04:58:48 +0000 Subject: Prevent execution of the STOP script command when its Zone does not exist. Patch #3021744 by fuzzie with some comments. svn-id: r50363 --- engines/parallaction/exec_br.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/parallaction/exec_br.cpp b/engines/parallaction/exec_br.cpp index 76e6f0dfe0..1d8724e2d8 100644 --- a/engines/parallaction/exec_br.cpp +++ b/engines/parallaction/exec_br.cpp @@ -527,6 +527,11 @@ DECLARE_INSTRUCTION_OPCODE(endif) { DECLARE_INSTRUCTION_OPCODE(stop) { ZonePtr z = ctxt._inst->_z; + + // Prevent execution if zone is missing. The known case is "PART2/insegui.scr", which has + // "STOP insegui", which doesn't exist (see ticket #3021744 for the gory details) + if (!z) return; + if (ACTIONTYPE(z) == kZoneHear) { warning("Parallaction_br::instOp_stop not yet implemented for HEAR zones"); // TODO: stop music or sound effects generated by a zone. -- cgit v1.2.3 From c922af06c2d209de13349d9938388242238fc744 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 05:17:40 +0000 Subject: Centralised the update logic for the various system lists into the MadsView class svn-id: r50365 --- engines/m4/mads_anim.cpp | 2 +- engines/m4/mads_scene.cpp | 3 +-- engines/m4/mads_views.cpp | 5 +++++ engines/m4/mads_views.h | 5 +++++ 4 files changed, 12 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index fb565a927c..c2e9ea4eee 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -547,7 +547,7 @@ void AnimviewView::updateState() { } void AnimviewView::readNextCommand() { -static bool tempFlag = false;//****DEBUG - Temporarily allow me to skip several intro scenes **** +static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several intro scenes **** while (!_script->eos() && !_script->err()) { if (!tempFlag) { diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 60fffadc07..73388a2325 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -297,7 +297,6 @@ void MadsScene::update() { void MadsScene::updateState() { _sceneLogic.sceneStep(); - _sequenceList.tick(); if ((_activeAnimation) && !_abortTimers) { _activeAnimation->update(); @@ -307,7 +306,7 @@ void MadsScene::updateState() { } } - _kernelMessages.update(); + MadsView::update(); } int MadsScene::loadSceneSpriteSet(const char *setName) { diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 08b579cfb0..7b0b1443a8 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -1238,6 +1238,11 @@ void MadsView::refresh() { _textDisplay.cleanUp(); } +void MadsView::update() { + _sequenceList.tick(); + _kernelMessages.update(); +} + void MadsView::clearLists() { _textDisplay.clear(); _kernelMessages.clear(); diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 843596412e..fc001740d3 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -170,6 +170,10 @@ public: AbortTimerMode abortMode; uint16 actionNouns[3]; char msg[100]; + + MadsKernelMessageEntry() { + flags = 0; + } }; class MadsKernelMessageList { @@ -404,6 +408,7 @@ public: ~MadsView(); void refresh(); + void update(); void clearLists(); }; -- cgit v1.2.3 From 965cdb6fbf1d7db6ca839a9cb75be1821975d8b7 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 05:18:21 +0000 Subject: Several bugfixes to the loading, display, and digital sound playing of messages during cutscenes svn-id: r50366 --- engines/m4/animation.cpp | 31 +++++++++++++++++-------------- engines/m4/animation.h | 6 +++--- 2 files changed, 20 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 6b32bdca17..fae21db072 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -132,23 +132,24 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S for (int i = 0; i < messagesCount; ++i) { AnimMessage rec; - rec.soundId = animStream->readUint16LE(); - animStream->read(rec.msg, 70); - animStream->readUint16LE(); - animStream->readUint16LE(); + rec.soundId = animStream->readSint16LE(); + animStream->read(rec.msg, 64); + animStream->skip(4); + rec.pos.x = animStream->readSint16LE(); + rec.pos.y = animStream->readSint16LE(); + rec.flags = animStream->readUint16LE(); rec.rgb1.r = animStream->readByte(); rec.rgb1.g = animStream->readByte(); rec.rgb1.b = animStream->readByte(); rec.rgb2.r = animStream->readByte(); rec.rgb2.g = animStream->readByte(); rec.rgb2.b = animStream->readByte(); - animStream->readUint16LE(); - animStream->readUint16LE(); - rec.kernelMsgIndex = animStream->readUint16LE(); - rec.pos.x = animStream->readUint16LE(); - rec.pos.y = animStream->readUint16LE(); + animStream->skip(2); // Space for kernelMsgIndex + rec.kernelMsgIndex = -1; + animStream->skip(6); rec.startFrame = animStream->readUint16LE(); rec.endFrame = animStream->readUint16LE(); + animStream->skip(2); _messages.push_back(rec); } @@ -166,8 +167,8 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S rec.seqIndex = animStream->readByte(); rec.spriteSlot.spriteListIndex = animStream->readByte(); rec.spriteSlot.frameNumber = animStream->readUint16LE(); - rec.spriteSlot.xp = animStream->readUint16LE(); - rec.spriteSlot.yp = animStream->readUint16LE(); + rec.spriteSlot.xp = animStream->readSint16LE(); + rec.spriteSlot.yp = animStream->readSint16LE(); rec.spriteSlot.depth = animStream->readByte(); rec.spriteSlot.scale = (int8)animStream->readByte(); @@ -425,10 +426,12 @@ void MadsAnimation::update() { _vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b); // Add a kernel message to display the given text - me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 101, 0, 0, INDEFINITE_TIMEOUT, me.msg); + me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101, 0, 0, INDEFINITE_TIMEOUT, me.msg); + assert(me.kernelMsgIndex >= 0); + // Play the associated sound, if it exists - if (me.soundId >= 0) - _vm->_sound->playDSRSound(me.soundId, 255, false); + if (me.soundId > 0) + _vm->_sound->playDSRSound(me.soundId - 1, 255, false); ++_messageCtr; } } diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 89c3cbbfaf..135618d7e2 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -40,12 +40,12 @@ class SpriteSlotSubset; class AnimMessage { public: int16 soundId; - char msg[70]; + char msg[64]; Common::Point pos; RGB8 rgb1, rgb2; - int kernelMsgIndex; - + uint16 flags; int startFrame, endFrame; + int kernelMsgIndex; }; class AnimFrameEntry { -- cgit v1.2.3 From be399485cde37b84fa660b6f83c4adf29f6312c7 Mon Sep 17 00:00:00 2001 From: Travis Howell Date: Sun, 27 Jun 2010 05:30:18 +0000 Subject: Add Nintendo Wii (PAL) versions of Freddi Fish: Kelp Seed Mystery. svn-id: r50367 --- engines/scumm/scumm-md5.h | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 76045f42a2..a25fac1a88 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Tue Jun 22 19:42:27 2010 + This file was generated by the md5table tool on Sun Jun 27 05:23:26 2010 DO NOT EDIT MANUALLY! */ @@ -137,6 +137,7 @@ static const MD5Table md5table[] = { { "2fe369ad70f52a8cf7ad6077ee64f81a", "loom", "EGA", "EGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "305d3dd57c96c65b017bc70c8c7cfb5e", "monkey", "CD", "CD", 8955, Common::DE_DEU, Common::kPlatformPC }, { "30ba1e825d4ad2b448143ae8df18482a", "pajama2", "HE 98.5", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown }, + { "30d1903b0715759af064be2127381cd0", "freddi", "HE 100", "", 34837, Common::DE_DEU, Common::kPlatformWii }, { "319a4dde52c7960b5aae8a1ec348d918", "monkey", "VGA", "VGA", -1, Common::DE_DEU, Common::kPlatformAmiga }, { "31aa57f460a3d12429f0552a46a90b39", "puttputt", "Demo", "Demo", 6150, Common::EN_ANY, Common::kPlatformPC }, { "31b8fda4c8c7413fa6b39997e776eba4", "loom", "FM-TOWNS", "", -1, Common::JA_JPN, Common::kPlatformFMTowns }, @@ -167,6 +168,7 @@ static const MD5Table md5table[] = { { "3a3e592b074f595489f7f11e150c398d", "puttzoo", "HE 99", "Updated", -1, Common::EN_USA, Common::kPlatformWindows }, { "3a5d13675e9a23aedac0bac7730f0ac1", "samnmax", "", "CD", -1, Common::FR_FRA, Common::kPlatformMacintosh }, { "3a5ec90d556d4920976c5578bfbfaf79", "maniac", "NES", "", -1, Common::DE_DEU, Common::kPlatformNES }, + { "3ae7f002d9256b8bdf76aaf8a3a069f8", "freddi", "HE 100", "", 34837, Common::EN_GRB, Common::kPlatformWii }, { "3af61c5edf8e15b43dbafd285b2e9777", "puttcircus", "", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows }, { "3b301b7892f883ce42ab4be6a274fea6", "samnmax", "Floppy", "Floppy", -1, Common::EN_ANY, Common::kPlatformPC }, { "3b832f4a90740bf22e9b8ed42ca0128c", "freddi4", "HE 99", "", -1, Common::EN_GRB, Common::kPlatformWindows }, @@ -196,6 +198,7 @@ static const MD5Table md5table[] = { { "49a1739981a89066b1121fac04b710f4", "spyfox2", "HE CUP", "Preview", 5756234, Common::UNK_LANG, Common::kPlatformUnknown }, { "4aa93cb30e485b728504ba3a693f12bf", "pajama", "HE 100", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "4af4a6b248103c1fe9edef619677f540", "puttmoon", "", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh }, + { "4afb734df8315ee412669c812d4cf0a1", "freddi", "HE 100", "", 34837, Common::FR_FRA, Common::kPlatformWii }, { "4ba37f835be11a59d969f90f272f575b", "water", "HE 80", "", -1, Common::EN_USA, Common::kPlatformUnknown }, { "4ba7fb331296c283e73d8f5b2096e551", "samnmax", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "4bedb49943df95a9c900a5a82ccbe9de", "ft", "", "", -1, Common::FR_FRA, Common::kPlatformUnknown }, @@ -230,6 +233,7 @@ static const MD5Table md5table[] = { { "55e4cc866ff9046824e1c638ba2b8c7f", "ft", "", "", -1, Common::RU_RUS, Common::kPlatformUnknown }, { "55f4e9402bec2bded383843123f37c5c", "pajama2", "HE 98.5", "", -1, Common::DE_DEU, Common::kPlatformWindows }, { "566165a7338fa11029e7c14d94fa70d0", "freddi", "HE 73", "Demo", 9800, Common::EN_ANY, Common::kPlatformWindows }, + { "56b5922751be7ffd771b38dda56b028b", "freddi", "HE 100", "", 34837, Common::NL_NLD, Common::kPlatformWii }, { "5719fc8a13b4638b78d9d8d12f091f94", "puttrace", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows }, { "5798972220cd458be2626d54c80f71d7", "atlantis", "Floppy", "Floppy", -1, Common::IT_ITA, Common::kPlatformAmiga }, { "57a17febe2183f521250e55d55b83e60", "PuttTime", "HE 99", "", -1, Common::FR_FRA, Common::kPlatformWindows }, @@ -357,6 +361,7 @@ static const MD5Table md5table[] = { { "87df3e0074624040407764b7c5e710b9", "pajama", "", "Demo", 18354, Common::NL_NLD, Common::kPlatformWindows }, { "87f6e8037b7cc996e13474b491a7a98e", "maniac", "V2", "V2", -1, Common::IT_ITA, Common::kPlatformPC }, { "8801fb4a1200b347f7a38523339526dd", "jungle", "", "", -1, Common::EN_ANY, Common::kPlatformWindows }, + { "880c5ca5b944648b3f8b03feb41705a8", "freddi", "HE 100", "", 34837, Common::SE_SWE, Common::kPlatformWii }, { "883af4b0af4f77a92f1dcf1d0a283140", "tentacle", "", "CD", -1, Common::ES_ESP, Common::kPlatformUnknown }, { "898ce8eb1234a955ef75e87141902bb3", "freddi3", "", "", -1, Common::RU_RUS, Common::kPlatformWindows }, { "898eaa21f79cf8d4f08db856244689ff", "pajama", "HE 99", "Updated", 66505, Common::EN_ANY, Common::kPlatformWindows }, @@ -430,6 +435,7 @@ static const MD5Table md5table[] = { { "a561d2e2413cc1c71d5a1bf87bf493ea", "lost", "HE 100", "Updated", -1, Common::EN_USA, Common::kPlatformUnknown }, { "a56e8d9d4281c53c3f63c9bd22a59e21", "catalog", "HE CUP", "Preview", 10978342, Common::EN_ANY, Common::kPlatformUnknown }, { "a570381b028972d891052ee1e51dc011", "maniac", "V2", "V2", 1988, Common::EN_ANY, Common::kPlatformAtariST }, + { "a59a438cb182124c30c4447d8ed469e9", "freddi", "HE 100", "", 34837, Common::NB_NOR, Common::kPlatformWii }, { "a5c5388da9bf0e6662fdca8813a79d13", "farm", "", "", 86962, Common::EN_ANY, Common::kPlatformWindows }, { "a654fb60c3b67d6317a7894ffd9f25c5", "pajama3", "", "Demo", -1, Common::EN_USA, Common::kPlatformUnknown }, { "a7cacad9c40c4dc9e1812abf6c8af9d5", "puttcircus", "", "Demo", -1, Common::EN_ANY, Common::kPlatformUnknown }, -- cgit v1.2.3 From 9a8683ac656e37a62ecf483f635424cc559d397a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 05:58:11 +0000 Subject: Added accidentally deleted line svn-id: r50369 --- engines/m4/mads_anim.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index c2e9ea4eee..d8976241e1 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -513,6 +513,8 @@ bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, boo } void AnimviewView::updateState() { + MadsView::update(); + if (!_script) return; -- cgit v1.2.3 From c7682f5117c5286247fbaf50497c4b35e5f6817f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 06:35:32 +0000 Subject: Added proper conversion of message RGB colour values svn-id: r50371 --- engines/m4/animation.cpp | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index fae21db072..4dc645991e 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -138,12 +138,12 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S rec.pos.x = animStream->readSint16LE(); rec.pos.y = animStream->readSint16LE(); rec.flags = animStream->readUint16LE(); - rec.rgb1.r = animStream->readByte(); - rec.rgb1.g = animStream->readByte(); - rec.rgb1.b = animStream->readByte(); - rec.rgb2.r = animStream->readByte(); - rec.rgb2.g = animStream->readByte(); - rec.rgb2.b = animStream->readByte(); + rec.rgb1.r = animStream->readByte() << 2; + rec.rgb1.g = animStream->readByte() << 2; + rec.rgb1.b = animStream->readByte() << 2; + rec.rgb2.r = animStream->readByte() << 2; + rec.rgb2.g = animStream->readByte() << 2; + rec.rgb2.b = animStream->readByte() << 2; animStream->skip(2); // Space for kernelMsgIndex rec.kernelMsgIndex = -1; animStream->skip(6); -- cgit v1.2.3 From b6b4247335c5cc0f82cdaf590b2bd93e22eb62af Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 27 Jun 2010 11:16:49 +0000 Subject: Workaround that corrects some bad frame data in the Russian version that was causing the several game crashes svn-id: r50372 --- engines/tinsel/graphics.cpp | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) (limited to 'engines') diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp index 9700e8947f..3423f1054a 100644 --- a/engines/tinsel/graphics.cpp +++ b/engines/tinsel/graphics.cpp @@ -443,6 +443,12 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply int numBytes; int clipAmount; + // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version + if ((pObj->hBits == 2517583660) && (_vm->getLanguage() == Common::RU_RUS)) { + uint8 correctBytes[5] = {0xA3, 0x00, 0x89, 0xC0, 0xA6}; + Common::copy(&correctBytes[0], &correctBytes[5], srcP); + } + for (int y = 0; y < pObj->height; ++y) { // Get the position to start writing out from uint8 *tempP = !horizFlipped ? destP : @@ -596,6 +602,23 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, int numBytes, colour; int v; + if (_vm->getLanguage() == Common::RU_RUS) { + // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version + if (pObj->hBits == 2517583393) { + uint8 correctBytes[5] = {0x00, 0x00, 0x17, 0x01, 0x00}; + Common::copy(&correctBytes[0], &correctBytes[5], srcP + 267); + } + // WORKAROUND: One of Dibbler's frames in the end sequence has corrupt bytes in the Russian version + if (pObj->hBits == 33651742) { + uint8 correctBytes[40] = { + 0x06, 0xc0, 0xd6, 0xc1, 0x09, 0xce, 0x0d, 0x24, 0x02, 0x12, 0x01, 0x00, 0x00, 0x23, 0x21, 0x32, + 0x12, 0x00, 0x00, 0x20, 0x01, 0x11, 0x32, 0x12, 0x01, 0x00, 0x00, 0x1b, 0x02, 0x11, 0x34, 0x11, + 0x00, 0x00, 0x18, 0x01, 0x11, 0x35, 0x21, 0x01 + }; + Common::copy(&correctBytes[0], &correctBytes[40], srcP); + } + } + if (applyClipping) { pObj->height -= pObj->botClip; topClip = pObj->topClip; -- cgit v1.2.3 From 0b6bd84aba372076c450dfefa89752a3c7778bae Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 11:19:23 +0000 Subject: SCI: adding uninit workaround for lsl6 (Narrator::startText) svn-id: r50373 --- engines/sci/engine/vm.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c4c77e16de..a6caa1e251 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -199,6 +199,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room + { GID_LSL6, 928, "*", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions (actually Narrator::startText) { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon { GID_KQ5, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio @@ -249,7 +250,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i // Search if this is a known uninitialized read const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && workaround->objectName == curObjectName + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && ((workaround->objectName == curObjectName) || (*workaround->objectName == '*')) && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) { // Workaround found r[index] = make_reg(0, workaround->newValue); -- cgit v1.2.3 From 32ee0338f8309bddfe61cc23db934bfb4447cdc2 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 11:51:44 +0000 Subject: SCI: better solution for the lsl6 uninit issue, we now go through all the parents till we find a working workaround - we can use Narrator::startText that way inside the workaround table svn-id: r50374 --- engines/sci/engine/vm.cpp | 29 +++++++++++++++++++---------- 1 file changed, 19 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a6caa1e251..c4552e591d 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -199,7 +199,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room - { GID_LSL6, 928, "*", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions (actually Narrator::startText) + { GID_LSL6, 928, "Narrator", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions, that's why we use the base-class { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon { GID_KQ5, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio @@ -248,16 +248,25 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i } // Search if this is a known uninitialized read - const UninitializedReadWorkaround *workaround = uninitializedReadWorkarounds; - while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && ((workaround->objectName == curObjectName) || (*workaround->objectName == '*')) - && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) { - // Workaround found - r[index] = make_reg(0, workaround->newValue); - return r[index]; + const UninitializedReadWorkaround *workaround; + Common::String searchObjectName = curObjectName; + reg_t searchObject = lastCall->sendp; + do { + workaround = uninitializedReadWorkarounds; + while (workaround->objectName) { + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->objectName == searchObjectName) + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) { + // Workaround found + r[index] = make_reg(0, workaround->newValue); + return r[index]; + } + workaround++; } - workaround++; - } + // Go back to the parent + searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); + if (!searchObject.isNull()) + searchObjectName = state->_segMan->getObjectName(searchObject); + } while (!searchObject.isNull()); // no parent left? error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset); } return r[index]; -- cgit v1.2.3 From 25ca058fa841f29b0e2999f446b9d6f8198d78e5 Mon Sep 17 00:00:00 2001 From: Eugene Sandulenko Date: Sun, 27 Jun 2010 13:06:22 +0000 Subject: Add support for Chinese The DIG. svn-id: r50375 --- engines/scumm/charset.cpp | 7 +++---- engines/scumm/detection.cpp | 4 +++- engines/scumm/string.cpp | 2 ++ 3 files changed, 8 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/scumm/charset.cpp b/engines/scumm/charset.cpp index 0e0c0e129e..fa4804ce7d 100644 --- a/engines/scumm/charset.cpp +++ b/engines/scumm/charset.cpp @@ -109,10 +109,9 @@ void ScummEngine::loadCJKFont() { numChar = 8192; break; case Common::ZH_TWN: - if (_game.id == GID_CMI) { - fontFile = "chinese.fnt"; - numChar = 13630; - } + // Both The DIG and COMI use same font + fontFile = "chinese.fnt"; + numChar = 13630; break; case Common::ZH_CNA: if (_game.id == GID_FT || _game.id == GID_LOOM || _game.id == GID_INDY3 || diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index dbd86505a8..407b139c7e 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -314,7 +314,7 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) { case 449787: // 64f3fe479d45b52902cf88145c41d172 return Common::ES_ESP; } - } else { + } else { // The DIG switch (size) { case 248627: // 1fd585ac849d57305878c77b2f6c74ff return Common::DE_DEU; @@ -328,6 +328,8 @@ static Common::Language detectLanguage(const Common::FSList &fslist, byte id) { return Common::ES_ESP; case 223107: // 64f3fe479d45b52902cf88145c41d172 return Common::JA_JPN; + case 180730: // 424fdd60822722cdc75356d921dad9bf + return Common::ZH_TWN; } } } diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp index 480e18e514..62fdf48440 100644 --- a/engines/scumm/string.cpp +++ b/engines/scumm/string.cpp @@ -1351,6 +1351,8 @@ void ScummEngine_v7::loadLanguageBundle() { // File contains Korean text (Hangul). just ignore it } else if (*ptr == 'j') { // File contains Japanese text. just ignore it + } else if (*ptr == 'c') { + // File contains Chinese text. just ignore it } else if (*ptr == 'e') { // File is encoded! enc = 0x13; -- cgit v1.2.3 From 6864d09d68b8e31f94ac802dd791a188523322d9 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Sun, 27 Jun 2010 13:15:01 +0000 Subject: SCI: Fix for large views in GK2. At least it does not segfault now. svn-id: r50376 --- engines/sci/graphics/view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index f00d6a652d..5436e426ff 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -579,8 +579,8 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect byte color; byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; int x, y; - uint16 scalingX[320]; - uint16 scalingY[200]; + uint16 scalingX[640]; + uint16 scalingY[480]; int16 scaledWidth, scaledHeight; int16 pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo; uint16 offsetX, offsetY; -- cgit v1.2.3 From 01bfcf98cc2bb5e135549b3e0cbdc4f3fe57e5ee Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 15:50:51 +0000 Subject: SCI: debug command vmvars - adding acc support svn-id: r50378 --- engines/sci/console.cpp | 115 +++++++++++++++++++++++++++++++----------------- 1 file changed, 74 insertions(+), 41 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e50ae171c1..8ea4315c24 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1958,76 +1958,109 @@ bool Console::cmdVMVarlist(int argc, const char **argv) { } bool Console::cmdVMVars(int argc, const char **argv) { - if (argc < 3) { + if (argc < 2) { DebugPrintf("Displays or changes variables in the VM\n"); DebugPrintf("Usage: %s []\n", argv[0]); - DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp) or p(aram).\n"); - DebugPrintf("Second parameter is the var number\n"); + DebugPrintf("First parameter is either g(lobal), l(ocal), t(emp), p(aram) or a(cc).\n"); + DebugPrintf("Second parameter is the var number (not specified on acc)\n"); DebugPrintf("Third parameter (if specified) is the value to set the variable to, in address form\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); return true; } EngineState *s = _engine->_gamestate; - const char *varnames[] = {"global", "local", "temp", "param"}; - const char *varabbrev = "gltp"; - const char *vartype_pre = strchr(varabbrev, *argv[1]); - int vartype; - int idx; - - if (!vartype_pre) { + const char *varNames[] = {"global", "local", "temp", "param", "acc"}; + const char *varAbbrev = "gltpa"; + const char *varType_pre = strchr(varAbbrev, *argv[1]); + int varType; + int varIndex = 0; + reg_t *curValue = NULL; + const char *setValue = NULL; + + if (!varType_pre) { DebugPrintf("Invalid variable type '%c'\n", *argv[1]); return true; } - vartype = vartype_pre - varabbrev; + varType = varType_pre - varAbbrev; - char *endPtr = 0; - int idxLen = strlen(argv[2]); - const char *lastChar = argv[2] + idxLen - (idxLen == 0 ? 0 : 1); + switch (varType) { + case 0: + case 1: + case 2: + case 3: { + // for global, local, temp and param, we need an index + if (argc < 3) { + DebugPrintf("Variable number must be specified for requested type\n"); + return true; + } + if (argc > 4) { + DebugPrintf("Too many arguments\n"); + return true; + } + + char *endPtr = 0; + int idxLen = strlen(argv[2]); + const char *lastChar = argv[2] + idxLen - (idxLen == 0 ? 0 : 1); - if ((strncmp(argv[2], "0x", 2) == 0) || (*lastChar == 'h')) { - // hexadecimal number - idx = strtol(argv[2], &endPtr, 16); - if ((*endPtr != 0) && (*endPtr != 'h')) { - DebugPrintf("Invalid hexadecimal index '%s'\n", argv[2]); + if ((strncmp(argv[2], "0x", 2) == 0) || (*lastChar == 'h')) { + // hexadecimal number + varIndex = strtol(argv[2], &endPtr, 16); + if ((*endPtr != 0) && (*endPtr != 'h')) { + DebugPrintf("Invalid hexadecimal number '%s'\n", argv[2]); + return true; + } + } else { + // decimal number + varIndex = strtol(argv[2], &endPtr, 10); + if (*endPtr != 0) { + DebugPrintf("Invalid decimal number '%s'\n", argv[2]); + return true; + } + } + if (varIndex < 0) { + DebugPrintf("Variable number may not be negative\n"); return true; } - } else { - // decimal number - idx = strtol(argv[2], &endPtr, 10); - if (*endPtr != 0) { - DebugPrintf("Invalid decimal index '%s'\n", argv[2]); + + if ((s->variablesMax) && (s->variablesMax[varType] <= varIndex)) { + DebugPrintf("Maximum variable number for this type is %d (0x%x)\n", s->variablesMax[varType], s->variablesMax[varType]); return true; } + curValue = &s->variables[varType][varIndex]; + if (argc == 4) + setValue = argv[3]; + break; } - if (idx < 0) { - DebugPrintf("Invalid: negative index\n"); - return true; - } + case 4: + // acc + if (argc > 3) { + DebugPrintf("Too many arguments\n"); + return true; + } + curValue = &s->r_acc; + if (argc == 3) + setValue = argv[2]; + break; - if ((s->variablesMax) && (s->variablesMax[vartype] <= idx)) { - DebugPrintf("Max. index is %d (0x%x)\n", s->variablesMax[vartype], s->variablesMax[vartype]); - return true; + default: + break; } - switch (argc) { - case 3: - DebugPrintf("%s var %d == %04x:%04x\n", varnames[vartype], idx, PRINT_REG(s->variables[vartype][idx])); - break; - case 4: - if (parse_reg_t(_engine->_gamestate, argv[3], &s->variables[vartype][idx], true)) { + if (!setValue) { + if (varType == 4) + DebugPrintf("%s == %04x:%04x\n", varNames[varType], PRINT_REG(*curValue)); + else + DebugPrintf("%s var %d == %04x:%04x\n", varNames[varType], varIndex, PRINT_REG(*curValue)); + } else { + if (parse_reg_t(s, setValue, curValue, true)) { DebugPrintf("Invalid value/address passed.\n"); DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); DebugPrintf("Or pass a decimal or hexadecimal value directly (e.g. 12, 1Ah)\n"); return true; } - break; - default: - DebugPrintf("Too many arguments\n"); } - return true; } -- cgit v1.2.3 From d7f212647a115b011db7c37f5bcdd6a5eae62235 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 16:02:03 +0000 Subject: Turned the error when failing to locate an invalid object back to a warning (KQ5 French has an invalid object in script 202) svn-id: r50379 --- engines/sci/engine/script.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index f26a2e53af..b3fbafb355 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -224,8 +224,9 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { obj->initSpecies(this, addr); if (!obj->initBaseObject(this, addr)) { - error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - //scr->scriptObjRemove(addr); + // Script 202 of KQ5 French has an invalid object + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + scr->scriptObjRemove(addr); } } break; -- cgit v1.2.3 From a2cdc475300c7f8e56cd26146f513715ecfa05e0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 16:09:17 +0000 Subject: SCI: now showing kernel call name when argument signature check fails svn-id: r50380 --- engines/sci/engine/vm.cpp | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index c4552e591d..841d4ede64 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -654,16 +654,16 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { } } -static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { +static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { - if (kernelFuncNum >= (int)g_sci->getKernel()->_kernelFuncs.size()) - error("Invalid kernel function 0x%x requested", kernelFuncNum); + if (kernelFuncNr >= (int)g_sci->getKernel()->_kernelFuncs.size()) + error("Invalid kernel function 0x%x requested", kernelFuncNr); - const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNum]; + const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNr]; if (kernelFunc.signature && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, s->xs->sp + 1)) { - error("[VM] Invalid arguments to kernel call %x", kernelFuncNum); + error("[VM] Invalid arguments to kernel call k%s (funcNr %x)", g_sci->getKernel()->getKernelName(kernelFuncNr).c_str(), kernelFuncNr); } reg_t *argv = s->xs->sp + 1; @@ -675,15 +675,15 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { ExecStack *xstack; xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->selector = kernelFuncNum; + xstack->selector = kernelFuncNr; xstack->type = EXEC_STACK_TYPE_KERNEL; //warning("callk %s", kernelFunc.origName.c_str()); // TODO: SCI2.1 equivalent if (s->loadFromLauncher >= 0 && ( - (kernelFuncNum == 0x8 && getSciVersion() <= SCI_VERSION_1_1) || // DrawPic - (kernelFuncNum == 0x3d && getSciVersion() == SCI_VERSION_2) // GetSaveDir + (kernelFuncNr == 0x8 && getSciVersion() <= SCI_VERSION_1_1) || // DrawPic + (kernelFuncNr == 0x3d && getSciVersion() == SCI_VERSION_2) // GetSaveDir //(kernelFuncNum == 0x28 && getSciVersion() == SCI_VERSION_2_1) // AddPlane )) { @@ -726,7 +726,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNum, int argc) { s->_executionStack.pop_back(); } else { Common::String warningMsg = "Dummy function " + kernelFunc.origName + - Common::String::printf("[0x%x]", kernelFuncNum) + + Common::String::printf("[0x%x]", kernelFuncNr) + " invoked - ignoring. Params: " + Common::String::printf("%d", argc) + " ("; -- cgit v1.2.3 From 5997307081db72c002a9a131d0eefc1a190e1ced Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 27 Jun 2010 17:06:26 +0000 Subject: Fixed GCC warnings. (Same warning twice, actually.) svn-id: r50383 --- engines/tinsel/graphics.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/tinsel/graphics.cpp b/engines/tinsel/graphics.cpp index 3423f1054a..48270d94e3 100644 --- a/engines/tinsel/graphics.cpp +++ b/engines/tinsel/graphics.cpp @@ -444,7 +444,7 @@ static void t2WrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, bool apply int clipAmount; // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version - if ((pObj->hBits == 2517583660) && (_vm->getLanguage() == Common::RU_RUS)) { + if ((pObj->hBits == 2517583660UL) && (_vm->getLanguage() == Common::RU_RUS)) { uint8 correctBytes[5] = {0xA3, 0x00, 0x89, 0xC0, 0xA6}; Common::copy(&correctBytes[0], &correctBytes[5], srcP); } @@ -604,7 +604,7 @@ static void PackedWrtNonZero(DRAWOBJECT *pObj, uint8 *srcP, uint8 *destP, if (_vm->getLanguage() == Common::RU_RUS) { // WORKAROUND: One of the mortician frames has several corrupt bytes in the Russian version - if (pObj->hBits == 2517583393) { + if (pObj->hBits == 2517583393UL) { uint8 correctBytes[5] = {0x00, 0x00, 0x17, 0x01, 0x00}; Common::copy(&correctBytes[0], &correctBytes[5], srcP + 267); } -- cgit v1.2.3 From 777794d11d8d26e0c2cc87d7e039548a723ef474 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 17:58:26 +0000 Subject: SCI: filter out set signal commands from midi streams, if they happen at ticker 0. fixes castle daventry getting removed immediately in kq5 french/mac svn-id: r50385 --- engines/sci/sound/midiparser_sci.cpp | 82 +++++++++++++++++------------------- 1 file changed, 39 insertions(+), 43 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 46459522a3..1d25a518e1 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -440,10 +440,8 @@ byte MidiParser_SCI::midiGetNextChannel(long ticker) { byte *MidiParser_SCI::midiMixChannels() { int totalSize = 0; - byte **dataPtr = new byte *[_track->channelCount]; for (int i = 0; i < _track->channelCount; i++) { - dataPtr[i] = _track->channels[i].data; _track->channels[i].time = 0; _track->channels[i].prev = 0; totalSize += _track->channels[i].size; @@ -453,8 +451,8 @@ byte *MidiParser_SCI::midiMixChannels() { _mixedData = outData; long ticker = 0; byte channelNr, curDelta; - byte command = 0, par1, global_prev = 0; - long new_delta; + byte midiCommand = 0, midiParam, global_prev = 0; + long newDelta; SoundResource::Channel *channel; while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel @@ -463,57 +461,60 @@ byte *MidiParser_SCI::midiMixChannels() { channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur if (curDelta == 0xF8) continue; - new_delta = channel->time - ticker; - ticker += new_delta; - - command = channel->data[channel->curPos++]; - if (command != kEndOfTrack) { - debugC(4, kDebugLevelSound, "\nDELTA "); + newDelta = channel->time - ticker; + ticker += newDelta; + + midiCommand = channel->data[channel->curPos++]; + if ((midiCommand == 0xCF) && (!ticker)) { + // set signal command at tick 0? + channel->curPos++; + continue; // filter it + // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately + // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to + // get immediately removed, so we currently filter it. + // TODO: find out what exactly happens in sierra sci + } + if (midiCommand != kEndOfTrack) { // Write delta - while (new_delta > 240) { + while (newDelta > 240) { *outData++ = 0xF8; - debugC(4, kDebugLevelSound, "F8 "); - new_delta -= 240; + newDelta -= 240; } - *outData++ = (byte)new_delta; - debugC(4, kDebugLevelSound, "%02X ", (uint32)new_delta); + *outData++ = (byte)newDelta; } // Write command - switch (command) { + switch (midiCommand) { case 0xF0: // sysEx - *outData++ = command; - debugC(4, kDebugLevelSound, "%02X ", command); + *outData++ = midiCommand; do { - par1 = channel->data[channel->curPos++]; - *outData++ = par1; // out - } while (par1 != 0xF7); + midiParam = channel->data[channel->curPos++]; + *outData++ = midiParam; + } while (midiParam != 0xF7); break; case kEndOfTrack: // end of channel - // FIXME: Why does this need to be fixed? There's no - // additional information available - channel->time = -1; // FIXME + channel->time = -1; break; default: // MIDI command - if (command & 0x80) { - par1 = channel->data[channel->curPos++]; + if (midiCommand & 0x80) { + midiParam = channel->data[channel->curPos++]; } else {// running status - par1 = command; - command = channel->prev; + midiParam = midiCommand; + midiCommand = channel->prev; } // remember which channel got used for channel remapping - byte midiChannel = command & 0xF; + byte midiChannel = midiCommand & 0xF; _channelUsed[midiChannel] = true; - if (command != global_prev) - *outData++ = command; // out command - *outData++ = par1;// pout par1 - if (nMidiParams[(command >> 4) - 8] == 2) - *outData++ = channel->data[channel->curPos++]; // out par2 - channel->prev = command; - global_prev = command; - }// switch(command) - }// while (curr) + if (midiCommand != global_prev) + *outData++ = midiCommand; + *outData++ = midiParam; + if (nMidiParams[(midiCommand >> 4) - 8] == 2) + *outData++ = channel->data[channel->curPos++]; + channel->prev = midiCommand; + global_prev = midiCommand; + } + } // Insert stop event *outData++ = 0; // Delta @@ -521,11 +522,6 @@ byte *MidiParser_SCI::midiMixChannels() { *outData++ = 0x2F; // End of track (EOT) *outData++ = 0x00; *outData++ = 0x00; - - for (channelNr = 0; channelNr < _track->channelCount; channelNr++) - _track->channels[channelNr].data = dataPtr[channelNr]; - - delete[] dataPtr; return _mixedData; } -- cgit v1.2.3 From 303dc063883dab2dfe30b44d9fad9fe8e3948ec5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 18:41:07 +0000 Subject: SCI: fixing regression from one of the merges svn-id: r50387 --- engines/sci/engine/script.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index b3fbafb355..03234bea1d 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -345,7 +345,7 @@ void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - int superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); + int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); if (superclass >= 0) { int superclass_script = segMan->getClass(superclass).script; -- cgit v1.2.3 From 4653153910ee2186e914f5f4717e212053adef54 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 19:58:32 +0000 Subject: SCI: added new command "p" / "stepover" to execute one command, but skip send/calls processing. single-step is now "trace" (alias "s" and "t"), stepping till ret is "step_ret" (alias "pret"), removed unused kDebugSeek svn-id: r50388 --- engines/sci/console.cpp | 26 +++++++--- engines/sci/console.h | 3 +- engines/sci/debug.h | 4 +- engines/sci/engine/scriptdebug.cpp | 98 ++++++++++++++++++++------------------ 4 files changed, 74 insertions(+), 57 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 8ea4315c24..b34b4f44ea 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -156,12 +156,15 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias - DCmd_Register("step", WRAP_METHOD(Console, cmdStep)); - DCmd_Register("s", WRAP_METHOD(Console, cmdStep)); // alias + DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace)); + DCmd_Register("t", WRAP_METHOD(Console, cmdTrace)); // alias + DCmd_Register("s", WRAP_METHOD(Console, cmdTrace)); // alias + DCmd_Register("stepover", WRAP_METHOD(Console, cmdStepOver)); + DCmd_Register("p", WRAP_METHOD(Console, cmdStepOver)); // alias + DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); + DCmd_Register("pret", WRAP_METHOD(Console, cmdStepRet)); // alias DCmd_Register("step_event", WRAP_METHOD(Console, cmdStepEvent)); DCmd_Register("se", WRAP_METHOD(Console, cmdStepEvent)); // alias - DCmd_Register("step_ret", WRAP_METHOD(Console, cmdStepRet)); - DCmd_Register("sret", WRAP_METHOD(Console, cmdStepRet)); // alias DCmd_Register("step_global", WRAP_METHOD(Console, cmdStepGlobal)); DCmd_Register("sg", WRAP_METHOD(Console, cmdStepGlobal)); // alias DCmd_Register("step_callk", WRAP_METHOD(Console, cmdStepCallk)); @@ -378,9 +381,10 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" dissect_script - Examines a script\n"); DebugPrintf(" set_acc - Sets the accumulator\n"); DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); - DebugPrintf(" step / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); + DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); + DebugPrintf(" step_ret / pret - Steps forward until ret is called on the current execution stack level.\n"); DebugPrintf(" step_event / se - Steps forward until a SCI event is received.\n"); - DebugPrintf(" step_ret / sret - Steps forward until ret is called on the current execution stack level.\n"); DebugPrintf(" step_global / sg - Steps until the global variable with the specified index is modified.\n"); DebugPrintf(" step_callk / snk - Steps forward until it hits the next callk operation, or a specific callk (specified as a parameter)\n"); DebugPrintf(" disasm - Disassembles a method by name\n"); @@ -2405,7 +2409,7 @@ bool Console::cmdBacktrace(int argc, const char **argv) { return true; } -bool Console::cmdStep(int argc, const char **argv) { +bool Console::cmdTrace(int argc, const char **argv) { if (argc == 2 && atoi(argv[1]) > 0) g_debugState.runningStep = atoi(argv[1]) - 1; g_debugState.debugging = true; @@ -2413,6 +2417,14 @@ bool Console::cmdStep(int argc, const char **argv) { return false; } +bool Console::cmdStepOver(int argc, const char **argv) { + g_debugState.seeking = kDebugSeekStepOver; + g_debugState.seekLevel = _engine->_gamestate->_executionStack.size(); + g_debugState.debugging = true; + + return false; +} + bool Console::cmdStepEvent(int argc, const char **argv) { g_debugState.stopOnEvent = true; g_debugState.debugging = true; diff --git a/engines/sci/console.h b/engines/sci/console.h index e353958a0d..f8a2768f35 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -120,7 +120,8 @@ private: bool cmdDissectScript(int argc, const char **argv); bool cmdSetAccumulator(int argc, const char **argv); bool cmdBacktrace(int argc, const char **argv); - bool cmdStep(int argc, const char **argv); + bool cmdTrace(int argc, const char **argv); + bool cmdStepOver(int argc, const char **argv); bool cmdStepEvent(int argc, const char **argv); bool cmdStepRet(int argc, const char **argv); bool cmdStepGlobal(int argc, const char **argv); diff --git a/engines/sci/debug.h b/engines/sci/debug.h index 8383722956..d381e55dc8 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -57,8 +57,8 @@ enum DebugSeeking { kDebugSeekCallk = 1, // Step forward until callk is found kDebugSeekLevelRet = 2, // Step forward until returned from this level kDebugSeekSpecialCallk = 3, // Step forward until a /special/ callk is found - kDebugSeekSO = 4, // Step forward until specified PC (after the send command) and stack depth - kDebugSeekGlobal = 5 // Step forward until one specified global variable is modified + kDebugSeekGlobal = 4, // Step forward until one specified global variable is modified + kDebugSeekStepOver = 5 // Step forward until we reach same stack-level again }; struct DebugState { diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index d829b01c31..b8a0987865 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -296,55 +296,59 @@ void script_debug(EngineState *s) { #endif if (g_debugState.seeking && !g_debugState.breakpointWasHit) { // Are we looking for something special? - SegmentObj *mobj = s->_segMan->getSegment(s->xs->addr.pc.segment, SEG_TYPE_SCRIPT); - - if (mobj) { - Script *scr = (Script *)mobj; - byte *code_buf = scr->_buf; - int code_buf_size = scr->getBufSize(); - int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset]; - int op = opcode >> 1; - int paramb1 = s->xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (s->xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + s->xs->addr.pc.offset + 1)); - - switch (g_debugState.seeking) { - case kDebugSeekSpecialCallk: - if (paramb1 != g_debugState.seekSpecial) - return; - - case kDebugSeekCallk: - if (op != op_callk) - return; - break; - - case kDebugSeekLevelRet: - if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1)) - return; - break; - - case kDebugSeekGlobal: - if (op < op_sag) - return; - if ((op & 0x3) > 1) - return; // param or temp - if ((op & 0x3) && s->_executionStack.back().local_segment > 0) - return; // locals and not running in script.000 - if (paramf1 != g_debugState.seekSpecial) - return; // CORRECT global? - break; - - case kDebugSeekSO: - // FIXME: Unhandled? - break; - - case kDebugSeekNothing: - // We seek nothing, so just continue - break; - } - + if (g_debugState.seeking == kDebugSeekStepOver) { + // are we above seek-level? resume then + if (g_debugState.seekLevel < (int)s->_executionStack.size()) + return; g_debugState.seeking = kDebugSeekNothing; - // OK, found whatever we were looking for } + + if (g_debugState.seeking != kDebugSeekNothing) { + SegmentObj *mobj = s->_segMan->getSegment(s->xs->addr.pc.segment, SEG_TYPE_SCRIPT); + + if (mobj) { + Script *scr = (Script *)mobj; + byte *code_buf = scr->_buf; + int code_buf_size = scr->getBufSize(); + int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset]; + int op = opcode >> 1; + int paramb1 = s->xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (s->xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + s->xs->addr.pc.offset + 1)); + + switch (g_debugState.seeking) { + case kDebugSeekSpecialCallk: + if (paramb1 != g_debugState.seekSpecial) + return; + + case kDebugSeekCallk: + if (op != op_callk) + return; + break; + + case kDebugSeekLevelRet: + if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1)) + return; + break; + + case kDebugSeekGlobal: + if (op < op_sag) + return; + if ((op & 0x3) > 1) + return; // param or temp + if ((op & 0x3) && s->_executionStack.back().local_segment > 0) + return; // locals and not running in script.000 + if (paramf1 != g_debugState.seekSpecial) + return; // CORRECT global? + break; + + default: + break; + } + + g_debugState.seeking = kDebugSeekNothing; + } + } + // OK, found whatever we were looking for } printf("Step #%d\n", s->scriptStepCounter); -- cgit v1.2.3 From 7644631daf8758e50e113f908f9db3b7d7c68a90 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 20:02:58 +0000 Subject: SCI: removing debug command "set_acc", use "vmvars a" instead svn-id: r50389 --- engines/sci/console.cpp | 23 ----------------------- engines/sci/console.h | 1 - 2 files changed, 24 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b34b4f44ea..f5a47db281 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -153,7 +153,6 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("addresses", WRAP_METHOD(Console, cmdAddresses)); DCmd_Register("registers", WRAP_METHOD(Console, cmdRegisters)); DCmd_Register("dissect_script", WRAP_METHOD(Console, cmdDissectScript)); - DCmd_Register("set_acc", WRAP_METHOD(Console, cmdSetAccumulator)); DCmd_Register("backtrace", WRAP_METHOD(Console, cmdBacktrace)); DCmd_Register("bt", WRAP_METHOD(Console, cmdBacktrace)); // alias DCmd_Register("trace", WRAP_METHOD(Console, cmdTrace)); @@ -379,7 +378,6 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" addresses - Provides information on how to pass addresses\n"); DebugPrintf(" registers - Shows the current register values\n"); DebugPrintf(" dissect_script - Examines a script\n"); - DebugPrintf(" set_acc - Sets the accumulator\n"); DebugPrintf(" backtrace / bt - Dumps the send/self/super/call/calle/callb stack\n"); DebugPrintf(" trace / t / s - Executes one operation (no parameters) or several operations (specified as a parameter) \n"); DebugPrintf(" stepover / p - Executes one operation, skips over call/send\n"); @@ -2322,27 +2320,6 @@ bool Console::cmdScriptSteps(int argc, const char **argv) { return true; } -bool Console::cmdSetAccumulator(int argc, const char **argv) { - if (argc != 2) { - DebugPrintf("Sets the accumulator.\n"); - DebugPrintf("Usage: %s
\n", argv[0]); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - return true; - } - - reg_t val; - - if (parse_reg_t(_engine->_gamestate, argv[1], &val, false)) { - DebugPrintf("Invalid address passed.\n"); - DebugPrintf("Check the \"addresses\" command on how to use addresses\n"); - return true; - } - - _engine->_gamestate->r_acc = val; - - return true; -} - bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); diff --git a/engines/sci/console.h b/engines/sci/console.h index f8a2768f35..c180875364 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -118,7 +118,6 @@ private: bool cmdAddresses(int argc, const char **argv); bool cmdRegisters(int argc, const char **argv); bool cmdDissectScript(int argc, const char **argv); - bool cmdSetAccumulator(int argc, const char **argv); bool cmdBacktrace(int argc, const char **argv); bool cmdTrace(int argc, const char **argv); bool cmdStepOver(int argc, const char **argv); -- cgit v1.2.3 From aa9b9dd08fb8a56685d30995661773cdc87eb546 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 20:09:51 +0000 Subject: SCI: Separated the code for initializing script classes from the code for initializing script objects svn-id: r50390 --- engines/sci/engine/script.cpp | 154 ++++++++++++++++++++------------------- engines/sci/engine/seg_manager.h | 1 + 2 files changed, 79 insertions(+), 76 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 03234bea1d..800460bfc2 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -176,94 +176,95 @@ void SegManager::scriptInitialiseLocals(SegmentId segmentId) { } } -void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { +void SegManager::scriptInitialiseClasses(SegmentId seg) { Script *scr = getScript(seg); - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); const byte *seeker = 0; - int objType; - reg_t addr; - - // The script is initialized in 2 passes. - // Pass 1: creates a lookup table of all used classes - // Pass 2: loads classes and objects - - for (uint16 pass = 0; pass <= 1; pass++) { - uint16 objLength = 0; - seeker = scr->_buf + (oldScriptHeader ? 2 : 0); - - do { - objType = READ_SCI11ENDIAN_UINT16(seeker); - if (!objType) - break; - - objLength = READ_SCI11ENDIAN_UINT16(seeker + 2); - seeker += 4; // skip header - addr = make_reg(seg, seeker - scr->_buf); - - switch (objType) { - case SCI_OBJ_OBJECT: - case SCI_OBJ_CLASS: - if (pass == 0 && objType == SCI_OBJ_CLASS) { - int species = READ_SCI11ENDIAN_UINT16(seeker + 8); // SCRIPT_OBJECT_MAGIC_OFFSET - - if (species == (int)classTableSize()) { - // Happens in the LSL2 demo - warning("Applying workaround for an off-by-one invalid species access"); - resizeClassTable(classTableSize() + 1); - } else if (species < 0 || species > (int)classTableSize()) { - error("Invalid species %d(0x%x) not in interval " - "[0,%d) while instantiating script at segment %d\n", - species, species, classTableSize(), - seg); - return; - } - - setClassOffset(species, make_reg(seg, seeker - scr->_buf + 8)); - } else if (pass == 1) { - Object *obj = scr->scriptObjInit(addr); - obj->initSpecies(this, addr); - - if (!obj->initBaseObject(this, addr)) { - // Script 202 of KQ5 French has an invalid object - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); - } - } - break; + uint16 mult = 0; + + if (getSciVersion() >= SCI_VERSION_1_1) { + seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + mult = 2; + } else { + seeker = scr->findBlock(SCI_OBJ_CLASS); + mult = 1; + } - default: - break; - } + if (!seeker) + return; + + while (true) { + // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234) + uint16 marker = READ_SCI11ENDIAN_UINT16(seeker); + bool isClass; + uint16 classpos = seeker - scr->_buf; + int16 species; + + if (!marker) + break; + + if (getSciVersion() >= SCI_VERSION_1_1) { + isClass = (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass); // -info- selector + species = READ_SCI11ENDIAN_UINT16(seeker + 10); + } else { + isClass = (marker == SCI_OBJ_CLASS); + species = READ_SCI11ENDIAN_UINT16(seeker + 12); + classpos += 12; + } + + if (isClass) { + // WORKAROUND for an invalid species access in the demo of LSL2 + if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)classTableSize()) + resizeClassTable(classTableSize() + 1); - seeker += objLength - 4; - } while (objType != 0 && (uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2); - } // for + if (species < 0 || species >= (int)classTableSize()) + error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n", + species, species, classTableSize(), scr->_nr); + + setClassOffset(species, make_reg(seg, classpos)); + } + + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult; + } } -void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { +void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart; - uint16 entrySize = READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; - seeker += entrySize; // skip first entry - seeker += 4; // skip header + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + const byte *seeker = scr->_buf + (oldScriptHeader ? 2 : 0); - while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - if (READ_SCI11ENDIAN_UINT16(seeker + 14) & kInfoFlagClass) { // -info- selector - int classpos = seeker - scr->_buf; - int species = READ_SCI11ENDIAN_UINT16(seeker + 10); - - if (species < 0 || species >= (int)_classTable.size()) { - error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d", - species, species, _classTable.size(), scr->_nr); - return; + do { + uint16 objType = READ_SCI11ENDIAN_UINT16(seeker); + if (!objType) + break; + + switch (objType) { + case SCI_OBJ_OBJECT: + case SCI_OBJ_CLASS: + { + reg_t addr = make_reg(seg, seeker - scr->_buf + 4); + Object *obj = scr->scriptObjInit(addr); + obj->initSpecies(this, addr); + + if (!obj->initBaseObject(this, addr)) { + // Script 202 of KQ5 French has an invalid object. This is non-fatal. + warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + scr->scriptObjRemove(addr); + } } + break; - setClassOffset(species, make_reg(seg, classpos)); + default: + break; } - seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; - } - seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); + } while ((uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2); +} + +void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { + Script *scr = getScript(seg); + const byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { reg_t reg = make_reg(seg, seeker - scr->_buf); Object *obj = scr->scriptObjInit(reg); @@ -311,6 +312,7 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNu scr->init(scriptNum, resMan); scr->load(resMan); segMan->scriptInitialiseLocals(segmentId); + segMan->scriptInitialiseClasses(segmentId); if (getSciVersion() >= SCI_VERSION_1_1) { segMan->scriptInitialiseObjectsSci11(segmentId); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 037f3f0819..1ed01e2c6b 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -426,6 +426,7 @@ public: */ reg_t findObjectByName(const Common::String &name, int index = -1); + void scriptInitialiseClasses(SegmentId seg); void scriptInitialiseObjectsSci0(SegmentId seg); void scriptInitialiseObjectsSci11(SegmentId seg); -- cgit v1.2.3 From 1537d6129964732b03aae5186e9bc3e01c164817 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 20:11:15 +0000 Subject: SCI: added alias for bplist ("bl") and bpdel ("bc"), added capability of deleting all breakpoints by using "bc *" svn-id: r50391 --- engines/sci/console.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f5a47db281..958f43ee6c 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -175,8 +175,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { // Breakpoints DCmd_Register("bp_list", WRAP_METHOD(Console, cmdBreakpointList)); DCmd_Register("bplist", WRAP_METHOD(Console, cmdBreakpointList)); // alias + DCmd_Register("bl", WRAP_METHOD(Console, cmdBreakpointList)); // alias DCmd_Register("bp_del", WRAP_METHOD(Console, cmdBreakpointDelete)); DCmd_Register("bpdel", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias + DCmd_Register("bc", WRAP_METHOD(Console, cmdBreakpointDelete)); // alias DCmd_Register("bp_exec_method", WRAP_METHOD(Console, cmdBreakpointExecMethod)); DCmd_Register("bpx", WRAP_METHOD(Console, cmdBreakpointExecMethod)); // alias DCmd_Register("bp_exec_function", WRAP_METHOD(Console, cmdBreakpointExecFunction)); @@ -391,8 +393,8 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" go - Executes the script\n"); DebugPrintf("\n"); DebugPrintf("Breakpoints:\n"); - DebugPrintf(" bp_list / bplist - Lists the current breakpoints\n"); - DebugPrintf(" bp_del / bpdel - Deletes a breakpoint with the specified index\n"); + DebugPrintf(" bp_list / bplist / bl - Lists the current breakpoints\n"); + DebugPrintf(" bp_del / bpdel / bc - Deletes a breakpoint with the specified index\n"); DebugPrintf(" bp_exec_method / bpx - Sets a breakpoint on the execution of the specified method\n"); DebugPrintf(" bp_exec_function / bpe - Sets a breakpoint on the execution of the specified exported function\n"); DebugPrintf("\n"); @@ -2669,6 +2671,9 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { i++; } + if (!i) + DebugPrintf(" No breakpoints defined.\n"); + return true; } @@ -2676,6 +2681,13 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Deletes a breakpoint with the specified index.\n"); DebugPrintf("Usage: %s \n", argv[0]); + DebugPrintf(" * will remove all breakpoints\n"); + return true; + } + + if (strcmp(argv[1], "*") == 0) { + g_debugState._breakpoints.clear(); + g_debugState._activeBreakpointTypes = 0; return true; } -- cgit v1.2.3 From e6a9a9da823b6c8fef25f2949d21525d8a229b9c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 20:22:09 +0000 Subject: Silenced a false positive in MSVC about a potentially uninitialized variable svn-id: r50392 --- engines/sci/graphics/ports.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 6e53ef44c4..36f84c3582 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -55,7 +55,7 @@ GfxPorts::~GfxPorts() { } void GfxPorts::init(bool usesOldGfxFunctions, GfxPaint16 *paint16, GfxText16 *text16) { - int16 offTop; + int16 offTop = 10; _usesOldGfxFunctions = usesOldGfxFunctions; _paint16 = paint16; -- cgit v1.2.3 From 0436f2823d7c83fa76d68fba3c18a7fcc4a29173 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 20:38:41 +0000 Subject: SCI: added additional output to vmvars command svn-id: r50395 --- engines/sci/console.cpp | 36 ++++++++++++++++++++++++++++++++++-- engines/sci/console.h | 2 ++ 2 files changed, 36 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 958f43ee6c..37d859cc7c 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2054,9 +2054,11 @@ bool Console::cmdVMVars(int argc, const char **argv) { if (!setValue) { if (varType == 4) - DebugPrintf("%s == %04x:%04x\n", varNames[varType], PRINT_REG(*curValue)); + DebugPrintf("%s == %04x:%04x", varNames[varType], PRINT_REG(*curValue)); else - DebugPrintf("%s var %d == %04x:%04x\n", varNames[varType], varIndex, PRINT_REG(*curValue)); + DebugPrintf("%s var %d == %04x:%04x", varNames[varType], varIndex, PRINT_REG(*curValue)); + printBasicVarInfo(*curValue); + DebugPrintf("\n"); } else { if (parse_reg_t(s, setValue, curValue, true)) { DebugPrintf("Invalid value/address passed.\n"); @@ -3207,6 +3209,36 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV return 0; } +void Console::printBasicVarInfo(reg_t variable) { + int segType = g_sci->getKernel()->findRegType(variable); + SegManager *segMan = g_sci->getEngineState()->_segMan; + + segType &= KSIG_ARITHMETIC | KSIG_OBJECT | KSIG_REF | KSIG_NODE | KSIG_LIST; + + switch (segType) { + case KSIG_ARITHMETIC: { + uint16 content = variable.toUint16(); + if (content >= 10) + DebugPrintf(" (%dd)", content); + break; + } + case KSIG_OBJECT: + DebugPrintf(" (object '%s')", segMan->getObjectName(variable)); + break; + case KSIG_REF: + DebugPrintf(" (reference)"); + break; + case KSIG_NODE: + DebugPrintf(" (node)"); + break; + case KSIG_LIST: + DebugPrintf(" (list)"); + break; + default: + DebugPrintf(" (???)"); + } +} + void Console::printList(List *list) { reg_t pos = list->first; reg_t my_prev = NULL_REG; diff --git a/engines/sci/console.h b/engines/sci/console.h index c180875364..2948e348d8 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -146,6 +146,8 @@ private: bool cmdViewActiveObject(int argc, const char **argv); bool cmdViewAccumulatorObject(int argc, const char **argv); + void printBasicVarInfo(reg_t variable); + bool segmentInfo(int nr); void printList(List *list); int printNode(reg_t addr); -- cgit v1.2.3 From bb992b0b93f3ee9dfad6524fd0721a350f12085a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 20:38:43 +0000 Subject: SCI: Moved all the script-related code inside script.cpp/.h, and all script opcode-related code inside vm.cpp/.h svn-id: r50396 --- engines/sci/engine/kscripts.cpp | 2 + engines/sci/engine/script.cpp | 434 ++++++++++++++++++++++++++++--------- engines/sci/engine/script.h | 346 ++++++++++++++++------------- engines/sci/engine/seg_manager.cpp | 44 +++- engines/sci/engine/seg_manager.h | 5 +- engines/sci/engine/segment.cpp | 326 +--------------------------- engines/sci/engine/segment.h | 176 --------------- engines/sci/engine/vm.cpp | 80 +++++++ engines/sci/engine/vm.h | 178 +++++++++++++-- 9 files changed, 809 insertions(+), 782 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 4e6be15760..8ea0ec2019 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -25,6 +25,8 @@ #include "sci/sci.h" #include "sci/resource.h" +#include "sci/engine/seg_manager.h" +#include "sci/engine/script.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" #include "sci/engine/kernel.h" diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 800460bfc2..748a8f9140 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -35,127 +35,353 @@ namespace Sci { -#define END Script_None - -opcode_format g_opcode_formats[128][4] = { - /*00*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*04*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*08*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*0C*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*10*/ - {Script_None}, {Script_None}, {Script_None}, {Script_None}, - /*14*/ - {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END}, - /*18*/ - {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None}, - /*1C*/ - {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END}, - /*20*/ - {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END}, - /*24 (24=ret)*/ - {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid}, - /*28*/ - {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END}, - /*2C*/ - {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid}, - /*30*/ - {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, - /*34*/ - {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, - /*38*/ - {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None}, - /*3C*/ - {Script_None}, {Script_None}, {Script_None}, {Script_Word}, - /*40-4F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*50-5F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*60-6F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - /*70-7F*/ - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, - {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END} -}; -#undef END - -// TODO: script_adjust_opcode_formats should probably be part of the -// constructor (?) of a VirtualMachine or a ScriptManager class. -void script_adjust_opcode_formats() { - if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) { - g_opcode_formats[op_lofsa][0] = Script_Offset; - g_opcode_formats[op_lofss][0] = Script_Offset; +Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { + _nr = 0; + _buf = NULL; + _bufSize = 0; + _scriptSize = 0; + _heapSize = 0; + + _synonyms = NULL; + _heapStart = NULL; + _exportTable = NULL; + + _localsOffset = 0; + _localsSegment = 0; + _localsBlock = NULL; + _localsCount = 0; + + _markedAsDeleted = false; +} + +Script::~Script() { + freeScript(); +} + +void Script::freeScript() { + free(_buf); + _buf = NULL; + _bufSize = 0; + + _objects.clear(); +} + +void Script::init(int script_nr, ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); + + _localsOffset = 0; + _localsBlock = NULL; + _localsCount = 0; + + _markedAsDeleted = false; + + _nr = script_nr; + _buf = 0; + _heapStart = 0; + + _scriptSize = script->size; + _bufSize = script->size; + _heapSize = 0; + + _lockers = 1; + + if (getSciVersion() == SCI_VERSION_0_EARLY) { + _bufSize += READ_LE_UINT16(script->data) * 2; + } else if (getSciVersion() >= SCI_VERSION_1_1) { + /** + * In SCI11, the heap was in a separate space from the script. + * We append it to the end of the script, and adjust addressing accordingly. + * However, since we address the heap with a 16-bit pointer, the combined + * size of the stack and the heap must be 64KB. So far this has worked + * for SCI11, SCI2 and SCI21 games. SCI3 games use a different script format, + * and theoretically they can exceed the 64KB boundary using relocation. + */ + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); + _bufSize += heap->size; + _heapSize = heap->size; + + // Ensure that the start of the heap resource can be word-aligned. + if (script->size & 2) { + _bufSize++; + _scriptSize++; + } + + // As mentioned above, the script and the heap together should not exceed 64KB + if (script->size + heap->size > 65535) + error("Script and heap sizes combined exceed 64K. This means a fundamental " + "design bug was made regarding SCI1.1 and newer games.\nPlease " + "report this error to the ScummVM team"); + } +} + +void Script::load(ResourceManager *resMan) { + Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); + assert(script != 0); + + _buf = (byte *)malloc(_bufSize); + assert(_buf); + + assert(_bufSize >= script->size); + memcpy(_buf, script->data, script->size); + + if (getSciVersion() >= SCI_VERSION_1_1) { + Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); + assert(heap != 0); + + _heapStart = _buf + _scriptSize; + + assert(_bufSize - _scriptSize <= heap->size); + memcpy(_heapStart, heap->data, heap->size); + } + + _exportTable = 0; + _numExports = 0; + _synonyms = 0; + _numSynonyms = 0; + + if (getSciVersion() >= SCI_VERSION_1_1) { + if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table? + _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); + } + _localsOffset = _scriptSize + 4; + _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); + } else { + _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); + if (_exportTable) { + _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1); + _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer) + } + _synonyms = findBlock(SCI_OBJ_SYNONYMS); + if (_synonyms) { + _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; + _synonyms += 4; // skip header + } + const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS); + if (localsBlock) { + _localsOffset = localsBlock - _buf + 4; + _localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size + } } -#ifdef ENABLE_SCI32 - // In SCI32, some arguments are now words instead of bytes - if (getSciVersion() >= SCI_VERSION_2) { - g_opcode_formats[op_calle][2] = Script_Word; - g_opcode_formats[op_callk][1] = Script_Word; - g_opcode_formats[op_super][1] = Script_Word; - g_opcode_formats[op_send][0] = Script_Word; - g_opcode_formats[op_self][0] = Script_Word; - g_opcode_formats[op_call][1] = Script_Word; - g_opcode_formats[op_callb][1] = Script_Word; + if (getSciVersion() > SCI_VERSION_0_EARLY) { + // Does the script actually have locals? If not, set the locals offset to 0 + if (!_localsCount) + _localsOffset = 0; + + if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { + error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); + _localsCount = (_bufSize - _localsOffset) >> 1; + } + } else { + // Old script block. There won't be a localvar block in this case. + // Instead, the script starts with a 16 bit int specifying the + // number of locals we need; these are then allocated and zeroed. + _localsCount = READ_LE_UINT16(_buf); + _localsOffset = -_localsCount * 2; // Make sure it's invalid } -#endif } -void SegManager::createClassTable() { - Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); +Object *Script::allocateObject(uint16 offset) { + return &_objects[offset]; +} + +Object *Script::getObject(uint16 offset) { + if (_objects.contains(offset)) + return &_objects[offset]; + else + return 0; +} + +const Object *Script::getObject(uint16 offset) const { + if (_objects.contains(offset)) + return &_objects[offset]; + else + return 0; +} - if (!vocab996) - error("SegManager: failed to open vocab 996"); +Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { + Object *obj; + + if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) + obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + + VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); + + obj = allocateObject(obj_pos.offset); + + VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); + + obj->init(_buf, obj_pos, fullObjectInit); + + return obj; +} + +void Script::scriptObjRemove(reg_t obj_pos) { + if (getSciVersion() < SCI_VERSION_1_1) + obj_pos.offset += 8; + + _objects.erase(obj_pos.toUint16()); +} - int totalClasses = vocab996->size >> 2; - _classTable.resize(totalClasses); +// This helper function is used by Script::relocateLocal and Object::relocate +// Duplicate in segment.cpp and script.cpp +static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { + int rel = location - block_location; - for (uint16 classNr = 0; classNr < totalClasses; classNr++) { - uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2); + if (rel < 0) + return false; - _classTable[classNr].reg = NULL_REG; - _classTable[classNr].script = scriptNr; + uint idx = rel >> 1; + + if (idx >= block.size()) + return false; + + if (rel & 1) { + error("Attempt to relocate odd variable #%d.5e (relative to %04x)\n", idx, block_location); + return false; } + block[idx].segment = segment; // Perform relocation + if (getSciVersion() >= SCI_VERSION_1_1) + block[idx].offset += scriptSize; - _resMan->unlockResource(vocab996); + return true; } -reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) { - if (classnr == 0xffff) - return NULL_REG; +bool Script::relocateLocal(SegmentId segment, int location) { + if (_localsBlock) + return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize); + else + return false; +} - if (classnr < 0 || (int)_classTable.size() <= classnr || _classTable[classnr].script < 0) { - error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classTable.size()); - return NULL_REG; - } else { - Class *the_class = &_classTable[classnr]; - if (!the_class->reg.segment) { - getScriptSegment(the_class->script, lock); +void Script::relocate(reg_t block) { + byte *heap = _buf; + uint16 heapSize = (uint16)_bufSize; + uint16 heapOffset = 0; - if (!the_class->reg.segment) { - error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); - return NULL_REG; - } - } else - if (caller.segment != the_class->reg.segment) - getScript(the_class->reg.segment)->incrementLockers(); + if (getSciVersion() >= SCI_VERSION_1_1) { + heap = _heapStart; + heapSize = (uint16)_heapSize; + heapOffset = _scriptSize; + } + + VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize, + "Relocation block outside of script\n"); + + int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); + int exportIndex = 0; + int pos = 0; + + for (int i = 0; i < count; i++) { + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + // This occurs in SCI01/SCI1 games where usually one export value + // is zero. It seems that in this situation, we should skip the + // export and move to the next one, though the total count of valid + // exports remains the same + if (!pos) { + exportIndex++; + pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; + if (!pos) + error("Script::relocate(): Consecutive zero exports found"); + } + + // In SCI0-SCI1, script local variables, objects and code are relocated. We only relocate + // locals and objects here, and ignore relocation of code blocks. In SCI1.1 and newer + // versions, only locals and objects are relocated. + if (!relocateLocal(block.segment, pos)) { + // Not a local? It's probably an object or code block. If it's an object, relocate it. + const ObjMap::iterator end = _objects.end(); + for (ObjMap::iterator it = _objects.begin(); it != end; ++it) + if (it->_value.relocate(block.segment, pos, _scriptSize)) + break; + } + + exportIndex++; + } +} + +void Script::incrementLockers() { + _lockers++; +} + +void Script::decrementLockers() { + if (_lockers > 0) + _lockers--; +} + +int Script::getLockers() const { + return _lockers; +} + +void Script::setLockers(int lockers) { + _lockers = lockers; +} + +uint16 Script::validateExportFunc(int pubfunct) { + bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); - return the_class->reg; + if (_numExports <= pubfunct) { + error("validateExportFunc(): pubfunct is invalid"); + return 0; } + + if (exportsAreWide) + pubfunct *= 2; + uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); + VERIFY(offset < _bufSize, "invalid export function pointer"); + + return offset; +} + +byte *Script::findBlock(int type) { + byte *buf = _buf; + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + + if (oldScriptHeader) + buf += 2; + + do { + int seekerType = READ_LE_UINT16(buf); + + if (seekerType == 0) + break; + if (seekerType == type) + return buf; + + int seekerSize = READ_LE_UINT16(buf + 2); + assert(seekerSize > 0); + buf += seekerSize; + } while (1); + + return NULL; +} + +// memory operations + +void Script::mcpyInOut(int dst, const void *src, size_t n) { + if (_buf) { + assert(dst + n <= _bufSize); + memcpy(_buf + dst, src, n); + } +} + +bool Script::isValidOffset(uint16 offset) const { + return offset < _bufSize; +} + +SegmentRef Script::dereference(reg_t pointer) { + if (pointer.offset > _bufSize) { + error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", + PRINT_REG(pointer), (uint)_bufSize); + return SegmentRef(); + } + + SegmentRef ret; + ret.isRaw = true; + ret.maxSize = _bufSize - pointer.offset; + ret.raw = _buf + pointer.offset; + return ret; } void SegManager::scriptInitialiseLocals(SegmentId segmentId) { diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index fe92dabe58..62d2228c9a 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -27,6 +27,7 @@ #define SCI_ENGINE_SCRIPT_H #include "common/str.h" +#include "sci/engine/segment.h" namespace Sci { @@ -49,160 +50,205 @@ enum ScriptObjectTypes { SCI_OBJ_LOCALVARS }; -// Opcode formats -enum opcode_format { - Script_Invalid = -1, - Script_None = 0, - Script_Byte, - Script_SByte, - Script_Word, - Script_SWord, - Script_Variable, - Script_SVariable, - Script_SRelative, - Script_Property, - Script_Global, - Script_Local, - Script_Temp, - Script_Param, - Script_Offset, - Script_End -}; +typedef Common::HashMap ObjMap; + +class Script : public SegmentObj { +public: + int _nr; /**< Script number */ + byte *_buf; /**< Static data buffer, or NULL if not used */ + byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ + + uint32 getScriptSize() { return _scriptSize; } + uint32 getHeapSize() { return _heapSize; } + uint32 getBufSize() { return _bufSize; } + +protected: + int _lockers; /**< Number of classes and objects that require this script */ + +private: + size_t _scriptSize; + size_t _heapSize; + uint16 _bufSize; + + const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ + uint16 _numExports; /**< Number of entries in the exports table */ + + const byte *_synonyms; /**< Synonyms block or 0 if not present*/ + uint16 _numSynonyms; /**< Number of entries in the synonyms block */ + + int _localsOffset; + uint16 _localsCount; + +public: + /** + * Table for objects, contains property variables. + * Indexed by the TODO offset. + */ + ObjMap _objects; + + int getLocalsOffset() const { return _localsOffset; } + uint16 getLocalsCount() const { return _localsCount; } + SegmentId _localsSegment; /**< The local variable segment */ + LocalVariables *_localsBlock; + + bool _markedAsDeleted; + +public: + Script(); + ~Script(); + + void freeScript(); + void init(int script_nr, ResourceManager *resMan); + void load(ResourceManager *resMan); + + virtual bool isValidOffset(uint16 offset) const; + virtual SegmentRef dereference(reg_t pointer); + virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; + virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); + virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; + virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + + virtual void saveLoadWithSerializer(Common::Serializer &ser); + + Object *allocateObject(uint16 offset); + Object *getObject(uint16 offset); + const Object *getObject(uint16 offset) const; + + /** + * Initializes an object within the segment manager + * @param obj_pos Location (segment, offset) of the object. It must + * point to the beginning of the script/class block + * (as opposed to what the VM considers to be the + * object location) + * @returns A newly created Object describing the object, + * stored within the relevant script + */ + Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); + + /** + * Removes a script object + * @param obj_pos Location (segment, offset) of the object. + */ + void scriptObjRemove(reg_t obj_pos); -enum sci_opcodes { - op_bnot = 0x00, // 000 - op_add = 0x01, // 001 - op_sub = 0x02, // 002 - op_mul = 0x03, // 003 - op_div = 0x04, // 004 - op_mod = 0x05, // 005 - op_shr = 0x06, // 006 - op_shl = 0x07, // 007 - op_xor = 0x08, // 008 - op_and = 0x09, // 009 - op_or = 0x0a, // 010 - op_neg = 0x0b, // 011 - op_not = 0x0c, // 012 - op_eq_ = 0x0d, // 013 - op_ne_ = 0x0e, // 014 - op_gt_ = 0x0f, // 015 - op_ge_ = 0x10, // 016 - op_lt_ = 0x11, // 017 - op_le_ = 0x12, // 018 - op_ugt_ = 0x13, // 019 - op_uge_ = 0x14, // 020 - op_ult_ = 0x15, // 021 - op_ule_ = 0x16, // 022 - op_bt = 0x17, // 023 - op_bnt = 0x18, // 024 - op_jmp = 0x19, // 025 - op_ldi = 0x1a, // 026 - op_push = 0x1b, // 027 - op_pushi = 0x1c, // 028 - op_toss = 0x1d, // 029 - op_dup = 0x1e, // 030 - op_link = 0x1f, // 031 - op_call = 0x20, // 032 - op_callk = 0x21, // 033 - op_callb = 0x22, // 034 - op_calle = 0x23, // 035 - op_ret = 0x24, // 036 - op_send = 0x25, // 037 - // dummy 0x26, // 038 - // dummy 0x27, // 039 - op_class = 0x28, // 040 - // dummy 0x29, // 041 - op_self = 0x2a, // 042 - op_super = 0x2b, // 043 - op_rest = 0x2c, // 044 - op_lea = 0x2d, // 045 - op_selfID = 0x2e, // 046 - // dummy 0x2f // 047 - op_pprev = 0x30, // 048 - op_pToa = 0x31, // 049 - op_aTop = 0x32, // 050 - op_pTos = 0x33, // 051 - op_sTop = 0x34, // 052 - op_ipToa = 0x35, // 053 - op_dpToa = 0x36, // 054 - op_ipTos = 0x37, // 055 - op_dpTos = 0x38, // 056 - op_lofsa = 0x39, // 057 - op_lofss = 0x3a, // 058 - op_push0 = 0x3b, // 059 - op_push1 = 0x3c, // 060 - op_push2 = 0x3d, // 061 - op_pushSelf = 0x3e, // 062 - op_line = 0x3f, // 063 - op_lag = 0x40, // 064 - op_lal = 0x41, // 065 - op_lat = 0x42, // 066 - op_lap = 0x43, // 067 - op_lsg = 0x44, // 068 - op_lsl = 0x45, // 069 - op_lst = 0x46, // 070 - op_lsp = 0x47, // 071 - op_lagi = 0x48, // 072 - op_lali = 0x49, // 073 - op_lati = 0x4a, // 074 - op_lapi = 0x4b, // 075 - op_lsgi = 0x4c, // 076 - op_lsli = 0x4d, // 077 - op_lsti = 0x4e, // 078 - op_lspi = 0x4f, // 079 - op_sag = 0x50, // 080 - op_sal = 0x51, // 081 - op_sat = 0x52, // 082 - op_sap = 0x53, // 083 - op_ssg = 0x54, // 084 - op_ssl = 0x55, // 085 - op_sst = 0x56, // 086 - op_ssp = 0x57, // 087 - op_sagi = 0x58, // 088 - op_sali = 0x59, // 089 - op_sati = 0x5a, // 090 - op_sapi = 0x5b, // 091 - op_ssgi = 0x5c, // 092 - op_ssli = 0x5d, // 093 - op_ssti = 0x5e, // 094 - op_sspi = 0x5f, // 095 - op_plusag = 0x60, // 096 - op_plusal = 0x61, // 097 - op_plusat = 0x62, // 098 - op_plusap = 0x63, // 099 - op_plussg = 0x64, // 100 - op_plussl = 0x65, // 101 - op_plusst = 0x66, // 102 - op_plussp = 0x67, // 103 - op_plusagi = 0x68, // 104 - op_plusali = 0x69, // 105 - op_plusati = 0x6a, // 106 - op_plusapi = 0x6b, // 107 - op_plussgi = 0x6c, // 108 - op_plussli = 0x6d, // 109 - op_plussti = 0x6e, // 110 - op_plusspi = 0x6f, // 111 - op_minusag = 0x70, // 112 - op_minusal = 0x71, // 113 - op_minusat = 0x72, // 114 - op_minusap = 0x73, // 115 - op_minussg = 0x74, // 116 - op_minussl = 0x75, // 117 - op_minusst = 0x76, // 118 - op_minussp = 0x77, // 119 - op_minusagi = 0x78, // 120 - op_minusali = 0x79, // 121 - op_minusati = 0x7a, // 122 - op_minusapi = 0x7b, // 123 - op_minussgi = 0x7c, // 124 - op_minussli = 0x7d, // 125 - op_minussti = 0x7e, // 126 - op_minusspi = 0x7f // 127 + /** + * Processes a relocation block witin a script + * This function is idempotent, but it must only be called after all + * objects have been instantiated, or a run-time error will occur. + * @param obj_pos Location (segment, offset) of the block + * @return Location of the relocation block + */ + void relocate(reg_t block); + +private: + bool relocateLocal(SegmentId segment, int location); + +public: + // script lock operations + + /** Increments the number of lockers of this script by one. */ + void incrementLockers(); + + /** Decrements the number of lockers of this script by one. */ + void decrementLockers(); + + /** + * Retrieves the number of locks held on this script. + * @return the number of locks held on the previously identified script + */ + int getLockers() const; + + /** Sets the number of locks held on this script. */ + void setLockers(int lockers); + + /** + * Retrieves a pointer to the exports of this script + * @return pointer to the exports. + */ + const uint16 *getExportTable() const { return _exportTable; } + + /** + * Retrieves the number of exports of script. + * @return the number of exports of this script + */ + uint16 getExportsNr() const { return _numExports; } + + /** + * Retrieves a pointer to the synonyms associated with this script + * @return pointer to the synonyms, in non-parsed format. + */ + const byte *getSynonyms() const { return _synonyms; } + + /** + * Retrieves the number of synonyms associated with this script. + * @return the number of synonyms associated with this script + */ + uint16 getSynonymsNr() const { return _numSynonyms; } + + /** + * Validate whether the specified public function is exported by + * the script in the specified segment. + * @param pubfunct Index of the function to validate + * @return NULL if the public function is invalid, its + * offset into the script's segment otherwise + */ + uint16 validateExportFunc(int pubfunct); + + /** + * Marks the script as deleted. + * This will not actually delete the script. If references remain present on the + * heap or the stack, the script will stay in memory in a quasi-deleted state until + * either unreachable (resulting in its eventual deletion) or reloaded (resulting + * in its data being updated). + */ + void markDeleted() { + _markedAsDeleted = true; + } + + /** + * Determines whether the script is marked as being deleted. + */ + bool isMarkedAsDeleted() const { + return _markedAsDeleted; + } + + /** + * Copies a byte string into a script's heap representation. + * @param dst script-relative offset of the destination area + * @param src pointer to the data source location + * @param n number of bytes to copy + */ + void mcpyInOut(int dst, const void *src, size_t n); + + /** + * Finds the pointer where a block of a specific type starts from + */ + byte *findBlock(int type); }; -extern opcode_format g_opcode_formats[128][4]; +/** + * Makes sure that a script and its superclasses get loaded to the heap. + * If the script already has been loaded, only the number of lockers is + * increased. All scripts containing superclasses of this script are loaded + * recursively as well, unless 'recursive' is set to zero. The + * complementary function is "script_uninstantiate()" below. + * @param[in] resMan The resource manager + * @param[in] segMan The segment manager + * @param[in] script_nr The script number to load + * @return The script's segment ID or 0 if out of heap + */ +int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr); -void script_adjust_opcode_formats(); +/** + * Decreases the numer of lockers of a script and unloads it if that number + * reaches zero. + * This function will recursively unload scripts containing its + * superclasses, if those aren't locked by other scripts as well. + * @param[in] segMan The segment manager + * @param[in] version The SCI version to use + * @param[in] script_nr The script number that is requestet to be unloaded + */ +void script_uninstantiate(SegManager *segMan, int script_nr); } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 9394e717ec..35ac0a5f69 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -26,6 +26,7 @@ #include "sci/sci.h" #include "sci/engine/seg_manager.h" #include "sci/engine/state.h" +#include "sci/engine/script.h" namespace Sci { @@ -837,7 +838,6 @@ Common::String SegManager::getString(reg_t pointer, int entries) { return ret; } - byte *SegManager::allocDynmem(int size, const char *descr, reg_t *addr) { SegmentId seg; SegmentObj *mobj = allocSegment(new DynMem(), &seg); @@ -949,4 +949,46 @@ void SegManager::freeString(reg_t addr) { #endif +void SegManager::createClassTable() { + Resource *vocab996 = _resMan->findResource(ResourceId(kResourceTypeVocab, 996), 1); + + if (!vocab996) + error("SegManager: failed to open vocab 996"); + + int totalClasses = vocab996->size >> 2; + _classTable.resize(totalClasses); + + for (uint16 classNr = 0; classNr < totalClasses; classNr++) { + uint16 scriptNr = READ_SCI11ENDIAN_UINT16(vocab996->data + classNr * 4 + 2); + + _classTable[classNr].reg = NULL_REG; + _classTable[classNr].script = scriptNr; + } + + _resMan->unlockResource(vocab996); +} + +reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller) { + if (classnr == 0xffff) + return NULL_REG; + + if (classnr < 0 || (int)_classTable.size() <= classnr || _classTable[classnr].script < 0) { + error("[VM] Attempt to dereference class %x, which doesn't exist (max %x)", classnr, _classTable.size()); + return NULL_REG; + } else { + Class *the_class = &_classTable[classnr]; + if (!the_class->reg.segment) { + getScriptSegment(the_class->script, lock); + + if (!the_class->reg.segment) { + error("[VM] Trying to instantiate class %x by instantiating script 0x%x (%03d) failed;", classnr, the_class->script, the_class->script); + return NULL_REG; + } + } else + if (caller.segment != the_class->reg.segment) + getScript(the_class->reg.segment)->incrementLockers(); + + return the_class->reg; + } +} } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 1ed01e2c6b..19fd06f596 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -28,7 +28,9 @@ #include "common/scummsys.h" #include "common/serializer.h" +#include "sci/engine/script.h" #include "sci/engine/vm.h" +#include "sci/engine/vm_types.h" #include "sci/engine/segment.h" namespace Sci { @@ -42,8 +44,6 @@ namespace Sci { error("%s, line, %d, %s", __FILE__, __LINE__, msg); \ } - - /** * Parameters for getScriptSegment(). */ @@ -53,6 +53,7 @@ enum ScriptLoadType { SCRIPT_GET_LOCK = 3 /**< Load, if neccessary, and lock */ }; +class Script; class SegManager : public Common::Serializable { friend class Console; diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 13c7904726..2bbedf2dcf 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -86,196 +86,8 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) { return mem; } -Script::Script() : SegmentObj(SEG_TYPE_SCRIPT) { - _nr = 0; - _buf = NULL; - _bufSize = 0; - _scriptSize = 0; - _heapSize = 0; - - _synonyms = NULL; - _heapStart = NULL; - _exportTable = NULL; - - _localsOffset = 0; - _localsSegment = 0; - _localsBlock = NULL; - _localsCount = 0; - - _markedAsDeleted = false; -} - -Script::~Script() { - freeScript(); -} - -void Script::freeScript() { - free(_buf); - _buf = NULL; - _bufSize = 0; - - _objects.clear(); -} - -void Script::init(int script_nr, ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, script_nr), 0); - - _localsOffset = 0; - _localsBlock = NULL; - _localsCount = 0; - - _markedAsDeleted = false; - - _nr = script_nr; - _buf = 0; - _heapStart = 0; - - _scriptSize = script->size; - _bufSize = script->size; - _heapSize = 0; - - _lockers = 1; - - if (getSciVersion() == SCI_VERSION_0_EARLY) { - _bufSize += READ_LE_UINT16(script->data) * 2; - } else if (getSciVersion() >= SCI_VERSION_1_1) { - /** - * In SCI11, the heap was in a separate space from the script. - * We append it to the end of the script, and adjust addressing accordingly. - * However, since we address the heap with a 16-bit pointer, the combined - * size of the stack and the heap must be 64KB. So far this has worked - * for SCI11, SCI2 and SCI21 games. SCI3 games use a different script format, - * and theoretically they can exceed the 64KB boundary using relocation. - */ - Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); - _bufSize += heap->size; - _heapSize = heap->size; - - // Ensure that the start of the heap resource can be word-aligned. - if (script->size & 2) { - _bufSize++; - _scriptSize++; - } - - // As mentioned above, the script and the heap together should not exceed 64KB - if (script->size + heap->size > 65535) - error("Script and heap sizes combined exceed 64K. This means a fundamental " - "design bug was made regarding SCI1.1 and newer games.\nPlease " - "report this error to the ScummVM team"); - } -} - -void Script::load(ResourceManager *resMan) { - Resource *script = resMan->findResource(ResourceId(kResourceTypeScript, _nr), 0); - assert(script != 0); - - _buf = (byte *)malloc(_bufSize); - assert(_buf); - - assert(_bufSize >= script->size); - memcpy(_buf, script->data, script->size); - - if (getSciVersion() >= SCI_VERSION_1_1) { - Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, _nr), 0); - assert(heap != 0); - - _heapStart = _buf + _scriptSize; - - assert(_bufSize - _scriptSize <= heap->size); - memcpy(_heapStart, heap->data, heap->size); - } - - _exportTable = 0; - _numExports = 0; - _synonyms = 0; - _numSynonyms = 0; - - if (getSciVersion() >= SCI_VERSION_1_1) { - if (READ_LE_UINT16(_buf + 1 + 5) > 0) { // does the script have an export table? - _exportTable = (const uint16 *)(_buf + 1 + 5 + 2); - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable - 1); - } - _localsOffset = _scriptSize + 4; - _localsCount = READ_SCI11ENDIAN_UINT16(_buf + _localsOffset - 2); - } else { - _exportTable = (const uint16 *)findBlock(SCI_OBJ_EXPORTS); - if (_exportTable) { - _numExports = READ_SCI11ENDIAN_UINT16(_exportTable + 1); - _exportTable += 3; // skip header plus 2 bytes (_exportTable is a uint16 pointer) - } - _synonyms = findBlock(SCI_OBJ_SYNONYMS); - if (_synonyms) { - _numSynonyms = READ_SCI11ENDIAN_UINT16(_synonyms + 2) / 4; - _synonyms += 4; // skip header - } - const byte* localsBlock = findBlock(SCI_OBJ_LOCALVARS); - if (localsBlock) { - _localsOffset = localsBlock - _buf + 4; - _localsCount = (READ_LE_UINT16(_buf + _localsOffset - 2) - 4) >> 1; // half block size - } - } - - if (getSciVersion() > SCI_VERSION_0_EARLY) { - // Does the script actually have locals? If not, set the locals offset to 0 - if (!_localsCount) - _localsOffset = 0; - - if (_localsOffset + _localsCount * 2 + 1 >= (int)_bufSize) { - error("Locals extend beyond end of script: offset %04x, count %d vs size %d", _localsOffset, _localsCount, _bufSize); - _localsCount = (_bufSize - _localsOffset) >> 1; - } - } else { - // Old script block. There won't be a localvar block in this case. - // Instead, the script starts with a 16 bit int specifying the - // number of locals we need; these are then allocated and zeroed. - _localsCount = READ_LE_UINT16(_buf); - _localsOffset = -_localsCount * 2; // Make sure it's invalid - } -} - -Object *Script::allocateObject(uint16 offset) { - return &_objects[offset]; -} - -Object *Script::getObject(uint16 offset) { - if (_objects.contains(offset)) - return &_objects[offset]; - else - return 0; -} - -const Object *Script::getObject(uint16 offset) const { - if (_objects.contains(offset)) - return &_objects[offset]; - else - return 0; -} - -Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { - Object *obj; - - if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) - obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - - VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); - - obj = allocateObject(obj_pos.offset); - - VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); - - obj->init(_buf, obj_pos, fullObjectInit); - - return obj; -} - -void Script::scriptObjRemove(reg_t obj_pos) { - if (getSciVersion() < SCI_VERSION_1_1) - obj_pos.offset += 8; - - _objects.erase(obj_pos.toUint16()); -} - // This helper function is used by Script::relocateLocal and Object::relocate +// Duplicate in segment.cpp and script.cpp static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { int rel = location - block_location; @@ -298,148 +110,12 @@ static bool relocateBlock(Common::Array &block, int block_location, Segme return true; } -bool Script::relocateLocal(SegmentId segment, int location) { - if (_localsBlock) - return relocateBlock(_localsBlock->_locals, _localsOffset, segment, location, _scriptSize); - else - return false; -} - -void Script::relocate(reg_t block) { - byte *heap = _buf; - uint16 heapSize = (uint16)_bufSize; - uint16 heapOffset = 0; - - if (getSciVersion() >= SCI_VERSION_1_1) { - heap = _heapStart; - heapSize = (uint16)_heapSize; - heapOffset = _scriptSize; - } - - VERIFY(block.offset < (uint16)heapSize && READ_SCI11ENDIAN_UINT16(heap + block.offset) * 2 + block.offset < (uint16)heapSize, - "Relocation block outside of script\n"); - - int count = READ_SCI11ENDIAN_UINT16(heap + block.offset); - int exportIndex = 0; - int pos = 0; - - for (int i = 0; i < count; i++) { - pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - // This occurs in SCI01/SCI1 games where usually one export value - // is zero. It seems that in this situation, we should skip the - // export and move to the next one, though the total count of valid - // exports remains the same - if (!pos) { - exportIndex++; - pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - if (!pos) - error("Script::relocate(): Consecutive zero exports found"); - } - - // In SCI0-SCI1, script local variables, objects and code are relocated. We only relocate - // locals and objects here, and ignore relocation of code blocks. In SCI1.1 and newer - // versions, only locals and objects are relocated. - if (!relocateLocal(block.segment, pos)) { - // Not a local? It's probably an object or code block. If it's an object, relocate it. - const ObjMap::iterator end = _objects.end(); - for (ObjMap::iterator it = _objects.begin(); it != end; ++it) - if (it->_value.relocate(block.segment, pos, _scriptSize)) - break; - } - - exportIndex++; - } -} - -void Script::incrementLockers() { - _lockers++; -} - -void Script::decrementLockers() { - if (_lockers > 0) - _lockers--; -} - -int Script::getLockers() const { - return _lockers; -} - -void Script::setLockers(int lockers) { - _lockers = lockers; -} - -uint16 Script::validateExportFunc(int pubfunct) { - bool exportsAreWide = (g_sci->_features->detectLofsType() == SCI_VERSION_1_MIDDLE); - - if (_numExports <= pubfunct) { - error("validateExportFunc(): pubfunct is invalid"); - return 0; - } - - if (exportsAreWide) - pubfunct *= 2; - uint16 offset = READ_SCI11ENDIAN_UINT16(_exportTable + pubfunct); - VERIFY(offset < _bufSize, "invalid export function pointer"); - - return offset; -} - -byte *Script::findBlock(int type) { - byte *buf = _buf; - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - - if (oldScriptHeader) - buf += 2; - - do { - int seekerType = READ_LE_UINT16(buf); - - if (seekerType == 0) - break; - if (seekerType == type) - return buf; - - int seekerSize = READ_LE_UINT16(buf + 2); - assert(seekerSize > 0); - buf += seekerSize; - } while (1); - - return NULL; -} - - -// memory operations - -void Script::mcpyInOut(int dst, const void *src, size_t n) { - if (_buf) { - assert(dst + n <= _bufSize); - memcpy(_buf + dst, src, n); - } -} - SegmentRef SegmentObj::dereference(reg_t pointer) { error("Error: Trying to dereference pointer %04x:%04x to inappropriate segment", PRINT_REG(pointer)); return SegmentRef(); } -bool Script::isValidOffset(uint16 offset) const { - return offset < _bufSize; -} - -SegmentRef Script::dereference(reg_t pointer) { - if (pointer.offset > _bufSize) { - error("Script::dereference(): Attempt to dereference invalid pointer %04x:%04x into script segment (script size=%d)", - PRINT_REG(pointer), (uint)_bufSize); - return SegmentRef(); - } - - SegmentRef ret; - ret.isRaw = true; - ret.maxSize = _bufSize - pointer.offset; - ret.raw = _buf + pointer.offset; - return ret; -} bool LocalVariables::isValidOffset(uint16 offset) const { return offset < _locals.size() * 2; diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index 24d27e367f..b621e53412 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -331,182 +331,6 @@ private: reg_t _pos; /**< Object offset within its script; for clones, this is their base */ }; -typedef Common::HashMap ObjMap; - -class Script : public SegmentObj { -public: - int _nr; /**< Script number */ - byte *_buf; /**< Static data buffer, or NULL if not used */ - byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ - - uint32 getScriptSize() { return _scriptSize; } - uint32 getHeapSize() { return _heapSize; } - uint32 getBufSize() { return _bufSize; } - -protected: - int _lockers; /**< Number of classes and objects that require this script */ - -private: - size_t _scriptSize; - size_t _heapSize; - uint16 _bufSize; - - const uint16 *_exportTable; /**< Abs. offset of the export table or 0 if not present */ - uint16 _numExports; /**< Number of entries in the exports table */ - - const byte *_synonyms; /**< Synonyms block or 0 if not present*/ - uint16 _numSynonyms; /**< Number of entries in the synonyms block */ - - int _localsOffset; - uint16 _localsCount; - -public: - /** - * Table for objects, contains property variables. - * Indexed by the TODO offset. - */ - ObjMap _objects; - - int getLocalsOffset() const { return _localsOffset; } - uint16 getLocalsCount() const { return _localsCount; } - SegmentId _localsSegment; /**< The local variable segment */ - LocalVariables *_localsBlock; - - bool _markedAsDeleted; - -public: - Script(); - ~Script(); - - void freeScript(); - void init(int script_nr, ResourceManager *resMan); - void load(ResourceManager *resMan); - - virtual bool isValidOffset(uint16 offset) const; - virtual SegmentRef dereference(reg_t pointer); - virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; - - virtual void saveLoadWithSerializer(Common::Serializer &ser); - - Object *allocateObject(uint16 offset); - Object *getObject(uint16 offset); - const Object *getObject(uint16 offset) const; - - /** - * Initializes an object within the segment manager - * @param obj_pos Location (segment, offset) of the object. It must - * point to the beginning of the script/class block - * (as opposed to what the VM considers to be the - * object location) - * @returns A newly created Object describing the object, - * stored within the relevant script - */ - Object *scriptObjInit(reg_t obj_pos, bool fullObjectInit = true); - - /** - * Removes a script object - * @param obj_pos Location (segment, offset) of the object. - */ - void scriptObjRemove(reg_t obj_pos); - - /** - * Processes a relocation block witin a script - * This function is idempotent, but it must only be called after all - * objects have been instantiated, or a run-time error will occur. - * @param obj_pos Location (segment, offset) of the block - * @return Location of the relocation block - */ - void relocate(reg_t block); - -private: - bool relocateLocal(SegmentId segment, int location); - -public: - // script lock operations - - /** Increments the number of lockers of this script by one. */ - void incrementLockers(); - - /** Decrements the number of lockers of this script by one. */ - void decrementLockers(); - - /** - * Retrieves the number of locks held on this script. - * @return the number of locks held on the previously identified script - */ - int getLockers() const; - - /** Sets the number of locks held on this script. */ - void setLockers(int lockers); - - /** - * Retrieves a pointer to the exports of this script - * @return pointer to the exports. - */ - const uint16 *getExportTable() const { return _exportTable; } - - /** - * Retrieves the number of exports of script. - * @return the number of exports of this script - */ - uint16 getExportsNr() const { return _numExports; } - - /** - * Retrieves a pointer to the synonyms associated with this script - * @return pointer to the synonyms, in non-parsed format. - */ - const byte *getSynonyms() const { return _synonyms; } - - /** - * Retrieves the number of synonyms associated with this script. - * @return the number of synonyms associated with this script - */ - uint16 getSynonymsNr() const { return _numSynonyms; } - - /** - * Validate whether the specified public function is exported by - * the script in the specified segment. - * @param pubfunct Index of the function to validate - * @return NULL if the public function is invalid, its - * offset into the script's segment otherwise - */ - uint16 validateExportFunc(int pubfunct); - - /** - * Marks the script as deleted. - * This will not actually delete the script. If references remain present on the - * heap or the stack, the script will stay in memory in a quasi-deleted state until - * either unreachable (resulting in its eventual deletion) or reloaded (resulting - * in its data being updated). - */ - void markDeleted() { - _markedAsDeleted = true; - } - - /** - * Determines whether the script is marked as being deleted. - */ - bool isMarkedAsDeleted() const { - return _markedAsDeleted; - } - - /** - * Copies a byte string into a script's heap representation. - * @param dst script-relative offset of the destination area - * @param src pointer to the data source location - * @param n number of bytes to copy - */ - void mcpyInOut(int dst, const void *src, size_t n); - - /** - * Finds the pointer where a block of a specific type starts from - */ - byte *findBlock(int type); -}; - /** Data stack */ struct DataStack : SegmentObj { int _capacity; /**< Number of stack entries */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 841d4ede64..9ab95c41bb 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -49,6 +49,86 @@ const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; #define SCI_XS_CALLEE_LOCALS ((SegmentId)-1) +#define END Script_None + +opcode_format g_opcode_formats[128][4] = { + /*00*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*04*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*08*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*0C*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*10*/ + {Script_None}, {Script_None}, {Script_None}, {Script_None}, + /*14*/ + {Script_None}, {Script_None}, {Script_None}, {Script_SRelative, END}, + /*18*/ + {Script_SRelative, END}, {Script_SRelative, END}, {Script_SVariable, END}, {Script_None}, + /*1C*/ + {Script_SVariable, END}, {Script_None}, {Script_None}, {Script_Variable, END}, + /*20*/ + {Script_SRelative, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_Byte, END}, {Script_Variable, Script_SVariable, Script_Byte, END}, + /*24 (24=ret)*/ + {Script_End}, {Script_Byte, END}, {Script_Invalid}, {Script_Invalid}, + /*28*/ + {Script_Variable, END}, {Script_Invalid}, {Script_Byte, END}, {Script_Variable, Script_Byte, END}, + /*2C*/ + {Script_SVariable, END}, {Script_SVariable, Script_Variable, END}, {Script_None}, {Script_Invalid}, + /*30*/ + {Script_None}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, + /*34*/ + {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, {Script_Property, END}, + /*38*/ + {Script_Property, END}, {Script_SRelative, END}, {Script_SRelative, END}, {Script_None}, + /*3C*/ + {Script_None}, {Script_None}, {Script_None}, {Script_Word}, + /*40-4F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*50-5F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*60-6F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + /*70-7F*/ + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END}, + {Script_Global, END}, {Script_Local, END}, {Script_Temp, END}, {Script_Param, END} +}; +#undef END + +// TODO: script_adjust_opcode_formats should probably be part of the +// constructor (?) of a VirtualMachine or a ScriptManager class. +void script_adjust_opcode_formats() { + if (g_sci->_features->detectLofsType() != SCI_VERSION_0_EARLY) { + g_opcode_formats[op_lofsa][0] = Script_Offset; + g_opcode_formats[op_lofss][0] = Script_Offset; + } + +#ifdef ENABLE_SCI32 + // In SCI32, some arguments are now words instead of bytes + if (getSciVersion() >= SCI_VERSION_2) { + g_opcode_formats[op_calle][2] = Script_Word; + g_opcode_formats[op_callk][1] = Script_Word; + g_opcode_formats[op_super][1] = Script_Word; + g_opcode_formats[op_send][0] = Script_Word; + g_opcode_formats[op_self][0] = Script_Word; + g_opcode_formats[op_call][1] = Script_Word; + g_opcode_formats[op_callb][1] = Script_Word; + } +#endif +} + /** * Adds an entry to the top of the execution stack. * diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 0938520525..ed4cc4a456 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -118,6 +118,160 @@ enum { GC_INTERVAL = 32768 }; +// Opcode formats +enum opcode_format { + Script_Invalid = -1, + Script_None = 0, + Script_Byte, + Script_SByte, + Script_Word, + Script_SWord, + Script_Variable, + Script_SVariable, + Script_SRelative, + Script_Property, + Script_Global, + Script_Local, + Script_Temp, + Script_Param, + Script_Offset, + Script_End +}; + +enum sci_opcodes { + op_bnot = 0x00, // 000 + op_add = 0x01, // 001 + op_sub = 0x02, // 002 + op_mul = 0x03, // 003 + op_div = 0x04, // 004 + op_mod = 0x05, // 005 + op_shr = 0x06, // 006 + op_shl = 0x07, // 007 + op_xor = 0x08, // 008 + op_and = 0x09, // 009 + op_or = 0x0a, // 010 + op_neg = 0x0b, // 011 + op_not = 0x0c, // 012 + op_eq_ = 0x0d, // 013 + op_ne_ = 0x0e, // 014 + op_gt_ = 0x0f, // 015 + op_ge_ = 0x10, // 016 + op_lt_ = 0x11, // 017 + op_le_ = 0x12, // 018 + op_ugt_ = 0x13, // 019 + op_uge_ = 0x14, // 020 + op_ult_ = 0x15, // 021 + op_ule_ = 0x16, // 022 + op_bt = 0x17, // 023 + op_bnt = 0x18, // 024 + op_jmp = 0x19, // 025 + op_ldi = 0x1a, // 026 + op_push = 0x1b, // 027 + op_pushi = 0x1c, // 028 + op_toss = 0x1d, // 029 + op_dup = 0x1e, // 030 + op_link = 0x1f, // 031 + op_call = 0x20, // 032 + op_callk = 0x21, // 033 + op_callb = 0x22, // 034 + op_calle = 0x23, // 035 + op_ret = 0x24, // 036 + op_send = 0x25, // 037 + // dummy 0x26, // 038 + // dummy 0x27, // 039 + op_class = 0x28, // 040 + // dummy 0x29, // 041 + op_self = 0x2a, // 042 + op_super = 0x2b, // 043 + op_rest = 0x2c, // 044 + op_lea = 0x2d, // 045 + op_selfID = 0x2e, // 046 + // dummy 0x2f // 047 + op_pprev = 0x30, // 048 + op_pToa = 0x31, // 049 + op_aTop = 0x32, // 050 + op_pTos = 0x33, // 051 + op_sTop = 0x34, // 052 + op_ipToa = 0x35, // 053 + op_dpToa = 0x36, // 054 + op_ipTos = 0x37, // 055 + op_dpTos = 0x38, // 056 + op_lofsa = 0x39, // 057 + op_lofss = 0x3a, // 058 + op_push0 = 0x3b, // 059 + op_push1 = 0x3c, // 060 + op_push2 = 0x3d, // 061 + op_pushSelf = 0x3e, // 062 + op_line = 0x3f, // 063 + op_lag = 0x40, // 064 + op_lal = 0x41, // 065 + op_lat = 0x42, // 066 + op_lap = 0x43, // 067 + op_lsg = 0x44, // 068 + op_lsl = 0x45, // 069 + op_lst = 0x46, // 070 + op_lsp = 0x47, // 071 + op_lagi = 0x48, // 072 + op_lali = 0x49, // 073 + op_lati = 0x4a, // 074 + op_lapi = 0x4b, // 075 + op_lsgi = 0x4c, // 076 + op_lsli = 0x4d, // 077 + op_lsti = 0x4e, // 078 + op_lspi = 0x4f, // 079 + op_sag = 0x50, // 080 + op_sal = 0x51, // 081 + op_sat = 0x52, // 082 + op_sap = 0x53, // 083 + op_ssg = 0x54, // 084 + op_ssl = 0x55, // 085 + op_sst = 0x56, // 086 + op_ssp = 0x57, // 087 + op_sagi = 0x58, // 088 + op_sali = 0x59, // 089 + op_sati = 0x5a, // 090 + op_sapi = 0x5b, // 091 + op_ssgi = 0x5c, // 092 + op_ssli = 0x5d, // 093 + op_ssti = 0x5e, // 094 + op_sspi = 0x5f, // 095 + op_plusag = 0x60, // 096 + op_plusal = 0x61, // 097 + op_plusat = 0x62, // 098 + op_plusap = 0x63, // 099 + op_plussg = 0x64, // 100 + op_plussl = 0x65, // 101 + op_plusst = 0x66, // 102 + op_plussp = 0x67, // 103 + op_plusagi = 0x68, // 104 + op_plusali = 0x69, // 105 + op_plusati = 0x6a, // 106 + op_plusapi = 0x6b, // 107 + op_plussgi = 0x6c, // 108 + op_plussli = 0x6d, // 109 + op_plussti = 0x6e, // 110 + op_plusspi = 0x6f, // 111 + op_minusag = 0x70, // 112 + op_minusal = 0x71, // 113 + op_minusat = 0x72, // 114 + op_minusap = 0x73, // 115 + op_minussg = 0x74, // 116 + op_minussl = 0x75, // 117 + op_minusst = 0x76, // 118 + op_minussp = 0x77, // 119 + op_minusagi = 0x78, // 120 + op_minusali = 0x79, // 121 + op_minusati = 0x7a, // 122 + op_minusapi = 0x7b, // 123 + op_minussgi = 0x7c, // 124 + op_minussli = 0x7d, // 125 + op_minussti = 0x7e, // 126 + op_minusspi = 0x7f // 127 +}; + +extern opcode_format g_opcode_formats[128][4]; + +void script_adjust_opcode_formats(); /** * Executes function pubfunct of the specified script. @@ -194,30 +348,6 @@ void script_debug(EngineState *s); SelectorType lookupSelector(SegManager *segMan, reg_t obj, Selector selectorid, ObjVarRef *varp, reg_t *fptr); -/** - * Makes sure that a script and its superclasses get loaded to the heap. - * If the script already has been loaded, only the number of lockers is - * increased. All scripts containing superclasses of this script are loaded - * recursively as well, unless 'recursive' is set to zero. The - * complementary function is "script_uninstantiate()" below. - * @param[in] resMan The resource manager - * @param[in] segMan The segment manager - * @param[in] script_nr The script number to load - * @return The script's segment ID or 0 if out of heap - */ -int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr); - -/** - * Decreases the numer of lockers of a script and unloads it if that number - * reaches zero. - * This function will recursively unload scripts containing its - * superclasses, if those aren't locked by other scripts as well. - * @param[in] segMan The segment manager - * @param[in] version The SCI version to use - * @param[in] script_nr The script number that is requestet to be unloaded - */ -void script_uninstantiate(SegManager *segMan, int script_nr); - /** * Read a PMachine instruction from a memory buffer and return its length. * -- cgit v1.2.3 From 5f9cc9e8f8272fd2e07c9b6cce8bcc541772d17f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 20:43:32 +0000 Subject: SCI: adding alias for vmvars ("vv") and vmvarlist ("vl") svn-id: r50397 --- engines/sci/console.cpp | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 37d859cc7c..b837c7b92b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -186,16 +186,18 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { // VM DCmd_Register("script_steps", WRAP_METHOD(Console, cmdScriptSteps)); DCmd_Register("vm_varlist", WRAP_METHOD(Console, cmdVMVarlist)); - DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + DCmd_Register("vmvarlist", WRAP_METHOD(Console, cmdVMVarlist)); // alias + DCmd_Register("vl", WRAP_METHOD(Console, cmdVMVarlist)); // alias DCmd_Register("vm_vars", WRAP_METHOD(Console, cmdVMVars)); - DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + DCmd_Register("vmvars", WRAP_METHOD(Console, cmdVMVars)); // alias + DCmd_Register("vv", WRAP_METHOD(Console, cmdVMVars)); // alias DCmd_Register("stack", WRAP_METHOD(Console, cmdStack)); DCmd_Register("value_type", WRAP_METHOD(Console, cmdValueType)); DCmd_Register("view_listnode", WRAP_METHOD(Console, cmdViewListNode)); DCmd_Register("view_reference", WRAP_METHOD(Console, cmdViewReference)); - DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias + DCmd_Register("vr", WRAP_METHOD(Console, cmdViewReference)); // alias DCmd_Register("view_object", WRAP_METHOD(Console, cmdViewObject)); - DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias + DCmd_Register("vo", WRAP_METHOD(Console, cmdViewObject)); // alias DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); @@ -400,8 +402,8 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("\n"); DebugPrintf("VM:\n"); DebugPrintf(" script_steps - Shows the number of executed SCI operations\n"); - DebugPrintf(" vm_varlist / vmvarlist - Shows the addresses of variables in the VM\n"); - DebugPrintf(" vm_vars / vmvars - Displays or changes variables in the VM\n"); + DebugPrintf(" vm_varlist / vmvarlist / vl - Shows the addresses of variables in the VM\n"); + DebugPrintf(" vm_vars / vmvars / vv - Displays or changes variables in the VM\n"); DebugPrintf(" stack - Lists the specified number of stack elements\n"); DebugPrintf(" value_type - Determines the type of a value\n"); DebugPrintf(" view_listnode - Examines the list node at the given address\n"); -- cgit v1.2.3 From 2843feeb9a4d031eaacc896da0045877fd048004 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 21:00:34 +0000 Subject: SCI: Made the code for initializing script classes, objects and locals part of the Script class svn-id: r50398 --- engines/sci/engine/script.cpp | 74 +++++++++++++++++++--------------------- engines/sci/engine/script.h | 24 +++++++++++++ engines/sci/engine/seg_manager.h | 21 ++---------- 3 files changed, 63 insertions(+), 56 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 748a8f9140..18244c7906 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -384,34 +384,31 @@ SegmentRef Script::dereference(reg_t pointer) { return ret; } -void SegManager::scriptInitialiseLocals(SegmentId segmentId) { - Script *scr = getScript(segmentId); - - LocalVariables *locals = allocLocalsSegment(scr); +void Script::initialiseLocals(SegManager *segMan) { + LocalVariables *locals = segMan->allocLocalsSegment(this); if (locals) { if (getSciVersion() > SCI_VERSION_0_EARLY) { - const byte *base = (const byte *)(scr->_buf + scr->getLocalsOffset()); + const byte *base = (const byte *)(_buf + getLocalsOffset()); - for (uint16 i = 0; i < scr->getLocalsCount(); i++) + for (uint16 i = 0; i < getLocalsCount(); i++) locals->_locals[i] = make_reg(0, READ_SCI11ENDIAN_UINT16(base + i * 2)); } else { // In SCI0 early, locals are set at run time, thus zero them all here - for (uint16 i = 0; i < scr->getLocalsCount(); i++) + for (uint16 i = 0; i < getLocalsCount(); i++) locals->_locals[i] = NULL_REG; } } } -void SegManager::scriptInitialiseClasses(SegmentId seg) { - Script *scr = getScript(seg); +void Script::initialiseClasses(SegManager *segMan) { const byte *seeker = 0; uint16 mult = 0; if (getSciVersion() >= SCI_VERSION_1_1) { - seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; + seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; mult = 2; } else { - seeker = scr->findBlock(SCI_OBJ_CLASS); + seeker = findBlock(SCI_OBJ_CLASS); mult = 1; } @@ -422,7 +419,7 @@ void SegManager::scriptInitialiseClasses(SegmentId seg) { // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234) uint16 marker = READ_SCI11ENDIAN_UINT16(seeker); bool isClass; - uint16 classpos = seeker - scr->_buf; + uint16 classpos = seeker - _buf; int16 species; if (!marker) @@ -439,24 +436,25 @@ void SegManager::scriptInitialiseClasses(SegmentId seg) { if (isClass) { // WORKAROUND for an invalid species access in the demo of LSL2 - if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)classTableSize()) - resizeClassTable(classTableSize() + 1); + if (g_sci->getGameId() == GID_LSL2 && g_sci->isDemo() && species == (int)segMan->classTableSize()) + segMan->resizeClassTable(segMan->classTableSize() + 1); - if (species < 0 || species >= (int)classTableSize()) + if (species < 0 || species >= (int)segMan->classTableSize()) error("Invalid species %d(0x%x) not in interval [0,%d) while instantiating script %d\n", - species, species, classTableSize(), scr->_nr); + species, species, segMan->classTableSize(), _nr); - setClassOffset(species, make_reg(seg, classpos)); + SegmentId segmentId = segMan->getScriptSegment(_nr); + segMan->setClassOffset(species, make_reg(segmentId, classpos)); } seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * mult; } } -void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { - Script *scr = getScript(seg); +void Script::initialiseObjectsSci0(SegManager *segMan) { bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - const byte *seeker = scr->_buf + (oldScriptHeader ? 2 : 0); + const byte *seeker = _buf + (oldScriptHeader ? 2 : 0); + SegmentId segmentId = segMan->getScriptSegment(_nr); do { uint16 objType = READ_SCI11ENDIAN_UINT16(seeker); @@ -467,14 +465,14 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { case SCI_OBJ_OBJECT: case SCI_OBJ_CLASS: { - reg_t addr = make_reg(seg, seeker - scr->_buf + 4); - Object *obj = scr->scriptObjInit(addr); - obj->initSpecies(this, addr); + reg_t addr = make_reg(segmentId, seeker - _buf + 4); + Object *obj = scriptObjInit(addr); + obj->initSpecies(segMan, addr); - if (!obj->initBaseObject(this, addr)) { + if (!obj->initBaseObject(segMan, addr)) { // Script 202 of KQ5 French has an invalid object. This is non-fatal. warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); - scr->scriptObjRemove(addr); + scriptObjRemove(addr); } } break; @@ -484,20 +482,20 @@ void SegManager::scriptInitialiseObjectsSci0(SegmentId seg) { } seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); - } while ((uint32)(seeker - scr->_buf) < scr->getScriptSize() - 2); + } while ((uint32)(seeker - _buf) < getScriptSize() - 2); } -void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { - Script *scr = getScript(seg); - const byte *seeker = scr->_heapStart + 4 + READ_SCI11ENDIAN_UINT16(scr->_heapStart + 2) * 2; +void Script::initialiseObjectsSci11(SegManager *segMan) { + const byte *seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; + SegmentId segmentId = segMan->getScriptSegment(_nr); while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { - reg_t reg = make_reg(seg, seeker - scr->_buf); - Object *obj = scr->scriptObjInit(reg); + reg_t reg = make_reg(segmentId, seeker - _buf); + Object *obj = scriptObjInit(reg); // Copy base from species class, as we need its selector IDs obj->setSuperClassSelector( - getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); + segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); // If object is instance, get -propDict- from class and set it for this object // This is needed for ::isMemberOf() to work. @@ -505,7 +503,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { // clicking on ego if (!obj->isClass()) { reg_t classObject = obj->getSuperClassSelector(); - Object *classObj = getObject(classObject); + Object *classObj = segMan->getObject(classObject); obj->setPropDictSelector(classObj->getPropDictSelector()); } @@ -515,7 +513,7 @@ void SegManager::scriptInitialiseObjectsSci11(SegmentId seg) { // uses this selector together with -propDict- to compare classes. // For the purpose of Obj::isKindOf, using the script number appears // to be sufficient. - obj->setClassScriptSelector(make_reg(0, scr->_nr)); + obj->setClassScriptSelector(make_reg(0, _nr)); seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; } @@ -537,14 +535,14 @@ int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNu scr->init(scriptNum, resMan); scr->load(resMan); - segMan->scriptInitialiseLocals(segmentId); - segMan->scriptInitialiseClasses(segmentId); + scr->initialiseLocals(segMan); + scr->initialiseClasses(segMan); if (getSciVersion() >= SCI_VERSION_1_1) { - segMan->scriptInitialiseObjectsSci11(segmentId); + scr->initialiseObjectsSci11(segMan); scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); } else { - segMan->scriptInitialiseObjectsSci0(segmentId); + scr->initialiseObjectsSci0(segMan); byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); if (relocationBlock) scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 62d2228c9a..cc3c0263e8 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -140,6 +140,30 @@ public: */ void relocate(reg_t block); + /** + * Initializes the script's local variables + * @param segMan A reference to the segment manager + */ + void initialiseLocals(SegManager *segMan); + + /** + * Adds the script's classes to the segment manager's class table + * @param segMan A reference to the segment manager + */ + void initialiseClasses(SegManager *segMan); + + /** + * Initializes the script's objects (SCI0) + * @param segMan A reference to the segment manager + */ + void initialiseObjectsSci0(SegManager *segMan); + + /** + * Initializes the script's objects (SCI1.1+) + * @param segMan A reference to the segment manager + */ + void initialiseObjectsSci11(SegManager *segMan); + private: bool relocateLocal(SegmentId segment, int location); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 19fd06f596..324527400b 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -139,19 +139,6 @@ public: */ Script *getScriptIfLoaded(SegmentId seg); - - // 1b. Script Initialisation - - // The set of functions below are intended - // to be used during script instantiation, - // i.e. loading and linking. - - /** - * Initializes a script's local variable block according to a prototype - * @param segmentId Segment containing the script to initialize - */ - void scriptInitialiseLocals(SegmentId segmentId); - // 2. Clones /** @@ -427,10 +414,6 @@ public: */ reg_t findObjectByName(const Common::String &name, int index = -1); - void scriptInitialiseClasses(SegmentId seg); - void scriptInitialiseObjectsSci0(SegmentId seg); - void scriptInitialiseObjectsSci11(SegmentId seg); - uint32 classTableSize() { return _classTable.size(); } Class getClass(int index) { return _classTable[index]; } void setClassOffset(int index, reg_t offset) { _classTable[index].reg = offset; } @@ -481,7 +464,6 @@ private: private: SegmentObj *allocSegment(SegmentObj *mem, SegmentId *segid); - LocalVariables *allocLocalsSegment(Script *scr); int deallocate(SegmentId seg, bool recursive); void createClassTable(); @@ -494,6 +476,9 @@ private: * 'seg' is a valid segment */ bool check(SegmentId seg); + +public: + LocalVariables *allocLocalsSegment(Script *scr); }; } // End of namespace Sci -- cgit v1.2.3 From 819dc92802d330a27066b755854cba7169b8dfad Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Sun, 27 Jun 2010 21:04:47 +0000 Subject: Escape a "?" character to prevent "??)" to be interpreted as trigraph and thus becoming "]". svn-id: r50399 --- engines/sci/console.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b837c7b92b..4bc68fd813 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3237,7 +3237,7 @@ void Console::printBasicVarInfo(reg_t variable) { DebugPrintf(" (list)"); break; default: - DebugPrintf(" (???)"); + DebugPrintf(" (??\?)"); } } -- cgit v1.2.3 From 456265f8fac8c5020e30fa99e0be1c1ff1a02aa8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 21:12:38 +0000 Subject: SCI: resetting curPos as well when mixing sound resources svn-id: r50401 --- engines/sci/sound/midiparser_sci.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 1d25a518e1..50a2407dde 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -444,6 +444,7 @@ byte *MidiParser_SCI::midiMixChannels() { for (int i = 0; i < _track->channelCount; i++) { _track->channels[i].time = 0; _track->channels[i].prev = 0; + _track->channels[i].curPos = 0; totalSize += _track->channels[i].size; } -- cgit v1.2.3 From 4a60ff409050e8f3da6065f2a44d78d31c4f34b9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 21:18:19 +0000 Subject: Made the script initialization/uninitialization methods part of the segment manager svn-id: r50402 --- engines/sci/engine/kscripts.cpp | 2 +- engines/sci/engine/script.cpp | 105 ------------------------------------ engines/sci/engine/script.h | 24 --------- engines/sci/engine/seg_manager.cpp | 108 ++++++++++++++++++++++++++++++++++++- engines/sci/engine/seg_manager.h | 24 +++++++++ engines/sci/engine/vm.cpp | 2 +- engines/sci/sci.cpp | 2 +- 7 files changed, 134 insertions(+), 133 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 8ea0ec2019..8f41fbad2e 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -239,7 +239,7 @@ reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { scr->setLockers(1); } - script_uninstantiate(s->_segMan, script); + s->_segMan->uninstantiateScript(script); if (argc != 2) { return s->r_acc; diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 18244c7906..2bb405372a 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -519,109 +519,4 @@ void Script::initialiseObjectsSci11(SegManager *segMan) { } } -int script_instantiate(ResourceManager *resMan, SegManager *segMan, int scriptNum) { - SegmentId segmentId = segMan->getScriptSegment(scriptNum); - Script *scr = segMan->getScriptIfLoaded(segmentId); - if (scr) { - if (!scr->isMarkedAsDeleted()) { - scr->incrementLockers(); - return segmentId; - } else { - scr->freeScript(); - } - } else { - scr = segMan->allocateScript(scriptNum, &segmentId); - } - - scr->init(scriptNum, resMan); - scr->load(resMan); - scr->initialiseLocals(segMan); - scr->initialiseClasses(segMan); - - if (getSciVersion() >= SCI_VERSION_1_1) { - scr->initialiseObjectsSci11(segMan); - scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); - } else { - scr->initialiseObjectsSci0(segMan); - byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); - if (relocationBlock) - scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); - } - - return segmentId; -} - -void script_uninstantiate_sci0(SegManager *segMan, int script_nr, SegmentId seg) { - bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); - reg_t reg = make_reg(seg, oldScriptHeader ? 2 : 0); - int objType, objLength = 0; - Script *scr = segMan->getScript(seg); - - // Make a pass over the object in order uninstantiate all superclasses - - do { - reg.offset += objLength; // Step over the last checked object - - objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset); - if (!objType) - break; - objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); - - reg.offset += 4; // Step over header - - if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? - reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); - - if (superclass >= 0) { - int superclass_script = segMan->getClass(superclass).script; - - if (superclass_script == script_nr) { - if (scr->getLockers()) - scr->decrementLockers(); // Decrease lockers if this is us ourselves - } else - script_uninstantiate(segMan, superclass_script); - // Recurse to assure that the superclass lockers number gets decreased - } - - reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET; - } // if object or class - - reg.offset -= 4; // Step back on header - - } while (objType != 0); -} - -void script_uninstantiate(SegManager *segMan, int script_nr) { - SegmentId segment = segMan->getScriptSegment(script_nr); - Script *scr = segMan->getScriptIfLoaded(segment); - - if (!scr) { // Is it already loaded? - //warning("unloading script 0x%x requested although not loaded", script_nr); - // This is perfectly valid SCI behaviour - return; - } - - scr->decrementLockers(); // One less locker - - if (scr->getLockers() > 0) - return; - - // Free all classtable references to this script - for (uint i = 0; i < segMan->classTableSize(); i++) - if (segMan->getClass(i).reg.segment == segment) - segMan->setClassOffset(i, NULL_REG); - - if (getSciVersion() < SCI_VERSION_1_1) - script_uninstantiate_sci0(segMan, script_nr, segment); - // FIXME: Add proper script uninstantiation for SCI 1.1 - - if (!scr->getLockers()) { - // The actual script deletion seems to be done by SCI scripts themselves - scr->markDeleted(); - debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); - } -} - - } // End of namespace Sci diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index cc3c0263e8..5396a7432e 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -250,30 +250,6 @@ public: byte *findBlock(int type); }; -/** - * Makes sure that a script and its superclasses get loaded to the heap. - * If the script already has been loaded, only the number of lockers is - * increased. All scripts containing superclasses of this script are loaded - * recursively as well, unless 'recursive' is set to zero. The - * complementary function is "script_uninstantiate()" below. - * @param[in] resMan The resource manager - * @param[in] segMan The segment manager - * @param[in] script_nr The script number to load - * @return The script's segment ID or 0 if out of heap - */ -int script_instantiate(ResourceManager *resMan, SegManager *segMan, int script_nr); - -/** - * Decreases the numer of lockers of a script and unloads it if that number - * reaches zero. - * This function will recursively unload scripts containing its - * superclasses, if those aren't locked by other scripts as well. - * @param[in] segMan The segment manager - * @param[in] version The SCI version to use - * @param[in] script_nr The script number that is requestet to be unloaded - */ -void script_uninstantiate(SegManager *segMan, int script_nr); - } // End of namespace Sci #endif // SCI_ENGINE_SCRIPT_H diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 35ac0a5f69..b56a539c63 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -361,7 +361,7 @@ SegmentId SegManager::getScriptSegment(int script_nr, ScriptLoadType load) { SegmentId segment; if ((load & SCRIPT_GET_LOAD) == SCRIPT_GET_LOAD) - script_instantiate(_resMan, this, script_nr); + instantiateScript(script_nr); segment = getScriptSegment(script_nr); @@ -991,4 +991,110 @@ reg_t SegManager::getClassAddress(int classnr, ScriptLoadType lock, reg_t caller return the_class->reg; } } + +int SegManager::instantiateScript(int scriptNum) { + SegmentId segmentId = getScriptSegment(scriptNum); + Script *scr = getScriptIfLoaded(segmentId); + if (scr) { + if (!scr->isMarkedAsDeleted()) { + scr->incrementLockers(); + return segmentId; + } else { + scr->freeScript(); + } + } else { + scr = allocateScript(scriptNum, &segmentId); + } + + scr->init(scriptNum, _resMan); + scr->load(_resMan); + scr->initialiseLocals(this); + scr->initialiseClasses(this); + + if (getSciVersion() >= SCI_VERSION_1_1) { + scr->initialiseObjectsSci11(this); + scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); + } else { + scr->initialiseObjectsSci0(this); + byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); + if (relocationBlock) + scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); + } + + return segmentId; +} + +void SegManager::uninstantiateScript(int script_nr) { + SegmentId segmentId = getScriptSegment(script_nr); + Script *scr = getScriptIfLoaded(segmentId); + + if (!scr) { // Is it already unloaded? + //warning("unloading script 0x%x requested although not loaded", script_nr); + // This is perfectly valid SCI behaviour + return; + } + + scr->decrementLockers(); // One less locker + + if (scr->getLockers() > 0) + return; + + // Free all classtable references to this script + for (uint i = 0; i < classTableSize(); i++) + if (getClass(i).reg.segment == segmentId) + setClassOffset(i, NULL_REG); + + if (getSciVersion() < SCI_VERSION_1_1) + uninstantiateScriptSci0(script_nr); + // FIXME: Add proper script uninstantiation for SCI 1.1 + + if (!scr->getLockers()) { + // The actual script deletion seems to be done by SCI scripts themselves + scr->markDeleted(); + debugC(kDebugLevelScripts, "Unloaded script 0x%x.", script_nr); + } +} + +void SegManager::uninstantiateScriptSci0(int script_nr) { + bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); + SegmentId segmentId = getScriptSegment(script_nr); + Script *scr = getScript(segmentId); + reg_t reg = make_reg(segmentId, oldScriptHeader ? 2 : 0); + int objType, objLength = 0; + + // Make a pass over the object in order uninstantiate all superclasses + + do { + reg.offset += objLength; // Step over the last checked object + + objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset); + if (!objType) + break; + objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); + + reg.offset += 4; // Step over header + + if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? + reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) + int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); + + if (superclass >= 0) { + int superclass_script = getClass(superclass).script; + + if (superclass_script == script_nr) { + if (scr->getLockers()) + scr->decrementLockers(); // Decrease lockers if this is us ourselves + } else + uninstantiateScript(superclass_script); + // Recurse to assure that the superclass lockers number gets decreased + } + + reg.offset += SCRIPT_OBJECT_MAGIC_OFFSET; + } // if object or class + + reg.offset -= 4; // Step back on header + + } while (objType != 0); +} + } // End of namespace Sci diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 324527400b..4af2965bc7 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -117,6 +117,30 @@ public: */ SegmentId getScriptSegment(int script_nr, ScriptLoadType load); + /** + * Makes sure that a script and its superclasses get loaded to the heap. + * If the script already has been loaded, only the number of lockers is + * increased. All scripts containing superclasses of this script are loaded + * recursively as well, unless 'recursive' is set to zero. The + * complementary function is "uninstantiateScript()" below. + * @param[in] script_nr The script number to load + * @return The script's segment ID or 0 if out of heap + */ + int instantiateScript(int script_nr); + + /** + * Decreases the numer of lockers of a script and unloads it if that number + * reaches zero. + * This function will recursively unload scripts containing its + * superclasses, if those aren't locked by other scripts as well. + * @param[in] script_nr The script number that is requestet to be unloaded + */ + void uninstantiateScript(int script_nr); + +private: + void uninstantiateScriptSci0(int script_nr); + +public: // TODO: document this reg_t getClassAddress(int classnr, ScriptLoadType lock, reg_t caller); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 9ab95c41bb..f59cf4a577 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -420,7 +420,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP Script *scr = s->_segMan->getScriptIfLoaded(seg); if (!scr || scr->isMarkedAsDeleted()) { // Script not present yet? - seg = script_instantiate(g_sci->getResMan(), s->_segMan, script); + seg = s->_segMan->instantiateScript(script); scr = s->_segMan->getScript(seg); } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 6decfc7c27..8a41d74b7f 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -373,7 +373,7 @@ bool SciEngine::initGame() { _gamestate->stack_base = stack->_entries; _gamestate->stack_top = stack->_entries + stack->_capacity; - if (!script_instantiate(_resMan, _gamestate->_segMan, 0)) { + if (!_gamestate->_segMan->instantiateScript(0)) { error("initGame(): Could not instantiate script 0"); return false; } -- cgit v1.2.3 From 1faebccce25ac422f65ab9616b9a7ecb647894a8 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 21:29:35 +0000 Subject: Cleanup, remove unused/obsolete code svn-id: r50403 --- engines/sci/console.cpp | 8 ----- engines/sci/engine/scriptdebug.cpp | 17 ----------- engines/sci/parser/vocabulary.cpp | 53 --------------------------------- engines/sci/sound/iterator/core.cpp | 44 --------------------------- engines/sci/sound/iterator/iterator.cpp | 45 ---------------------------- 5 files changed, 167 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 4bc68fd813..611d1481ad 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -285,14 +285,6 @@ void Console::postEnter() { } } - -#if 0 -// Unused -#define LOOKUP_SPECIES(species) (\ - (species >= 1000) ? species : *(s->_classTable[species].scriptposp) \ - + s->_classTable[species].class_offset) -#endif - bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf("\n"); DebugPrintf("Variables\n"); diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index b8a0987865..d730856332 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -278,23 +278,6 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod void script_debug(EngineState *s) { - // Do we support a separate console? - -#if 0 - if (sci_debug_flags & _DEBUG_FLAG_LOGGING) { - printf("%d: acc=%04x:%04x ", scriptStepCounter, PRINT_REG(s->r_acc)); - disassemble(s, s->xs->addr.pc, 0, 1); - if (s->seeking == kDebugSeekGlobal) - printf("Global %d (0x%x) = %04x:%04x\n", s->seekSpecial, - s->seekSpecial, PRINT_REG(s->script_000->_localsBlock->_locals[s->seekSpecial])); - } -#endif - -#if 0 - if (!g_debugState.debugging) - return; -#endif - if (g_debugState.seeking && !g_debugState.breakpointWasHit) { // Are we looking for something special? if (g_debugState.seeking == kDebugSeekStepOver) { // are we above seek-level? resume then diff --git a/engines/sci/parser/vocabulary.cpp b/engines/sci/parser/vocabulary.cpp index 00448f5d51..e48a9cdfda 100644 --- a/engines/sci/parser/vocabulary.cpp +++ b/engines/sci/parser/vocabulary.cpp @@ -33,59 +33,6 @@ namespace Sci { -#if 0 - -#define VOCAB_RESOURCE_CLASSES 996 -/** - * Vocabulary class names. - * These strange names were taken from an SCI01 interpreter. - */ -const char *class_names[] = {"", - "", - "conj", // conjunction - "ass", // ? - "pos", // preposition ? - "art", // article - "adj", // adjective - "pron", // pronoun - "noun", // noun - "auxv", // auxillary verb - "adv", // adverb - "verb", // verb - "", - "", - "", - "" - }; - -int *vocab_get_classes(ResourceManager *resMan, int* count) { - Resource* r; - int *c; - unsigned int i; - - if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == NULL) - return 0; - - c = (int *)malloc(sizeof(int) * r->size / 2); - for (i = 2; i < r->size; i += 4) { - c[i/4] = READ_LE_UINT16(r->data + i); - } - *count = r->size / 4; - - return c; -} - -int vocab_get_class_count(ResourceManager *resMan) { - Resource* r; - - if ((r = resMan->findResource(ResourceId(kResourceTypeVocab, VOCAB_RESOURCE_CLASSES), 0)) == 0) - return 0; - - return r->size / 4; -} - -#endif - Vocabulary::Vocabulary(ResourceManager *resMan) : _resMan(resMan) { _parserRules = NULL; _vocabVersion = kVocabularySCI0; diff --git a/engines/sci/sound/iterator/core.cpp b/engines/sci/sound/iterator/core.cpp index e2e62c83b7..9ecd00f54c 100644 --- a/engines/sci/sound/iterator/core.cpp +++ b/engines/sci/sound/iterator/core.cpp @@ -384,50 +384,6 @@ void SfxState::thawTime() { } } -#if 0 -// Unreferenced - removed -static void _dump_playing_list(SfxState *self, char *msg) { - Song *song = self->_song; - - fprintf(stderr, "[] Song list : [ "); - song = *(self->_songlib.lib); - while (song) { - fprintf(stderr, "%08lx:%d ", song->handle, song->_status); - song = song->_nextPlaying; - } - fprintf(stderr, "]\n"); - - fprintf(stderr, "[] Play list (%s) : [ " , msg); - - while (song) { - fprintf(stderr, "%08lx ", song->handle); - song = song->_nextPlaying; - } - - fprintf(stderr, "]\n"); -} -#endif - -#if 0 -static void _dump_songs(SfxState *self) { - Song *song = self->_song; - - fprintf(stderr, "Cue iterators:\n"); - song = *(self->_songlib.lib); - while (song) { - fprintf(stderr, " **\tHandle %08x (p%d): status %d\n", - song->handle, song->_priority, song->_status); - SIMSG_SEND(song->_it, SIMSG_PRINT(1)); - song = song->_next; - } - - if (self->_player) { - fprintf(stderr, "Audio iterator:\n"); - self->_player->iterator_message(SongIterator::Message(0, SIMSG_PRINT(1))); - } -} -#endif - bool SfxState::isPlaying(Song *song) { Song *playing_song = _song; diff --git a/engines/sci/sound/iterator/iterator.cpp b/engines/sci/sound/iterator/iterator.cpp index 5d9d63e5af..62560b631f 100644 --- a/engines/sci/sound/iterator/iterator.cpp +++ b/engines/sci/sound/iterator/iterator.cpp @@ -187,20 +187,6 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann midi_channel = cmd & 0xf; paramsleft = MIDI_cmdlen[midi_op]; -#if 0 - if (1) { - fprintf(stderr, "[IT]: off=%x, cmd=%02x, takes %d args ", - channel->offset - 1, cmd, paramsleft); - fprintf(stderr, "[%02x %02x <%02x> %02x %02x %02x]\n", - _data[channel->offset-3], - _data[channel->offset-2], - _data[channel->offset-1], - _data[channel->offset], - _data[channel->offset+1], - _data[channel->offset+2]); - } -#endif - buf[0] = cmd; @@ -285,25 +271,6 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann case SCI_MIDI_SET_POLYPHONY: _polyphony[midi_channel] = buf[2]; - -#if 0 - { - Sci1SongIterator *self1 = (Sci1SongIterator *)this; - int i; - int voices = 0; - for (i = 0; i < self1->_numChannels; i++) { - voices += _polyphony[i]; - } - - printf("SET_POLYPHONY(%d, %d) for a total of %d voices\n", midi_channel, buf[2], voices); - printf("[iterator] DEBUG: Polyphony = [ "); - for (i = 0; i < self1->_numChannels; i++) - printf("%d ", _polyphony[i]); - printf("]\n"); - printf("[iterator] DEBUG: Importance = [ "); - printf("]\n"); - } -#endif break; case SCI_MIDI_SET_REVERB: @@ -359,18 +326,6 @@ int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChann return 0; } else { -#if 0 - /* Perform remapping, if neccessary */ - if (cmd != SCI_MIDI_SET_SIGNAL - && cmd < 0xf0) { /* Not a generic command */ - int chan = cmd & 0xf; - int op = cmd & 0xf0; - - chan = channel_remap[chan]; - buf[0] = chan | op; - } -#endif - /* Process as normal MIDI operation */ return 0; } -- cgit v1.2.3 From 8db94ef9913713185dafebfd040b6f08611f903d Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 21:38:45 +0000 Subject: Cleanup svn-id: r50404 --- engines/sci/engine/script.h | 2 -- engines/sci/engine/vm.cpp | 3 --- 2 files changed, 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 5396a7432e..296570c218 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -34,8 +34,6 @@ namespace Sci { struct EngineState; class ResourceManager; -#define SCI_SCRIPTS_NR 1000 - enum ScriptObjectTypes { SCI_OBJ_TERMINATOR, SCI_OBJ_OBJECT, diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f59cf4a577..a69a142e10 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -826,9 +826,6 @@ static void gcCountDown(EngineState *s) { } } -static const byte _fake_return_buffer[2] = {op_ret << 1, op_ret << 1}; - - int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) { uint offset = 0; extOpcode = src[offset++]; // Get "extended" opcode (lower bit has special meaning) -- cgit v1.2.3 From a887d4898db9c954f29972e8bfb5155659069e4b Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 27 Jun 2010 21:41:30 +0000 Subject: SCI: tell midiparser that he lost ownership of channels in case we take them away svn-id: r50405 --- engines/sci/sound/midiparser_sci.cpp | 6 ++++++ engines/sci/sound/midiparser_sci.h | 1 + engines/sci/sound/music.cpp | 2 ++ 3 files changed, 9 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 50a2407dde..099d4572be 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -648,6 +648,12 @@ void MidiParser_SCI::tryToOwnChannels() { } } +void MidiParser_SCI::lostChannels() { + for (int curChannel = 0; curChannel < 15; curChannel++) + if ((_channelUsed[curChannel]) && (curChannel != 9)) + _channelRemap[curChannel] = -1; +} + void MidiParser_SCI::setVolume(byte volume) { // FIXME: This receives values > 127... throw a warning for now and clip the variable if (volume > MUSIC_VOLUME_MAX) { diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index dbd37018b1..8b796d01fc 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -81,6 +81,7 @@ public: const byte *getMixedData() const { return _mixedData; } void tryToOwnChannels(); + void lostChannels(); void sendFromScriptToDriver(uint32 midi); void sendToDriver(uint32 midi); void sendToDriver(byte status, byte firstOp, byte secondOp) { diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index d1555ca7a6..f10ff6d09a 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -287,6 +287,8 @@ void SciMusic::freeChannels(MusicEntry *caller) { if (_usedChannel[i] == caller) _usedChannel[i] = 0; } + // Also tell midiparser, that he lost ownership + caller->pMidiParser->lostChannels(); } void SciMusic::soundPlay(MusicEntry *pSnd) { -- cgit v1.2.3 From 048ceb73d36e4729cb9c8dde292043c32a554234 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 27 Jun 2010 23:20:08 +0000 Subject: SCI: Removed the hack for loading games from the launcher from run_vm(). This is now done on startup. This should fix loading from the launcher for LSL6 svn-id: r50406 --- engines/sci/engine/selector.cpp | 1 + engines/sci/engine/selector.h | 2 ++ engines/sci/engine/state.cpp | 14 +++++++----- engines/sci/engine/state.h | 2 -- engines/sci/engine/vm.cpp | 50 +++++++++++------------------------------ engines/sci/sci.cpp | 27 +++++++++++++++++++--- 6 files changed, 48 insertions(+), 48 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 00480743cc..155aa83883 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -161,6 +161,7 @@ void Kernel::mapSelectors() { FIND_SELECTOR(maxScale); FIND_SELECTOR(vanishingX); FIND_SELECTOR(vanishingY); + FIND_SELECTOR(init); FIND_SELECTOR(iconIndex); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index acb7912d8d..1fff7caac8 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -103,6 +103,8 @@ struct SelectorCache { // perform Selector moveDone; ///< used for DoBresen + Selector init; ///< Used for menu initialization when loading from the launcher + // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere Selector topString; ///< SCI1 scroll lists use this instead of lsTop diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 4b99097476..9bd8f380a1 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -145,12 +145,14 @@ void EngineState::setRoomNumber(uint16 roomNumber) { } void EngineState::shrinkStackToBase() { - uint size = executionStackBase + 1; - assert(_executionStack.size() >= size); - Common::List::iterator iter = _executionStack.begin(); - for (uint i = 0; i < size; ++i) - ++iter; - _executionStack.erase(iter, _executionStack.end()); + if (_executionStack.size() > 0) { + uint size = executionStackBase + 1; + assert(_executionStack.size() >= size); + Common::List::iterator iter = _executionStack.begin(); + for (uint i = 0; i < size; ++i) + ++iter; + _executionStack.erase(iter, _executionStack.end()); + } } static kLanguage charToLanguage(const char c) { diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index b47b739007..2fcad5b2e4 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -152,8 +152,6 @@ public: SegmentId variablesSegment[4]; ///< Same as above, contains segment IDs int variablesMax[4]; ///< Max. values for all variables - int loadFromLauncher; - AbortGameState abortScriptProcessing; bool gameWasRestarted; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a69a142e10..d819db3d08 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -758,48 +758,24 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { xstack->selector = kernelFuncNr; xstack->type = EXEC_STACK_TYPE_KERNEL; - //warning("callk %s", kernelFunc.origName.c_str()); - - // TODO: SCI2.1 equivalent - if (s->loadFromLauncher >= 0 && ( - (kernelFuncNr == 0x8 && getSciVersion() <= SCI_VERSION_1_1) || // DrawPic - (kernelFuncNr == 0x3d && getSciVersion() == SCI_VERSION_2) // GetSaveDir - //(kernelFuncNum == 0x28 && getSciVersion() == SCI_VERSION_2_1) // AddPlane - )) { - - // A game is being loaded from the launcher, and the game is about to draw something on - // screen, hence all initialization has taken place (i.e. menus have been constructed etc). - // Therefore, inject a kRestoreGame call here, instead of the requested function. - // The restore call is injected here mainly for games which have a menu, as the menu is - // constructed when the game starts and is not reconstructed when a saved game is loaded. - int saveSlot = s->loadFromLauncher; - s->loadFromLauncher = -1; // invalidate slot, so that we don't load again - - if (saveSlot < 0) - error("Requested to load invalid save slot"); // should never happen, really - - reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL) - kRestoreGame(s, 2, restoreArgv); - } else { - // Call kernel function - s->r_acc = kernelFunc.func(s, argc, argv); + // Call kernel function + s->r_acc = kernelFunc.func(s, argc, argv); #if 0 - // Used for debugging - Common::String debugMsg = kernelFunc.origName + - Common::String::printf("[0x%x]", kernelFuncNum) + - Common::String::printf(", %d params: ", argc) + - " ("; + // Used for debugging + Common::String debugMsg = kernelFunc.origName + + Common::String::printf("[0x%x]", kernelFuncNum) + + Common::String::printf(", %d params: ", argc) + + " ("; - for (int i = 0; i < argc; i++) { - debugMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); - debugMsg += (i == argc - 1 ? ")" : ", "); - } + for (int i = 0; i < argc; i++) { + debugMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + debugMsg += (i == argc - 1 ? ")" : ", "); + } - debugMsg += ", result: " + Common::String::printf("%04x:%04x", PRINT_REG(s->r_acc)); - debug("%s", debugMsg.c_str()); + debugMsg += ", result: " + Common::String::printf("%04x:%04x", PRINT_REG(s->r_acc)); + debug("%s", debugMsg.c_str()); #endif - } // Remove callk stack frame again, if there's still an execution stack if (s->_executionStack.begin() != s->_executionStack.end()) diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 8a41d74b7f..9a80420a12 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -306,9 +306,30 @@ Common::Error SciEngine::run() { // Check whether loading a savestate was requested if (ConfMan.hasKey("save_slot")) { - _gamestate->loadFromLauncher = ConfMan.getInt("save_slot"); - } else { - _gamestate->loadFromLauncher = -1; + reg_t restoreArgv[2] = { NULL_REG, make_reg(0, ConfMan.getInt("save_slot")) }; // special call (argv[0] is NULL) + kRestoreGame(_gamestate, 2, restoreArgv); + + // Initialize the game menu, if there is one. + // This is not done when loading, so we must do it manually. + reg_t menuBarObj = _gamestate->_segMan->findObjectByName("MenuBar"); + if (menuBarObj.isNull()) + menuBarObj = _gamestate->_segMan->findObjectByName("menuBar"); // LSL6 + if (!menuBarObj.isNull()) { + // Game menus are found in SCI0-SCI01 games (but not in demos), which had a selector vocabulary, + // thus the following code should always work (at least theoretically). + // The init selector is being moved around in all games, thus adding it to the list of static + // selectors can be tricky. An alternative way would be to call the first method of the + // MenuBar object (which is init), but this will require refactoring. + if (_kernel->_selectorCache.init != -1) { + // Reset abortScriptProcessing before initializing the game menu, so that the + // VM call performed by invokeSelector will actually run. + _gamestate->abortScriptProcessing = kAbortNone; + invokeSelector(_gamestate, menuBarObj, SELECTOR(init), 0, _gamestate->stack_base); + _gamestate->abortScriptProcessing = kAbortLoadGame; + } else { + warning("Game has a menu but not a selector vocabulary, skipping menu initialization"); + } + } } runGame(); -- cgit v1.2.3 From c7554c267e6eaf8457611c44476143a54bbb66c0 Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Mon, 28 Jun 2010 04:04:16 +0000 Subject: Implement shortcuts for switching items in the inventory slash: switch between the last held item and normal mouse comma, period: replace the currently held item with the previous/next item in the inventory Also, commented a bit better what happens when ESCAPE is present with respect to map programs and cut-scenes. svn-id: r50407 --- engines/draci/draci.cpp | 31 ++++++++----- engines/draci/game.cpp | 110 ++++++++++++++++++++++++++++++++++++----------- engines/draci/game.h | 8 ++++ engines/draci/script.cpp | 2 + 4 files changed, 115 insertions(+), 36 deletions(-) (limited to 'engines') diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index a87e9a476d..ee883f9881 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -253,19 +253,20 @@ void DraciEngine::handleEvents() { if (escRoom >= 0) { // Schedule room change - // TODO: gate 0 (always present) is not - // always best for returning from the - // map, e.g. in the starting location. - // also, after loading the game, we - // shouldn't run any gate program, but - // rather restore the state of all - // objects. + // TODO: gate 0 (always present) is not always best for + // returning from the map, e.g. in the starting location. + // also, after loading the game, we shouldn't run any gate + // program, but rather restore the state of all objects. _game->scheduleEnteringRoomUsingGate(escRoom, 0); - // Immediately cancel any running animation or dubbing. + // Immediately cancel any running animation or dubbing and + // end any currently running GPL programs. In the intro it + // works as intended---skipping the rest of it. + // + // In the map, this causes that animation on newly + // discovered locations will be re-run next time and + // cut-scenes won't be played. _game->setExitLoop(true); - - // End any currently running GPL programs _script->endCurrentProgram(true); } break; @@ -301,6 +302,16 @@ void DraciEngine::handleEvents() { openMainMenuDialog(); } break; + case Common::KEYCODE_COMMA: + case Common::KEYCODE_PERIOD: + case Common::KEYCODE_SLASH: + if ((_game->getLoopStatus() == kStatusOrdinary || + _game->getLoopStatus() == kStatusInventory) && + _game->getLoopSubstatus() == kOuterLoop && + _game->getRoomNum() != _game->getMapRoom()) { + _game->inventorySwitch(event.kbd.keycode); + } + break; default: break; } diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 23cb4700c1..4ae0b71280 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -23,6 +23,7 @@ * */ +#include "common/keyboard.h" #include "common/serializer.h" #include "common/stream.h" #include "common/system.h" @@ -202,7 +203,8 @@ void Game::init() { _animUnderCursor = NULL; _currentItem = _itemUnderCursor = NULL; - + _previousItemPosition = -1; + _vm->_mouse->setCursorType(kHighlightedCursor); // anything different from kNormalCursor _objUnderCursor = NULL; @@ -272,8 +274,8 @@ void Game::handleOrdinaryLoop(int x, int y) { if (_vm->_mouse->lButtonPressed()) { _vm->_mouse->lButtonSet(false); - if (_currentItem) { - putItem(_currentItem, 0); + if (getCurrentItem()) { + putItem(getCurrentItem(), getPreviousItemPosition()); updateOrdinaryCursor(); } else { if (_objUnderCursor) { @@ -327,6 +329,16 @@ void Game::handleOrdinaryLoop(int x, int y) { } } +int Game::inventoryPositionFromMouse() { + const int column = CLIP(scummvm_lround( + (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) / + kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1); + const int line = CLIP(scummvm_lround( + (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) / + kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1); + return line * kInventoryColumns + column; +} + void Game::handleInventoryLoop() { if (_loopSubstatus != kOuterLoop) { return; @@ -353,19 +365,12 @@ void Game::handleInventoryLoop() { // If there is an inventory item under the cursor and we aren't // holding any item, run its look GPL program - if (_itemUnderCursor && !_currentItem) { + if (_itemUnderCursor && !getCurrentItem()) { _vm->_script->runWrapper(_itemUnderCursor->_program, _itemUnderCursor->_look, true, false); // Otherwise, if we are holding an item, try to place it inside the // inventory - } else if (_currentItem) { - const int column = CLIP(scummvm_lround( - (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) / - kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1); - const int line = CLIP(scummvm_lround( - (_vm->_mouse->getPosY() - kInventoryY + kInventoryItemHeight / 2.) / - kInventoryItemHeight) - 1, 0L, (long) kInventoryLines - 1); - const int index = line * kInventoryColumns + column; - putItem(_currentItem, index); + } else if (getCurrentItem()) { + putItem(getCurrentItem(), inventoryPositionFromMouse()); updateInventoryCursor(); } } else if (_vm->_mouse->rButtonPressed()) { @@ -381,8 +386,9 @@ void Game::handleInventoryLoop() { // The first is that there is no item in our hands. // In that case, just take the inventory item from the inventory. - if (!_currentItem) { - _currentItem = _itemUnderCursor; + if (!getCurrentItem()) { + setCurrentItem(_itemUnderCursor); + setPreviousItemPosition(inventoryPositionFromMouse()); removeItem(_itemUnderCursor); // The second is that there *is* an item in our hands. @@ -623,10 +629,10 @@ void Game::updateOrdinaryCursor() { // If there is no game object under the cursor, try using the room itself if (!_objUnderCursor) { if (_vm->_script->testExpression(_currentRoom._program, _currentRoom._canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } @@ -637,10 +643,10 @@ void Game::updateOrdinaryCursor() { // update the cursor image (highlight it). if (_objUnderCursor->_walkDir == 0) { if (_vm->_script->testExpression(_objUnderCursor->_program, _objUnderCursor->_canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } @@ -654,10 +660,10 @@ void Game::updateOrdinaryCursor() { // Load the appropriate cursor (item image if an item is held or ordinary cursor // if not) if (!mouseChanged) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kNormalCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, false); + _vm->_mouse->loadItemCursor(getCurrentItem(), false); } } } @@ -668,19 +674,19 @@ void Game::updateInventoryCursor() { if (_itemUnderCursor) { if (_vm->_script->testExpression(_itemUnderCursor->_program, _itemUnderCursor->_canUse)) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kHighlightedCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, true); + _vm->_mouse->loadItemCursor(getCurrentItem(), true); } mouseChanged = true; } } if (!mouseChanged) { - if (!_currentItem) { + if (!getCurrentItem()) { _vm->_mouse->setCursorType(kNormalCursor); } else { - _vm->_mouse->loadItemCursor(_currentItem, false); + _vm->_mouse->loadItemCursor(getCurrentItem(), false); } } } @@ -732,6 +738,8 @@ const GameObject *Game::getObjectWithAnimation(const Animation *anim) const { } void Game::removeItem(GameItem *item) { + if (!item) + return; for (uint i = 0; i < kInventorySlots; ++i) { if (_inventory[i] == item) { _inventory[i] = NULL; @@ -753,7 +761,7 @@ void Game::loadItemAnimation(GameItem *item) { void Game::putItem(GameItem *item, int position) { // Empty our hands - _currentItem = NULL; + setCurrentItem(NULL); if (!item) return; @@ -767,6 +775,7 @@ void Game::putItem(GameItem *item, int position) { break; } } + setPreviousItemPosition(position); const int line = position / kInventoryColumns + 1; const int column = position % kInventoryColumns + 1; @@ -854,6 +863,55 @@ void Game::inventoryReload() { for (uint i = 0; i < kInventorySlots; ++i) { putItem(_inventory[i], i); } + setPreviousItemPosition(0); +} + +void Game::inventorySwitch(int keycode) { + switch (keycode) { + case Common::KEYCODE_SLASH: + // Switch between holding an item and the ordinary mouse cursor. + if (!getCurrentItem()) { + if (getPreviousItemPosition() >= 0) { + GameItem* last_item = _inventory[getPreviousItemPosition()]; + setCurrentItem(last_item); + removeItem(last_item); + } + } else { + putItem(getCurrentItem(), getPreviousItemPosition()); + } + break; + case Common::KEYCODE_COMMA: + case Common::KEYCODE_PERIOD: + // Iterate between the items in the inventory. + if (getCurrentItem()) { + assert(getPreviousItemPosition() >= 0); + int direction = keycode == Common::KEYCODE_PERIOD ? +1 : -1; + // Find the next available item. + int pos = getPreviousItemPosition() + direction; + while (true) { + if (pos < 0) + pos += kInventorySlots; + else if (pos >= kInventorySlots) + pos -= kInventorySlots; + if (pos == getPreviousItemPosition() || _inventory[pos]) { + break; + } + pos += direction; + } + // Swap it with the current item. + putItem(getCurrentItem(), getPreviousItemPosition()); + GameItem* new_item = _inventory[pos]; + setCurrentItem(new_item); + setPreviousItemPosition(pos); + removeItem(new_item); + } + break; + } + if (getRoomNum() != getMapRoom()) { + updateOrdinaryCursor(); + } else { + updateInventoryCursor(); + } } void Game::dialogueMenu(int dialogueID) { diff --git a/engines/draci/game.h b/engines/draci/game.h index 3d02489da7..1c8cc68a35 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -255,6 +255,8 @@ public: GameItem *getItem(int id) { return id >= 0 && id < (int) _info._numItems ? &_items[id] : NULL; } GameItem *getCurrentItem() const { return _currentItem; } void setCurrentItem(GameItem *item) { _currentItem = item; } + int getPreviousItemPosition() const { return _previousItemPosition; } + void setPreviousItemPosition(int pos) { _previousItemPosition = pos; } void removeItem(GameItem *item); void loadItemAnimation(GameItem *item); void putItem(GameItem *item, int position); @@ -292,6 +294,7 @@ public: void inventoryDraw(); void inventoryDone(); void inventoryReload(); + void inventorySwitch(int keycode); void dialogueMenu(int dialogueID); int dialogueDraw(); @@ -325,6 +328,7 @@ public: private: void updateOrdinaryCursor(); void updateInventoryCursor(); + int inventoryPositionFromMouse(); void handleOrdinaryLoop(int x, int y); void handleInventoryLoop(); void handleDialogueLoop(); @@ -353,6 +357,10 @@ private: GameItem *_currentItem; GameItem *_itemUnderCursor; + // Last position in the inventory of the item currently in the hands, resp. of the item that + // was last in our hands. + int _previousItemPosition; + GameItem *_inventory[kInventorySlots]; Room _currentRoom; diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index a366740526..f46153ccc5 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -553,6 +553,7 @@ void Script::icoStat(const Common::Array ¶ms) { // arrow leading outside a location), set it to standard. if (_vm->_game->getCurrentItem() == item) { _vm->_game->setCurrentItem(NULL); + _vm->_game->setPreviousItemPosition(-1); if (_vm->_mouse->getCursorType() >= kItemCursor) { _vm->_mouse->setCursorType(kNormalCursor); } @@ -561,6 +562,7 @@ void Script::icoStat(const Common::Array ¶ms) { } else { _vm->_game->loadItemAnimation(item); _vm->_game->setCurrentItem(item); + _vm->_game->setPreviousItemPosition(0); // next time, try to place the item from the beginning _vm->_mouse->loadItemCursor(item, false); } } -- cgit v1.2.3 From d4a0c8a1ad162aaa8d7f207161cbe61abc458d4c Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Mon, 28 Jun 2010 04:16:00 +0000 Subject: bugfix for the item fast-switching commit svn-id: r50408 --- engines/draci/game.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 4ae0b71280..c39b763987 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -907,7 +907,7 @@ void Game::inventorySwitch(int keycode) { } break; } - if (getRoomNum() != getMapRoom()) { + if (getLoopStatus() == kStatusOrdinary) { updateOrdinaryCursor(); } else { updateInventoryCursor(); -- cgit v1.2.3 From 76b8c33aaf964dab911b00e616e7800110dd780c Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Mon, 28 Jun 2010 04:59:13 +0000 Subject: Fade palette in/out when entering/leaving a location svn-id: r50409 --- engines/draci/game.cpp | 30 +++++++++++++++++++++++++----- engines/draci/game.h | 12 ++++++++++-- engines/draci/script.cpp | 2 +- 3 files changed, 36 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index c39b763987..23c50b8f63 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -176,6 +176,9 @@ void Game::start() { // Call the outer loop doing all the hard job. loop(kOuterLoop, false); + // Fade out the palette after leaving the location. + fadePalette(true); + if (!isReloaded()) { // We are changing location. Run the hero's LOOK // program to trigger a possible cut-scene. This is @@ -428,6 +431,22 @@ void Game::handleDialogueLoop() { } } +void Game::fadePalette(bool fading_out) { + const byte *startPal = NULL; + const byte *endPal = _currentRoom._palette >= 0 + ? _vm->_paletteArchive->getFile(_currentRoom._palette)->_data + : NULL; + if (fading_out) { + startPal = endPal; + endPal = NULL; + } + for (int i = 1; i <= kBlackFadingIterations; ++i) { + _vm->_system->delayMillis(kBlackFadingTimeUnit); + _vm->_screen->interpolatePalettes(startPal, endPal, 0, kNumColours, i, kBlackFadingIterations); + _vm->_screen->copyToScreen(); + } +} + void Game::advanceAnimationsAndTestLoopExit() { // Fade the palette if requested if (_fadePhase > 0 && (_vm->_system->getMillis() - _fadeTick) >= kFadingTimeUnit) { @@ -485,7 +504,7 @@ void Game::advanceAnimationsAndTestLoopExit() { // callbacks) and redraw screen _vm->_anims->drawScene(_vm->_screen->getSurface()); _vm->_screen->copyToScreen(); - _vm->_system->delayMillis(20); + _vm->_system->delayMillis(kTimeUnit); // If the hero has arrived at his destination, after even the last // phase was correctly animated, run the callback. @@ -1364,10 +1383,11 @@ void Game::enterNewRoom() { loadRoomObjects(); loadOverlays(); - // Set room palette - const BAFile *f; - f = _vm->_paletteArchive->getFile(_currentRoom._palette); - _vm->_screen->setPalette(f->_data, 0, kNumColours); + // Draw the scene with the black palette and slowly fade into the right palette. + _vm->_screen->setPalette(NULL, 0, kNumColours); + _vm->_anims->drawScene(_vm->_screen->getSurface()); + _vm->_screen->copyToScreen(); + fadePalette(false); // Run the program for the gate the dragon came through debugC(6, kDraciLogicDebugLevel, "Running program for gate %d", _newGate); diff --git a/engines/draci/game.h b/engines/draci/game.h index 1c8cc68a35..275293074e 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -65,9 +65,16 @@ enum SpeechConstants { kStandardSpeed = 60 }; -// One fading phase is 50ms. enum FadeConstants { - kFadingTimeUnit = 50 + // One fading phase called from the game scripts is 50ms. + kFadingTimeUnit = 50, + // Fading in/out when entering/leaving a location takes 15 iterations of (at least) 7ms each. + kBlackFadingIterations = 15, + kBlackFadingTimeUnit = 7 +}; + +enum AnimationConstants { + kTimeUnit = 20 }; /** Inventory related magical constants */ @@ -334,6 +341,7 @@ private: void handleDialogueLoop(); void updateTitle(int x, int y); void updateCursor(); + void fadePalette(bool fading_out); void advanceAnimationsAndTestLoopExit(); void handleStatusChangeByMouse(); diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index f46153ccc5..0572eb7a81 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -881,7 +881,7 @@ void Script::setPalette(const Common::Array ¶ms) { } // Immediately update the palette _vm->_screen->copyToScreen(); - _vm->_system->delayMillis(20); + _vm->_system->delayMillis(kTimeUnit); } void Script::quitGame(const Common::Array ¶ms) { -- cgit v1.2.3 From 31af2bfe32429563563d5beaa320a23fc035ad71 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 07:42:16 +0000 Subject: SCI: show arguments on selector invoke breakpoint even when VM_DEBUG_SEND is not used, but in a compressed fashion svn-id: r50410 --- engines/sci/engine/vm.cpp | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d819db3d08..35f9baef7b 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -620,7 +620,28 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt printf(") at %04x:%04x\n", PRINT_REG(funcp)); #endif // VM_DEBUG_SEND if (printSendActions) { - debug("[invoke selector]\n"); + printf("[invoke selector]"); +#ifndef VM_DEBUG_SEND + int displaySize = 0; + for (int argNr = 1; argNr <= argc; argNr++) { + if (argNr == 1) + printf(" - "); + reg_t curParam = argp[argNr]; + if (curParam.segment) { + printf("[%04x:%04x] ", PRINT_REG(curParam)); + displaySize += 12; + } else { + printf("[%04x] ", curParam.offset); + displaySize += 7; + } + if (displaySize > 50) { + if (argNr < argc) + printf("..."); + break; + } + } +#endif + printf("\n"); printSendActions = false; } -- cgit v1.2.3 From 698f10611ccf82b0941b04f7d2bcebfe0c971b84 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 08:16:20 +0000 Subject: SCI: fix regression of r50405 - sq1vga right at the beginning - scripts are pausing sound and then sending manually commands afterwards svn-id: r50411 --- engines/sci/sound/midiparser_sci.cpp | 6 ++++++ 1 file changed, 6 insertions(+) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 099d4572be..9cedb86349 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -165,6 +165,12 @@ void MidiParser_SCI::sendFromScriptToDriver(uint32 midi) { // this happens for cmdSendMidi at least in sq1vga right at the start, it's a script issue return; } + if (_channelRemap[midiChannel] == -1) { + // trying to send to an unmapped channel + // this happens for cmdSendMidi at least in sq1vga right at the start, scripts are pausing the sound + // and then sending manually. it's a script issue + return; + } sendToDriver(midi); } -- cgit v1.2.3 From 52ddc711d0bcea3f447c46d25f8c5c959c5ad558 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 28 Jun 2010 08:18:55 +0000 Subject: SCI: separated the graphics initialization code a bit - Moved all of the graphics initialization code on startup inside initGraphics() - Moved all of the screen initialization (resolution, upscaled graphics etc) code inside GfxScreen() svn-id: r50412 --- engines/sci/graphics/screen.cpp | 30 +++++- engines/sci/graphics/screen.h | 2 +- engines/sci/sci.cpp | 207 ++++++++++++++++++---------------------- 3 files changed, 120 insertions(+), 119 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index bcb86e2d6f..ca8a8880b7 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -35,8 +35,34 @@ namespace Sci { -GfxScreen::GfxScreen(ResourceManager *resMan, int16 width, int16 height, int upscaledHires) : - _resMan(resMan), _width(width), _height(height), _upscaledHires(upscaledHires) { +GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { + + // Scale the screen, if needed + _upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; + + // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as + // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit + // it to platform windows. + if (g_sci->getPlatform() == Common::kPlatformWindows) { + if (g_sci->getGameId() == GID_KQ6) + _upscaledHires = GFX_SCREEN_UPSCALED_640x440; +#ifdef ENABLE_SCI32 + if (g_sci->getGameId() == GID_GK1) + _upscaledHires = GFX_SCREEN_UPSCALED_640x480; +#endif + } + + if (_resMan->detectHires()) { + _width = 640; + _height = 480; + } else { + _width = 320; + _height = 200; + } + + // Japanese versions of games use hi-res font on upscaled version of the game + if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) + _upscaledHires = GFX_SCREEN_UPSCALED_640x400; _pixels = _width * _height; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index b2479e9735..d64c2541ec 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -59,7 +59,7 @@ enum GfxScreenMasks { */ class GfxScreen { public: - GfxScreen(ResourceManager *resMan, int16 width = 320, int16 height = 200, int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED); + GfxScreen(ResourceManager *resMan); ~GfxScreen(); uint16 getWidth() { return _width; } diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 9a80420a12..822adb592b 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -136,14 +136,35 @@ SciEngine::~SciEngine() { // Remove all of our debug levels here DebugMan.clearAllDebugChannels(); +#ifdef ENABLE_SCI32 + delete _gfxFrameout; +#endif + delete _gfxMenu; + delete _gfxControls; + delete _gfxText16; + delete _gfxAnimate; + delete _gfxPaint; + delete _gfxTransitions; + delete _gfxCompare; + delete _gfxCoordAdjuster; + delete _gfxPorts; + delete _gfxCache; + delete _gfxPalette; + delete _gfxCursor; + delete _gfxScreen; + delete _audio; delete _kernel; delete _vocabulary; delete _console; - delete _resMan; delete _features; delete _gfxMacIconBar; + delete _eventMan; + delete _gamestate->_soundCmd; + delete _gamestate->_segMan; + delete _gamestate; + delete _resMan; // should be deleted last g_sci = 0; } @@ -172,74 +193,12 @@ Common::Error SciEngine::run() { SegManager *segMan = new SegManager(_resMan); - // Scale the screen, if needed - int upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; - - // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as - // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit - // it to platform windows. - if (getPlatform() == Common::kPlatformWindows) { - if (_gameId == GID_KQ6) - upscaledHires = GFX_SCREEN_UPSCALED_640x440; -#ifdef ENABLE_SCI32 - if (_gameId == GID_GK1) - upscaledHires = GFX_SCREEN_UPSCALED_640x480; -#endif - } - - // Japanese versions of games use hi-res font on upscaled version of the game - if ((getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) - upscaledHires = GFX_SCREEN_UPSCALED_640x400; - - // Reset all graphics objects - _gfxAnimate = 0; - _gfxCache = 0; - _gfxCompare = 0; - _gfxControls = 0; - _gfxCoordAdjuster = 0; - _gfxCursor = 0; - _gfxMacIconBar = 0; - _gfxMenu = 0; - _gfxPaint = 0; - _gfxPaint16 = 0; - _gfxPalette = 0; - _gfxPorts = 0; - _gfxScreen = 0; - _gfxText16 = 0; - _gfxTransitions = 0; -#ifdef ENABLE_SCI32 - _gfxFrameout = 0; - _gfxPaint32 = 0; -#endif - - // Initialize graphics-related parts - - if (_resMan->detectHires()) - _gfxScreen = new GfxScreen(_resMan, 640, 480); - else - _gfxScreen = new GfxScreen(_resMan, 320, 200, upscaledHires); - + // Initialize the game screen + _gfxScreen = new GfxScreen(_resMan); _gfxScreen->debugUnditherSetState(ConfMan.getBool("undither")); - if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) - _gfxMacIconBar = new GfxMacIconBar(); - - bool paletteMerging = true; - if (getSciVersion() >= SCI_VERSION_1_1) { - // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying - if (getSciVersion() == SCI_VERSION_1_1) - paletteMerging = _resMan->detectForPaletteMergingForSci11(); - else - paletteMerging = false; - } - - _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging); - _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); - _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen); - // Create debugger console. It requires GFX to be initialized _console = new Console(this); - _kernel = new Kernel(_resMan, segMan); _features = new GameFeatures(segMan, _kernel); // Only SCI0 and SCI01 games used a parser @@ -257,35 +216,6 @@ Common::Error SciEngine::run() { return Common::kUnknownError; } -#ifdef ENABLE_SCI32 - if (getSciVersion() >= SCI_VERSION_2) { - // SCI32 graphic objects creation - _gfxCoordAdjuster = new GfxCoordAdjuster32(segMan); - _gfxCursor->init(_gfxCoordAdjuster, _eventMan); - _gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); - _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); - _gfxPaint = _gfxPaint32; - _gfxFrameout = new GfxFrameout(segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); - } else { -#endif - // SCI0-SCI1.1 graphic objects creation - _gfxPorts = new GfxPorts(segMan, _gfxScreen); - _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); - _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); - _gfxCompare = new GfxCompare(segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); - _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); - _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); - _gfxPaint = _gfxPaint16; - _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); - _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); - _gfxControls = new GfxControls(segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); - _gfxMenu = new GfxMenu(g_sci->getEventManager(), segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); - - _gfxMenu->reset(); -#ifdef ENABLE_SCI32 - } -#endif - _kernel->loadKernelNames(_features); // Must be called after game_init() script_adjust_opcode_formats(); @@ -300,6 +230,7 @@ Common::Error SciEngine::run() { syncSoundSettings(); + // Initialize all graphics related subsystems initGraphics(); debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); @@ -336,28 +267,6 @@ Common::Error SciEngine::run() { ConfMan.flushToDisk(); - delete _gamestate->_soundCmd; -#ifdef ENABLE_SCI32 - delete _gfxFrameout; -#endif - delete _gfxMenu; - delete _gfxControls; - delete _gfxText16; - delete _gfxAnimate; - delete _gfxPaint; - delete _gfxTransitions; - delete _gfxCompare; - delete _gfxCoordAdjuster; - delete _gfxPorts; - delete _gfxCache; - delete _gfxPalette; - delete _gfxCursor; - delete _gfxScreen; - - delete _eventMan; - delete segMan; - delete _gamestate; - return Common::kNoError; } @@ -422,6 +331,72 @@ bool SciEngine::initGame() { } void SciEngine::initGraphics() { + + // Reset all graphics objects + _gfxAnimate = 0; + _gfxCache = 0; + _gfxCompare = 0; + _gfxControls = 0; + _gfxCoordAdjuster = 0; + _gfxCursor = 0; + _gfxMacIconBar = 0; + _gfxMenu = 0; + _gfxPaint = 0; + _gfxPaint16 = 0; + _gfxPalette = 0; + _gfxPorts = 0; + _gfxText16 = 0; + _gfxTransitions = 0; +#ifdef ENABLE_SCI32 + _gfxFrameout = 0; + _gfxPaint32 = 0; +#endif + + if (_resMan->isSci11Mac() && getSciVersion() == SCI_VERSION_1_1) + _gfxMacIconBar = new GfxMacIconBar(); + + bool paletteMerging = true; + if (getSciVersion() >= SCI_VERSION_1_1) { + // there are some games that use inbetween SCI1.1 interpreter, so we have to detect if it's merging or copying + if (getSciVersion() == SCI_VERSION_1_1) + paletteMerging = _resMan->detectForPaletteMergingForSci11(); + else + paletteMerging = false; + } + + _gfxPalette = new GfxPalette(_resMan, _gfxScreen, paletteMerging); + _gfxCache = new GfxCache(_resMan, _gfxScreen, _gfxPalette); + _gfxCursor = new GfxCursor(_resMan, _gfxPalette, _gfxScreen); + +#ifdef ENABLE_SCI32 + if (getSciVersion() >= SCI_VERSION_2) { + // SCI32 graphic objects creation + _gfxCoordAdjuster = new GfxCoordAdjuster32(_gamestate->_segMan); + _gfxCursor->init(_gfxCoordAdjuster, _eventMan); + _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxPaint32 = new GfxPaint32(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette); + _gfxPaint = _gfxPaint32; + _gfxFrameout = new GfxFrameout(_gamestate->_segMan, g_sci->getResMan(), _gfxCoordAdjuster, _gfxCache, _gfxScreen, _gfxPalette, _gfxPaint32); + } else { +#endif + // SCI0-SCI1.1 graphic objects creation + _gfxPorts = new GfxPorts(_gamestate->_segMan, _gfxScreen); + _gfxCoordAdjuster = new GfxCoordAdjuster16(_gfxPorts); + _gfxCursor->init(_gfxCoordAdjuster, g_sci->getEventManager()); + _gfxCompare = new GfxCompare(_gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxScreen, _gfxCoordAdjuster); + _gfxTransitions = new GfxTransitions(_gfxScreen, _gfxPalette, g_sci->getResMan()->isVGA()); + _gfxPaint16 = new GfxPaint16(g_sci->getResMan(), _gamestate->_segMan, g_sci->getKernel(), _gfxCache, _gfxPorts, _gfxCoordAdjuster, _gfxScreen, _gfxPalette, _gfxTransitions, _audio); + _gfxPaint = _gfxPaint16; + _gfxAnimate = new GfxAnimate(_gamestate, _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen, _gfxPalette, _gfxCursor, _gfxTransitions); + _gfxText16 = new GfxText16(g_sci->getResMan(), _gfxCache, _gfxPorts, _gfxPaint16, _gfxScreen); + _gfxControls = new GfxControls(_gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen); + _gfxMenu = new GfxMenu(g_sci->getEventManager(), _gamestate->_segMan, _gfxPorts, _gfxPaint16, _gfxText16, _gfxScreen, _gfxCursor); + + _gfxMenu->reset(); +#ifdef ENABLE_SCI32 + } +#endif + if (_gfxPorts) { _gfxPorts->init(_features->usesOldGfxFunctions(), _gfxPaint16, _gfxText16); _gfxPaint16->init(_gfxAnimate, _gfxText16); -- cgit v1.2.3 From 253036ec4d76492dde59d52264ade1c5730a9643 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 08:25:45 +0000 Subject: SCI: regression from implementing channel remapping and r50405 - center pitch wheels and hold pedal on init instead of unloadMusic(), fixes lsl5 piano scene svn-id: r50413 --- engines/sci/sound/midiparser_sci.cpp | 19 ++++++++----------- 1 file changed, 8 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 9cedb86349..cdc2050f8b 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -127,6 +127,14 @@ void MidiParser_SCI::sendInitCommands() { if (_channelUsed[i]) sendToDriver(0xB0 | i, 0x4E, 0); // Reset velocity } + + // Center the pitch wheels and hold pedal in preparation for the next piece of music + for (int i = 0; i < 16; ++i) { + if (_channelUsed[i]) { + sendToDriver(0xE0 | i, 0, 0x40); // Reset pitch wheel + sendToDriver(0xB0 | i, 0x40, 0); // Reset hold pedal + } + } } void MidiParser_SCI::unloadMusic() { @@ -142,17 +150,6 @@ void MidiParser_SCI::unloadMusic() { delete[] _mixedData; _mixedData = NULL; } - - // Center the pitch wheels and hold pedal in preparation for the next piece of music - if (_driver && _pSnd) { - for (int i = 0; i < 16; ++i) { - int16 realChannel = _channelRemap[i]; - if (realChannel != -1) { - _driver->send(0xE0 | realChannel, 0, 0x40); // Reset pitch wheel - _driver->send(0xB0 | realChannel, 0x40, 0); // Reset hold pedal - } - } - } } // this is used for scripts sending midi commands to us. we verify in that case that the channel is actually -- cgit v1.2.3 From e4cb2703ca654ca11bd067f4c2eef2f4631a507f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 09:22:57 +0000 Subject: SCI: implementing real setVolume() support, fixing some fading in sci1 games (like pq3 intro) svn-id: r50414 --- engines/sci/sound/midiparser_sci.cpp | 32 +++++++++++++++++++++++++++++--- engines/sci/sound/midiparser_sci.h | 1 + 2 files changed, 30 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index cdc2050f8b..5cc5873a72 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -53,7 +53,7 @@ MidiParser_SCI::MidiParser_SCI(SciVersion soundVersion, SciMusic *music) : _ppqn = 1; setTempo(16667); - _volume = 0; + _volume = 127; _signalSet = false; _signalToSet = 0; @@ -88,6 +88,7 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in _channelUsed[i] = false; _channelRemap[i] = -1; _channelMuted[i] = false; + _channelVolume[i] = 127; } _channelRemap[9] = 9; // never map channel 9, because that's used for percussion _channelRemap[15] = 15; // never map channel 15, because thats used by sierra internally @@ -109,9 +110,14 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in } void MidiParser_SCI::sendInitCommands() { + // reset our "global" volume and channel volumes + _volume = 127; + for (int i = 0; i < 16; i++) + _channelVolume[i] = 127; + + // Set initial voice count if (_pSnd) { if (_soundVersion <= SCI_VERSION_0_LATE) { - // Set initial voice count for (int i = 0; i < 15; ++i) { byte voiceCount = 0; if (_channelUsed[i]) { @@ -186,6 +192,17 @@ void MidiParser_SCI::sendToDriver(uint32 midi) { // Is channel muted? if so, don't send command if (_channelMuted[midiChannel]) return; + + if ((midi & 0xFFF0) == 0x07B0) { + // someone trying to set channel volume? + int channelVolume = (midi >> 16) & 0xFF; + // Remember, if we need to set it ourselves + _channelVolume[midiChannel] = channelVolume; + // Adjust volume accordingly to current "global" volume + channelVolume = channelVolume * _volume / 127; + midi = (midi & 0xFFF0) | ((channelVolume & 0xFF) << 16); + } + // Channel remapping int16 realChannel = _channelRemap[midiChannel]; assert(realChannel != -1); @@ -660,14 +677,23 @@ void MidiParser_SCI::lostChannels() { void MidiParser_SCI::setVolume(byte volume) { // FIXME: This receives values > 127... throw a warning for now and clip the variable if (volume > MUSIC_VOLUME_MAX) { - warning("attempted to set an invalid volume(%d)", volume); + // FIXME: please write where we get an invalid volume, so we can track down the issue + error("attempted to set an invalid volume(%d)", volume); volume = MUSIC_VOLUME_MAX; // reset } assert(volume <= MUSIC_VOLUME_MAX); + _volume = volume; + // Send previous channel volumes again to actually update the volume + for (int i = 0; i < 15; i++) + if (_channelRemap[i] != -1) + sendToDriver(0xB0 + i, 7, _channelVolume[i]); + return; + // TODO: old code, should be left here till we figured out that new code works fine if (_volume != volume) { _volume = volume; + switch (_soundVersion) { case SCI_VERSION_0_EARLY: case SCI_VERSION_0_LATE: { diff --git a/engines/sci/sound/midiparser_sci.h b/engines/sci/sound/midiparser_sci.h index 8b796d01fc..90db06e539 100644 --- a/engines/sci/sound/midiparser_sci.h +++ b/engines/sci/sound/midiparser_sci.h @@ -115,6 +115,7 @@ protected: bool _channelUsed[16]; int16 _channelRemap[16]; bool _channelMuted[16]; + byte _channelVolume[16]; }; } // End of namespace Sci -- cgit v1.2.3 From 92cc16e6a5f3b096868a8fa45b923de38d678e5d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 10:00:12 +0000 Subject: SCI: reordering and cleanup, removing debug code from sci0 mix-code svn-id: r50415 --- engines/sci/sound/midiparser_sci.cpp | 468 +++++++++++++++++------------------ 1 file changed, 229 insertions(+), 239 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 5cc5873a72..4503e97628 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -109,6 +109,235 @@ bool MidiParser_SCI::loadMusic(SoundResource::Track *track, MusicEntry *psnd, in return true; } +byte MidiParser_SCI::midiGetNextChannel(long ticker) { + byte curr = 0xFF; + long closest = ticker + 1000000, next = 0; + + for (int i = 0; i < _track->channelCount; i++) { + if (_track->channels[i].time == -1) // channel ended + continue; + SoundResource::Channel *curChannel = &_track->channels[i]; + if (curChannel->curPos >= curChannel->size) + continue; + next = curChannel->data[curChannel->curPos]; // when the next event should occur + if (next == 0xF8) // 0xF8 means 240 ticks delay + next = 240; + next += _track->channels[i].time; + if (next < closest) { + curr = i; + closest = next; + } + } + + return curr; +} + +byte *MidiParser_SCI::midiMixChannels() { + int totalSize = 0; + + for (int i = 0; i < _track->channelCount; i++) { + _track->channels[i].time = 0; + _track->channels[i].prev = 0; + _track->channels[i].curPos = 0; + totalSize += _track->channels[i].size; + } + + byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data + _mixedData = outData; + long ticker = 0; + byte channelNr, curDelta; + byte midiCommand = 0, midiParam, global_prev = 0; + long newDelta; + SoundResource::Channel *channel; + + while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel + channel = &_track->channels[channelNr]; + curDelta = channel->data[channel->curPos++]; + channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur + if (curDelta == 0xF8) + continue; + newDelta = channel->time - ticker; + ticker += newDelta; + + midiCommand = channel->data[channel->curPos++]; + if ((midiCommand == 0xCF) && (!ticker)) { + // set signal command at tick 0? + channel->curPos++; + continue; // filter it + // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately + // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to + // get immediately removed, so we currently filter it. + // TODO: find out what exactly happens in sierra sci + } + if (midiCommand != kEndOfTrack) { + // Write delta + while (newDelta > 240) { + *outData++ = 0xF8; + newDelta -= 240; + } + *outData++ = (byte)newDelta; + } + // Write command + switch (midiCommand) { + case 0xF0: // sysEx + *outData++ = midiCommand; + do { + midiParam = channel->data[channel->curPos++]; + *outData++ = midiParam; + } while (midiParam != 0xF7); + break; + case kEndOfTrack: // end of channel + channel->time = -1; + break; + default: // MIDI command + if (midiCommand & 0x80) { + midiParam = channel->data[channel->curPos++]; + } else {// running status + midiParam = midiCommand; + midiCommand = channel->prev; + } + + // remember which channel got used for channel remapping + byte midiChannel = midiCommand & 0xF; + _channelUsed[midiChannel] = true; + + if (midiCommand != global_prev) + *outData++ = midiCommand; + *outData++ = midiParam; + if (nMidiParams[(midiCommand >> 4) - 8] == 2) + *outData++ = channel->data[channel->curPos++]; + channel->prev = midiCommand; + global_prev = midiCommand; + } + } + + // Insert stop event + *outData++ = 0; // Delta + *outData++ = 0xFF; // Meta event + *outData++ = 0x2F; // End of track (EOT) + *outData++ = 0x00; + *outData++ = 0x00; + return _mixedData; +} + +// This is used for SCI0 sound-data. SCI0 only has one stream that may +// contain several channels and according to output device we remove +// certain channels from that data. +byte *MidiParser_SCI::midiFilterChannels(int channelMask) { + SoundResource::Channel *channel = &_track->channels[0]; + byte *channelData = channel->data; + byte *channelDataEnd = channel->data + channel->size; + byte *outData = new byte[channel->size + 5]; + byte curChannel = 15, curByte, curDelta; + byte command = 0, lastCommand = 0; + int delta = 0; + int midiParamCount = 0; + + _mixedData = outData; + + while (channelData < channelDataEnd) { + curDelta = *channelData++; + if (curDelta == 0xF8) { + delta += 240; + continue; + } + delta += curDelta; + curByte = *channelData++; + + switch (curByte) { + case 0xF0: // sysEx + case kEndOfTrack: // end of channel + command = curByte; + curChannel = 15; + break; + default: + if (curByte & 0x80) { + command = curByte; + curChannel = command & 0x0F; + midiParamCount = nMidiParams[(command >> 4) - 8]; + } + } + if ((1 << curChannel) & channelMask) { + if (command != kEndOfTrack) { + // Write delta + while (delta > 240) { + *outData++ = 0xF8; + delta -= 240; + } + *outData++ = (byte)delta; + delta = 0; + } + // Write command + switch (command) { + case 0xF0: // sysEx + *outData++ = command; + do { + curByte = *channelData++; + *outData++ = curByte; // out + } while (curByte != 0xF7); + lastCommand = command; + break; + + case kEndOfTrack: // end of channel + break; + + default: // MIDI command + // remember which channel got used for channel remapping + byte midiChannel = command & 0xF; + _channelUsed[midiChannel] = true; + + if (lastCommand != command) { + *outData++ = command; + lastCommand = command; + } + if (midiParamCount > 0) { + if (curByte & 0x80) + *outData++ = *channelData++; + else + *outData++ = curByte; + } + if (midiParamCount > 1) { + *outData++ = *channelData++; + } + } + } else { + if (curByte & 0x80) + channelData += midiParamCount; + else + channelData += midiParamCount - 1; + } + } + + // Insert stop event + *outData++ = 0; // Delta + *outData++ = 0xFF; // Meta event + *outData++ = 0x2F; // End of track (EOT) + *outData++ = 0x00; + *outData++ = 0x00; + + return _mixedData; +} + +// This will get called right before actual playing and will try to own the used channels +void MidiParser_SCI::tryToOwnChannels() { + // We don't have SciMusic in case debug command show_instruments is used + if (!_music) + return; + for (int curChannel = 0; curChannel < 15; curChannel++) { + if (_channelUsed[curChannel]) { + if (_channelRemap[curChannel] == -1) { + _channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel); + } + } + } +} + +void MidiParser_SCI::lostChannels() { + for (int curChannel = 0; curChannel < 15; curChannel++) + if ((_channelUsed[curChannel]) && (curChannel != 9)) + _channelRemap[curChannel] = -1; +} + void MidiParser_SCI::sendInitCommands() { // reset our "global" volume and channel volumes _volume = 127; @@ -435,245 +664,6 @@ void MidiParser_SCI::allNotesOff() { memset(_active_notes, 0, sizeof(_active_notes)); } -byte MidiParser_SCI::midiGetNextChannel(long ticker) { - byte curr = 0xFF; - long closest = ticker + 1000000, next = 0; - - for (int i = 0; i < _track->channelCount; i++) { - if (_track->channels[i].time == -1) // channel ended - continue; - SoundResource::Channel *curChannel = &_track->channels[i]; - if (curChannel->curPos >= curChannel->size) - continue; - next = curChannel->data[curChannel->curPos]; // when the next event should occur - if (next == 0xF8) // 0xF8 means 240 ticks delay - next = 240; - next += _track->channels[i].time; - if (next < closest) { - curr = i; - closest = next; - } - } - - return curr; -} - -byte *MidiParser_SCI::midiMixChannels() { - int totalSize = 0; - - for (int i = 0; i < _track->channelCount; i++) { - _track->channels[i].time = 0; - _track->channels[i].prev = 0; - _track->channels[i].curPos = 0; - totalSize += _track->channels[i].size; - } - - byte *outData = new byte[totalSize * 2]; // FIXME: creates overhead and still may be not enough to hold all data - _mixedData = outData; - long ticker = 0; - byte channelNr, curDelta; - byte midiCommand = 0, midiParam, global_prev = 0; - long newDelta; - SoundResource::Channel *channel; - - while ((channelNr = midiGetNextChannel(ticker)) != 0xFF) { // there is still an active channel - channel = &_track->channels[channelNr]; - curDelta = channel->data[channel->curPos++]; - channel->time += (curDelta == 0xF8 ? 240 : curDelta); // when the command is supposed to occur - if (curDelta == 0xF8) - continue; - newDelta = channel->time - ticker; - ticker += newDelta; - - midiCommand = channel->data[channel->curPos++]; - if ((midiCommand == 0xCF) && (!ticker)) { - // set signal command at tick 0? - channel->curPos++; - continue; // filter it - // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately - // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to - // get immediately removed, so we currently filter it. - // TODO: find out what exactly happens in sierra sci - } - if (midiCommand != kEndOfTrack) { - // Write delta - while (newDelta > 240) { - *outData++ = 0xF8; - newDelta -= 240; - } - *outData++ = (byte)newDelta; - } - // Write command - switch (midiCommand) { - case 0xF0: // sysEx - *outData++ = midiCommand; - do { - midiParam = channel->data[channel->curPos++]; - *outData++ = midiParam; - } while (midiParam != 0xF7); - break; - case kEndOfTrack: // end of channel - channel->time = -1; - break; - default: // MIDI command - if (midiCommand & 0x80) { - midiParam = channel->data[channel->curPos++]; - } else {// running status - midiParam = midiCommand; - midiCommand = channel->prev; - } - - // remember which channel got used for channel remapping - byte midiChannel = midiCommand & 0xF; - _channelUsed[midiChannel] = true; - - if (midiCommand != global_prev) - *outData++ = midiCommand; - *outData++ = midiParam; - if (nMidiParams[(midiCommand >> 4) - 8] == 2) - *outData++ = channel->data[channel->curPos++]; - channel->prev = midiCommand; - global_prev = midiCommand; - } - } - - // Insert stop event - *outData++ = 0; // Delta - *outData++ = 0xFF; // Meta event - *outData++ = 0x2F; // End of track (EOT) - *outData++ = 0x00; - *outData++ = 0x00; - return _mixedData; -} - -// This is used for SCI0 sound-data. SCI0 only has one stream that may -// contain several channels and according to output device we remove -// certain channels from that data. -byte *MidiParser_SCI::midiFilterChannels(int channelMask) { - SoundResource::Channel *channel = &_track->channels[0]; - byte *channelData = channel->data; - byte *channelDataEnd = channel->data + channel->size; - byte *outData = new byte[channel->size + 5]; - byte curChannel = 15, curByte, curDelta; - byte command = 0, lastCommand = 0; - int delta = 0; - int midiParamCount = 0; - - _mixedData = outData; - - while (channelData < channelDataEnd) { - curDelta = *channelData++; - if (curDelta == 0xF8) { - delta += 240; - continue; - } - delta += curDelta; - curByte = *channelData++; - - switch (curByte) { - case 0xF0: // sysEx - case kEndOfTrack: // end of channel - command = curByte; - curChannel = 15; - break; - default: - if (curByte & 0x80) { - command = curByte; - curChannel = command & 0x0F; - midiParamCount = nMidiParams[(command >> 4) - 8]; - } - } - if ((1 << curChannel) & channelMask) { - if (command != kEndOfTrack) { - debugC(4, kDebugLevelSound, "\nDELTA "); - // Write delta - while (delta > 240) { - *outData++ = 0xF8; - debugC(4, kDebugLevelSound, "F8 "); - delta -= 240; - } - *outData++ = (byte)delta; - debugC(4, kDebugLevelSound, "%02X ", delta); - delta = 0; - } - // Write command - switch (command) { - case 0xF0: // sysEx - *outData++ = command; - debugC(4, kDebugLevelSound, "%02X ", command); - do { - curByte = *channelData++; - *outData++ = curByte; // out - } while (curByte != 0xF7); - lastCommand = command; - break; - - case kEndOfTrack: // end of channel - break; - - default: // MIDI command - // remember which channel got used for channel remapping - byte midiChannel = command & 0xF; - _channelUsed[midiChannel] = true; - - if (lastCommand != command) { - *outData++ = command; - debugC(4, kDebugLevelSound, "%02X ", command); - lastCommand = command; - } - if (midiParamCount > 0) { - if (curByte & 0x80) { - debugC(4, kDebugLevelSound, "%02X ", *channelData); - *outData++ = *channelData++; - } else { - debugC(4, kDebugLevelSound, "%02X ", curByte); - *outData++ = curByte; - } - } - if (midiParamCount > 1) { - debugC(4, kDebugLevelSound, "%02X ", *channelData); - *outData++ = *channelData++; - } - } - } else { - if (curByte & 0x80) { - channelData += midiParamCount; - } else { - channelData += midiParamCount - 1; - } - } - } - - // Insert stop event - *outData++ = 0; // Delta - *outData++ = 0xFF; // Meta event - *outData++ = 0x2F; // End of track (EOT) - *outData++ = 0x00; - *outData++ = 0x00; - - return _mixedData; -} - -// This will get called right before actual playing and will try to own the used channels -void MidiParser_SCI::tryToOwnChannels() { - // We don't have SciMusic in case debug command show_instruments is used - if (!_music) - return; - for (int curChannel = 0; curChannel < 15; curChannel++) { - if (_channelUsed[curChannel]) { - if (_channelRemap[curChannel] == -1) { - _channelRemap[curChannel] = _music->tryToOwnChannel(_pSnd, curChannel); - } - } - } -} - -void MidiParser_SCI::lostChannels() { - for (int curChannel = 0; curChannel < 15; curChannel++) - if ((_channelUsed[curChannel]) && (curChannel != 9)) - _channelRemap[curChannel] = -1; -} - void MidiParser_SCI::setVolume(byte volume) { // FIXME: This receives values > 127... throw a warning for now and clip the variable if (volume > MUSIC_VOLUME_MAX) { -- cgit v1.2.3 From 10a9dfc0d7a521d7f9815fd21edc5e7b82d8344c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 10:15:13 +0000 Subject: SCI: added uninit workaround for lsl3 - when accessing set volume menu the first time sound got muted before (because a uninitialized temp was used to do it, would have been 's' in sierra sci) svn-id: r50416 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 35f9baef7b..d247ce1cfb 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -279,6 +279,7 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room + { GID_LSL3, 997, "TheMenuBar", "handleEvent", -1, 1, 0xf }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') { GID_LSL6, 928, "Narrator", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions, that's why we use the base-class { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon -- cgit v1.2.3 From caa4479bdf593241e3a93525387f98ba4fd969bf Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 10:36:10 +0000 Subject: SCI: changed the way setVolume works for sci0 back to the way it was from r50414, because adlib driver doesn't support channel volume changes for sci0 games, fixes fading in those games svn-id: r50417 --- engines/sci/sound/midiparser_sci.cpp | 16 ++++------------ 1 file changed, 4 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 4503e97628..4172d05888 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -673,20 +673,14 @@ void MidiParser_SCI::setVolume(byte volume) { } assert(volume <= MUSIC_VOLUME_MAX); - _volume = volume; - // Send previous channel volumes again to actually update the volume - for (int i = 0; i < 15; i++) - if (_channelRemap[i] != -1) - sendToDriver(0xB0 + i, 7, _channelVolume[i]); - return; - // TODO: old code, should be left here till we figured out that new code works fine if (_volume != volume) { _volume = volume; - switch (_soundVersion) { case SCI_VERSION_0_EARLY: case SCI_VERSION_0_LATE: { + // SCI0 adlib driver doesn't support channel volumes, so we need to go this way + // TODO: this should take the actual master volume into account int16 globalVolume = _volume * 15 / 127; ((MidiPlayer *)_driver)->setVolume(globalVolume); break; @@ -694,12 +688,10 @@ void MidiParser_SCI::setVolume(byte volume) { case SCI_VERSION_1_EARLY: case SCI_VERSION_1_LATE: - // sending volume change to all currently mapped channels - // FIXME?: maybe we should better store new volume if music isn't playing currently and adjust volume - // when playing + // Send previous channel volumes again to actually update the volume for (int i = 0; i < 15; i++) if (_channelRemap[i] != -1) - sendToDriver(0xB0 + i, 7, _volume); + sendToDriver(0xB0 + i, 7, _channelVolume[i]); break; default: -- cgit v1.2.3 From 22a8b2236ee57884929b71eb8cbf1adb5a071b37 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 10:48:09 +0000 Subject: SCI: set volume all the time, fixes volume being 0 after fading in sci0 svn-id: r50418 --- engines/sci/sound/midiparser_sci.cpp | 42 +++++++++++++++++------------------- 1 file changed, 20 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 4172d05888..2a86ef8942 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -673,30 +673,28 @@ void MidiParser_SCI::setVolume(byte volume) { } assert(volume <= MUSIC_VOLUME_MAX); - if (_volume != volume) { - _volume = volume; - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: { - // SCI0 adlib driver doesn't support channel volumes, so we need to go this way - // TODO: this should take the actual master volume into account - int16 globalVolume = _volume * 15 / 127; - ((MidiPlayer *)_driver)->setVolume(globalVolume); - break; - } + _volume = volume; + + switch (_soundVersion) { + case SCI_VERSION_0_EARLY: + case SCI_VERSION_0_LATE: { + // SCI0 adlib driver doesn't support channel volumes, so we need to go this way + // TODO: this should take the actual master volume into account + int16 globalVolume = _volume * 15 / 127; + ((MidiPlayer *)_driver)->setVolume(globalVolume); + break; + } - case SCI_VERSION_1_EARLY: - case SCI_VERSION_1_LATE: - // Send previous channel volumes again to actually update the volume - for (int i = 0; i < 15; i++) - if (_channelRemap[i] != -1) - sendToDriver(0xB0 + i, 7, _channelVolume[i]); - break; + case SCI_VERSION_1_EARLY: + case SCI_VERSION_1_LATE: + // Send previous channel volumes again to actually update the volume + for (int i = 0; i < 15; i++) + if (_channelRemap[i] != -1) + sendToDriver(0xB0 + i, 7, _channelVolume[i]); + break; - default: - error("MidiParser_SCI::setVolume: Unsupported soundVersion"); - } + default: + error("MidiParser_SCI::setVolume: Unsupported soundVersion"); } } -- cgit v1.2.3 From 4016bdfd271be8f20d6da5bbfad982d2fb7fa24d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:19:27 +0000 Subject: SCI: cleanup svn-id: r50419 --- engines/sci/engine/kgraphics.cpp | 3 +-- engines/sci/engine/vm.cpp | 26 +++++++++++++------------- 2 files changed, 14 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index b1cd1451d1..c9d3c92603 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1346,8 +1346,7 @@ reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv) { int flags = argv[3].offset; Common::String flagspec; - if (argc > 3) - { + if (argc > 3) { if (flags & 1) flagspec += "doubled "; if (flags & 2) diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d247ce1cfb..555576f579 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -398,7 +398,7 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i } } -#define READ_VAR(type, index, def) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, def) +#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, s->r_acc) #define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); @@ -1654,7 +1654,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lap: // 0x43 (67) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - s->r_acc = READ_VAR(var_type, var_number, s->r_acc); + s->r_acc = READ_VAR(var_type, var_number); break; case op_lsg: // 0x44 (68) @@ -1663,7 +1663,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lsp: // 0x47 (71) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - PUSH32(READ_VAR(var_type, var_number, s->r_acc)); + PUSH32(READ_VAR(var_type, var_number)); break; case op_lagi: // 0x48 (72) @@ -1672,7 +1672,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lapi: // 0x4b (75) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - s->r_acc = READ_VAR(var_type, var_number, s->r_acc); + s->r_acc = READ_VAR(var_type, var_number); break; case op_lsgi: // 0x4c (76) @@ -1681,7 +1681,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lspi: // 0x4f (79) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - PUSH32(READ_VAR(var_type, var_number, s->r_acc)); + PUSH32(READ_VAR(var_type, var_number)); break; case op_sag: // 0x50 (80) @@ -1730,7 +1730,7 @@ void run_vm(EngineState *s, bool restoring) { case op_plusap: // 0x63 (99) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, 1); @@ -1745,7 +1745,7 @@ void run_vm(EngineState *s, bool restoring) { case op_plussp: // 0x67 (103) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, 1); @@ -1761,7 +1761,7 @@ void run_vm(EngineState *s, bool restoring) { case op_plusapi: // 0x6b (107) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, 1); @@ -1776,7 +1776,7 @@ void run_vm(EngineState *s, bool restoring) { case op_plusspi: // 0x6f (111) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, 1); @@ -1792,7 +1792,7 @@ void run_vm(EngineState *s, bool restoring) { case op_minusap: // 0x73 (115) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, -1); @@ -1807,7 +1807,7 @@ void run_vm(EngineState *s, bool restoring) { case op_minussp: // 0x77 (119) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, -1); @@ -1823,7 +1823,7 @@ void run_vm(EngineState *s, bool restoring) { case op_minusapi: // 0x7b (123) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! s->r_acc = pointer_add(s, r_temp, -1); @@ -1838,7 +1838,7 @@ void run_vm(EngineState *s, bool restoring) { case op_minusspi: // 0x7f (127) var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); - r_temp = READ_VAR(var_type, var_number, s->r_acc); + r_temp = READ_VAR(var_type, var_number); if (r_temp.segment) { // Pointer arithmetics! r_temp = pointer_add(s, r_temp, -1); -- cgit v1.2.3 From db2d41a4332c6c2a468f4460a23189a750fb8616 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:19:45 +0000 Subject: SCI: Make src param of GfxScreen::scale2x const svn-id: r50420 --- engines/sci/graphics/screen.cpp | 4 ++-- engines/sci/graphics/screen.h | 6 ++++-- 2 files changed, 6 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index ca8a8880b7..519020f3a1 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -583,9 +583,9 @@ void GfxScreen::debugShowMap(int mapNo) { copyToScreen(); } -void GfxScreen::scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { +void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { int newWidth = srcWidth * 2; - byte *srcPtr = src; + const byte *srcPtr = src; for (int y = 0; y < srcHeight; y++) { for (int x = 0; x < srcWidth; x++) { diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index d64c2541ec..c1e10fabc8 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -50,7 +50,9 @@ enum GfxScreenMasks { GFX_SCREEN_MASK_ALL = GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY|GFX_SCREEN_MASK_CONTROL }; -#define SCI_SCREEN_UNDITHERMEMORIAL_SIZE 256 +enum { + SCI_SCREEN_UNDITHERMEMORIAL_SIZE = 256 +}; /** * Screen class, actually creates 3 (4) screens internally - which is visual/display (for the user), @@ -104,7 +106,7 @@ public: void setVerticalShakePos(uint16 shakePos); - void scale2x(byte *src, byte *dst, int16 srcWidth, int16 srcHeight); + void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight); void adjustToUpscaledCoordinates(int16 &y, int16 &x); -- cgit v1.2.3 From 9f48a37671737229e76cd38cf766d855fd2e7318 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:20:14 +0000 Subject: SCI: Add const qualifiers to many GfxView methods and their return values. This helps to ensure proper data encapsulation. Also reformatted some overlong comments to 80 chars per line, and fixed some other code formatting issues. svn-id: r50421 --- engines/sci/graphics/animate.cpp | 8 +-- engines/sci/graphics/compare.cpp | 8 +-- engines/sci/graphics/cursor.cpp | 18 +++--- engines/sci/graphics/frameout.cpp | 4 +- engines/sci/graphics/view.cpp | 113 +++++++++++++++++++++----------------- engines/sci/graphics/view.h | 22 ++++---- 6 files changed, 91 insertions(+), 82 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 491553cebe..6a5bbff6bb 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -267,9 +267,9 @@ void GfxAnimate::fill(byte &old_picNotValid) { // Create rect according to coordinates and given cel if (listEntry->scaleSignal & kScaleSignalDoScaling) { - view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, &listEntry->celRect); + view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, listEntry->celRect); } else { - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect); + view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->celRect); } writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), listEntry->celRect.left); writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), listEntry->celRect.top); @@ -583,7 +583,7 @@ void GfxAnimate::addToPicDrawCels() { view = _cache->getView(listEntry->viewId); // Create rect according to coordinates and given cel - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, &listEntry->celRect); + view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->celRect); // draw corresponding cel _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo); @@ -601,7 +601,7 @@ void GfxAnimate::addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celN Common::Rect celRect; // Create rect according to coordinates and given cel - view->getCelRect(loopNo, celNo, leftPos, topPos, priority, &celRect); + view->getCelRect(loopNo, celNo, leftPos, topPos, priority, celRect); _paint16->drawCel(view, loopNo, celNo, celRect, priority, 0); } diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index a245eefdda..7cd55b1139 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -132,7 +132,7 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) { // now get cel rectangle view = _cache->getView(viewId); - view->getCelRect(loopNo, celNo, x, y, z, &celRect); + view->getCelRect(loopNo, celNo, x, y, z, celRect); if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) { writeSelectorValue(_segMan, objectReference, SELECTOR(nsLeft), celRect.left); @@ -175,10 +175,10 @@ bool GfxCompare::kernelCanBeHere(reg_t curObject, reg_t listReference) { bool GfxCompare::kernelIsItSkip(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Point position) { GfxView *tmpView = _cache->getView(viewId); - CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); + const CelInfo *celInfo = tmpView->getCelInfo(loopNo, celNo); position.x = CLIP(position.x, 0, celInfo->width - 1); position.y = CLIP(position.y, 0, celInfo->height - 1); - byte *celData = tmpView->getBitmap(loopNo, celNo); + const byte *celData = tmpView->getBitmap(loopNo, celNo); bool result = (celData[position.y * celInfo->width + position.x] == celInfo->clearKey); return result; } @@ -200,7 +200,7 @@ void GfxCompare::kernelBaseSetter(reg_t object) { GfxView *tmpView = _cache->getView(viewId); Common::Rect celRect; - tmpView->getCelRect(loopNo, celNo, x, y, z, &celRect); + tmpView->getCelRect(loopNo, celNo, x, y, z, celRect); celRect.bottom = y + 1; celRect.top = celRect.bottom - yStep; diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index db42dac3dd..c5f4de9cf5 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -164,12 +164,11 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co GfxView *cursorView = _cachedCursors[viewNum]; - CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum); + const CelInfo *celInfo = cursorView->getCelInfo(loopNum, celNum); int16 width = celInfo->width; int16 height = celInfo->height; byte clearKey = celInfo->clearKey; Common::Point *cursorHotspot = hotspot; - byte *cursorBitmap; if (!cursorHotspot) // Compute hotspot from xoffset/yoffset @@ -182,24 +181,21 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co return; } - celInfo->rawBitmap = cursorView->getBitmap(loopNum, celNum); + const byte *rawBitmap = cursorView->getBitmap(loopNum, celNum); if (_upscaledHires) { // Scale cursor by 2x - note: sierra didn't do this, but it looks much better width *= 2; height *= 2; cursorHotspot->x *= 2; cursorHotspot->y *= 2; - cursorBitmap = new byte[width * height]; - _screen->scale2x(celInfo->rawBitmap, cursorBitmap, celInfo->width, celInfo->height); + byte *cursorBitmap = new byte[width * height]; + _screen->scale2x(rawBitmap, cursorBitmap, celInfo->width, celInfo->height); + CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); + delete[] cursorBitmap; } else { - cursorBitmap = celInfo->rawBitmap; + CursorMan.replaceCursor(rawBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); } - CursorMan.replaceCursor(cursorBitmap, width, height, cursorHotspot->x, cursorHotspot->y, clearKey); - - if (_upscaledHires) - delete[] cursorBitmap; - kernelShow(); delete cursorHotspot; diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 4247c4db9e..446db82566 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -229,9 +229,9 @@ void GfxFrameout::kernelFrameout() { GfxView *view = _cache->getView(itemEntry->viewId); if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, &itemEntry->celRect); + view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); else - view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, &itemEntry->celRect); + view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) continue; diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 5436e426ff..0749d958a0 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -82,10 +82,11 @@ void GfxView::initData(GuiResourceId resourceId) { _embeddedPal = false; _EGAmapping = NULL; - // If we find a SCI1/SCI1.1 view (not amiga), we switch to that type for EGA - // This could get used to make view patches for EGA games, where the new views include more colors - // Users could manually adjust old views to make them look better (like removing dithered colors that aren't - // caught by our undithering or even improve the graphics overall) + // If we find an SCI1/SCI1.1 view (not amiga), we switch to that type for + // EGA. This could get used to make view patches for EGA games, where the + // new views include more colors. Users could manually adjust old views to + // make them look better (like removing dithered colors that aren't caught + // by our undithering or even improve the graphics overall). if (curViewType == kViewEga) { if (_resourceData[1] == 0x80) { curViewType = kViewVga; @@ -110,10 +111,12 @@ void GfxView::initData(GuiResourceId resourceId) { palOffset = READ_LE_UINT16(_resourceData + 6); if (palOffset && palOffset != 0x100) { - // Some SCI0/SCI01 games also have an offset set. It seems that it points to a 16-byte mapping table - // but on those games using that mapping will actually screw things up. - // On the other side: vga sci1 games have this pointing to a VGA palette - // and ega sci1 games have this pointing to a 8x16 byte mapping table that needs to get applied then + // Some SCI0/SCI01 games also have an offset set. It seems that it + // points to a 16-byte mapping table but on those games using that + // mapping will actually screw things up. On the other side: VGA + // SCI1 games have this pointing to a VGA palette and EGA SCI1 games + // have this pointing to a 8x16 byte mapping table that needs to get + // applied then. if (!isEGA) { _palette->createFromData(&_resourceData[palOffset], _resourceSize - palOffset, &_viewPalette); _embeddedPal = true; @@ -122,7 +125,7 @@ void GfxView::initData(GuiResourceId resourceId) { if (getSciVersion() >= SCI_VERSION_1_EGA) { _EGAmapping = &_resourceData[palOffset]; for (EGAmapNr = 0; EGAmapNr < SCI_VIEW_EGAMAPPING_COUNT; EGAmapNr++) { - if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE)!=0) + if (memcmp(_EGAmapping, EGAmappingStraight, SCI_VIEW_EGAMAPPING_SIZE) != 0) break; _EGAmapping += SCI_VIEW_EGAMAPPING_SIZE; } @@ -184,12 +187,13 @@ void GfxView::initData(GuiResourceId resourceId) { case kViewVga11: // View-format SCI1.1+ // HeaderSize:WORD LoopCount:BYTE Unknown:BYTE Version:WORD Unknown:WORD PaletteOffset:WORD - headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so its added + headerSize = READ_SCI11ENDIAN_UINT16(_resourceData + 0) + 2; // headerSize is not part of the header, so it's added assert(headerSize >= 16); _loopCount = _resourceData[2]; assert(_loopCount); palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8); - // FIXME: After LoopCount there is another byte and its set for view 50 within Laura Bow 2 CD, check what it means + // FIXME: After LoopCount there is another byte and its set for view 50 + // within Laura Bow 2 CD, check what it means. loopData = _resourceData + headerSize; loopSize = _resourceData[12]; @@ -251,47 +255,47 @@ void GfxView::initData(GuiResourceId resourceId) { } } -GuiResourceId GfxView::getResourceId() { +GuiResourceId GfxView::getResourceId() const { return _resourceId; } -int16 GfxView::getWidth(int16 loopNo, int16 celNo) { +int16 GfxView::getWidth(int16 loopNo, int16 celNo) const { loopNo = CLIP(loopNo, 0, _loopCount - 1); celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); return _loopCount ? _loop[loopNo].cel[celNo].width : 0; } -int16 GfxView::getHeight(int16 loopNo, int16 celNo) { - loopNo = CLIP(loopNo, 0, _loopCount -1); +int16 GfxView::getHeight(int16 loopNo, int16 celNo) const { + loopNo = CLIP(loopNo, 0, _loopCount - 1); celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); return _loopCount ? _loop[loopNo].cel[celNo].height : 0; } -CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) { +const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const { loopNo = CLIP(loopNo, 0, _loopCount - 1); celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); return _loopCount ? &_loop[loopNo].cel[celNo] : NULL; } -LoopInfo *GfxView::getLoopInfo(int16 loopNo) { +const LoopInfo *GfxView::getLoopInfo(int16 loopNo) const { loopNo = CLIP(loopNo, 0, _loopCount - 1); return _loopCount ? &_loop[loopNo] : NULL; } -void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect) { - CelInfo *celInfo = getCelInfo(loopNo, celNo); +void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const { + const CelInfo *celInfo = getCelInfo(loopNo, celNo); if (celInfo) { - outRect->left = x + celInfo->displaceX - (celInfo->width >> 1); - outRect->right = outRect->left + celInfo->width; - outRect->bottom = y + celInfo->displaceY - z + 1; - outRect->top = outRect->bottom - celInfo->height; + outRect.left = x + celInfo->displaceX - (celInfo->width >> 1); + outRect.right = outRect.left + celInfo->width; + outRect.bottom = y + celInfo->displaceY - z + 1; + outRect.top = outRect.bottom - celInfo->height; } } -void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect) { +void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const { int16 scaledDisplaceX, scaledDisplaceY; int16 scaledWidth, scaledHeight; - CelInfo *celInfo = getCelInfo(loopNo, celNo); + const CelInfo *celInfo = getCelInfo(loopNo, celNo); if (celInfo) { // Scaling displaceX/Y, Width/Height scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7; @@ -301,15 +305,15 @@ void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int1 scaledWidth = CLIP(scaledWidth, 0, _screen->getWidth()); scaledHeight = CLIP(scaledHeight, 0, _screen->getHeight()); - outRect->left = x + scaledDisplaceX - (scaledWidth >> 1); - outRect->right = outRect->left + scaledWidth; - outRect->bottom = y + scaledDisplaceY - z + 1; - outRect->top = outRect->bottom - scaledHeight; + outRect.left = x + scaledDisplaceX - (scaledWidth >> 1); + outRect.right = outRect.left + scaledWidth; + outRect.bottom = y + scaledDisplaceY - z + 1; + outRect.top = outRect.bottom - scaledHeight; } } void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) { - CelInfo *celInfo = getCelInfo(loopNo, celNo); + const CelInfo *celInfo = getCelInfo(loopNo, celNo); byte *rlePtr; byte *literalPtr; uint32 pixelNo = 0, runLength; @@ -325,9 +329,10 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou pixelNo += runLength; } } else { - // we skip over transparent pixels, so the buffer needs to be already filled with it - // also some RLE compressed cels are possibly ending with the last non-transparent pixel - // (is this even possible with the current code?) + // We skip over transparent pixels, so the buffer needs to be already + // filled with "it". (FIXME: What is "it" supposed to mean here?) + // Also some RLE compressed cels are possibly ending with the last + // non-transparent pixel (is this even possible with the current code?) memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount); rlePtr = _resourceData + celInfo->offsetRLE; @@ -371,7 +376,7 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou literalPtr = _resourceData + celInfo->offsetLiteral; if (celInfo->offsetRLE) { if (g_sci->getPlatform() == Common::kPlatformMacintosh && getSciVersion() >= SCI_VERSION_1_1) { - // Crazy-Ass compression for SCI1.1+ Mac + // compression for SCI1.1+ Mac while (pixelNo < pixelCount) { uint32 pixelLine = pixelNo; runLength = *rlePtr++; @@ -414,7 +419,7 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou } } -byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { +const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { loopNo = CLIP(loopNo, 0, _loopCount -1); celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); if (_loop[loopNo].cel[celNo].rawBitmap) @@ -443,8 +448,10 @@ byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { return _loop[loopNo].cel[celNo].rawBitmap; } -// Called after unpacking an EGA cel, this will try to undither (parts) of the cel if the dithering in here -// matches dithering used by the current picture +/** + * Called after unpacking an EGA cel, this will try to undither (parts) of the + * cel if the dithering in here matches dithering used by the current picture. + */ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) { int16 *unditherMemorial = _screen->unditherGetMemorial(); @@ -453,7 +460,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl return; // Makes no sense to process bitmaps that are 3 pixels wide or less - if (width <= 3) return; + if (width <= 3) + return; // If EGA mapping is used for this view, dont do undithering as well if (_EGAmapping) @@ -490,7 +498,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl color1 = color & 0x0F; color2 = color >> 4; if ((color1 != clearKey) && (color2 != clearKey) && (color1 != color2)) { // so set this and the reversed color-combination for undithering - unditherTable[color] = true; unditherTable[(color1 << 4) | color2] = true; + unditherTable[color] = true; + unditherTable[(color1 << 4) | color2] = true; unditherCount++; } } @@ -507,8 +516,9 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl for (x = 1; x < width; x++) { color = (color << 4) | curPtr[1]; if (unditherTable[color]) { - // some color with black? turn colors around otherwise it wont be the right color at all - if ((color & 0xF0)==0) + // Some color with black? Turn colors around, otherwise it won't + // be the right color at all. + if ((color & 0xF0) == 0) color = (color << 4) | (color >> 4); curPtr[0] = color; curPtr[1] = color; } @@ -518,10 +528,10 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl } } -void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { +void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; - CelInfo *celInfo = getCelInfo(loopNo, celNo); - byte *bitmap = getBitmap(loopNo, celNo); + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + const byte *bitmap = getBitmap(loopNo, celNo); int16 celHeight = celInfo->height, celWidth = celInfo->width; int16 width, height; byte clearKey = celInfo->clearKey; @@ -568,12 +578,15 @@ void GfxView::draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRe } } -// We don't fully follow sierra sci here, I did the scaling algo myself and it's definitely not pixel-perfect -// with the one sierra is using. It shouldn't matter because the scaled cel rect is definitely the same as in sierra sci -void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { +/** + * We don't fully follow sierra sci here, I did the scaling algo myself and it + * is definitely not pixel-perfect with the one sierra is using. It shouldn't + * matter because the scaled cel rect is definitely the same as in sierra sci. + */ +void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; - CelInfo *celInfo = getCelInfo(loopNo, celNo); - byte *bitmap = getBitmap(loopNo, celNo); + const CelInfo *celInfo = getCelInfo(loopNo, celNo); + const byte *bitmap = getBitmap(loopNo, celNo); int16 celHeight = celInfo->height, celWidth = celInfo->width; byte clearKey = celInfo->clearKey; byte color; @@ -647,7 +660,7 @@ void GfxView::drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect } } -uint16 GfxView::getCelCount(int16 loopNo) { +uint16 GfxView::getCelCount(int16 loopNo) const { if ((loopNo < 0) || (loopNo >= _loopCount)) return 0; return _loop[loopNo].celCount; diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index fe033dfe23..dd25bde3f2 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -60,18 +60,18 @@ public: GfxView(ResourceManager *resMan, GfxScreen *screen, GfxPalette *palette, GuiResourceId resourceId); ~GfxView(); - GuiResourceId getResourceId(); - int16 getWidth(int16 loopNo, int16 celNo); - int16 getHeight(int16 loopNo, int16 celNo); - CelInfo *getCelInfo(int16 loopNo, int16 celNo); - LoopInfo *getLoopInfo(int16 loopNo); - void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect *outRect); - void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect *outRect); - byte *getBitmap(int16 loopNo, int16 celNo); - void draw(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires); - void drawScaled(Common::Rect rect, Common::Rect clipRect, Common::Rect clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY); + GuiResourceId getResourceId() const; + int16 getWidth(int16 loopNo, int16 celNo) const; + int16 getHeight(int16 loopNo, int16 celNo) const; + const CelInfo *getCelInfo(int16 loopNo, int16 celNo) const; + const LoopInfo *getLoopInfo(int16 loopNo) const; + void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const; + void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const; + const byte *getBitmap(int16 loopNo, int16 celNo); + void draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires); + void drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY); uint16 getLoopCount() const { return _loopCount; } - uint16 getCelCount(int16 loopNo); + uint16 getCelCount(int16 loopNo) const; Palette *getPalette(); private: -- cgit v1.2.3 From 2c01d10a36f50da6c8bdcfe70558f7d9a2e56324 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:20:33 +0000 Subject: SCI: Remove GfxView::getLoopInfo; add assert to GfxView::getCelInfo The return value of GfxView::getCelInfo was used virtually everywhere without a check for it being non-NULL. Hence instead of returning NULL when the loop count is zero, it makes more sense to assert out (instead of a segfault, or worse, random data being used). svn-id: r50422 --- engines/sci/graphics/cache.cpp | 2 +- engines/sci/graphics/view.cpp | 63 +++++++++++++++++++----------------------- engines/sci/graphics/view.h | 1 - 3 files changed, 30 insertions(+), 36 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cache.cpp b/engines/sci/graphics/cache.cpp index 81bdab80ea..8caa28b3a1 100644 --- a/engines/sci/graphics/cache.cpp +++ b/engines/sci/graphics/cache.cpp @@ -102,7 +102,7 @@ int16 GfxCache::kernelViewGetLoopCount(GuiResourceId viewId) { } int16 GfxCache::kernelViewGetCelCount(GuiResourceId viewId, int16 loopNo) { - return getView(viewId)->getLoopInfo(loopNo)->celCount; + return getView(viewId)->getCelCount(loopNo); } } // End of namespace Sci diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 0749d958a0..b255b18adc 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -272,44 +272,49 @@ int16 GfxView::getHeight(int16 loopNo, int16 celNo) const { } const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const { + assert(_loopCount); loopNo = CLIP(loopNo, 0, _loopCount - 1); celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? &_loop[loopNo].cel[celNo] : NULL; + return &_loop[loopNo].cel[celNo]; } -const LoopInfo *GfxView::getLoopInfo(int16 loopNo) const { - loopNo = CLIP(loopNo, 0, _loopCount - 1); - return _loopCount ? &_loop[loopNo] : NULL; +uint16 GfxView::getCelCount(int16 loopNo) const { +// assert(_loopCount); +// loopNo = CLIP(loopNo, 0, _loopCount - 1); + if ((loopNo < 0) || (loopNo >= _loopCount)) + return 0; + return _loop[loopNo].celCount; +} + +Palette *GfxView::getPalette() { + return _embeddedPal ? &_viewPalette : NULL; } void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const { const CelInfo *celInfo = getCelInfo(loopNo, celNo); - if (celInfo) { - outRect.left = x + celInfo->displaceX - (celInfo->width >> 1); - outRect.right = outRect.left + celInfo->width; - outRect.bottom = y + celInfo->displaceY - z + 1; - outRect.top = outRect.bottom - celInfo->height; - } + outRect.left = x + celInfo->displaceX - (celInfo->width >> 1); + outRect.right = outRect.left + celInfo->width; + outRect.bottom = y + celInfo->displaceY - z + 1; + outRect.top = outRect.bottom - celInfo->height; } void GfxView::getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const { int16 scaledDisplaceX, scaledDisplaceY; int16 scaledWidth, scaledHeight; const CelInfo *celInfo = getCelInfo(loopNo, celNo); - if (celInfo) { - // Scaling displaceX/Y, Width/Height - scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7; - scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7; - scaledWidth = (celInfo->width * scaleX) >> 7; - scaledHeight = (celInfo->height * scaleY) >> 7; - scaledWidth = CLIP(scaledWidth, 0, _screen->getWidth()); - scaledHeight = CLIP(scaledHeight, 0, _screen->getHeight()); - - outRect.left = x + scaledDisplaceX - (scaledWidth >> 1); - outRect.right = outRect.left + scaledWidth; - outRect.bottom = y + scaledDisplaceY - z + 1; - outRect.top = outRect.bottom - scaledHeight; - } + + // Scaling displaceX/Y, Width/Height + scaledDisplaceX = (celInfo->displaceX * scaleX) >> 7; + scaledDisplaceY = (celInfo->displaceY * scaleY) >> 7; + scaledWidth = (celInfo->width * scaleX) >> 7; + scaledHeight = (celInfo->height * scaleY) >> 7; + scaledWidth = CLIP(scaledWidth, 0, _screen->getWidth()); + scaledHeight = CLIP(scaledHeight, 0, _screen->getHeight()); + + outRect.left = x + scaledDisplaceX - (scaledWidth >> 1); + outRect.right = outRect.left + scaledWidth; + outRect.bottom = y + scaledDisplaceY - z + 1; + outRect.top = outRect.bottom - scaledHeight; } void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount) { @@ -660,14 +665,4 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, } } -uint16 GfxView::getCelCount(int16 loopNo) const { - if ((loopNo < 0) || (loopNo >= _loopCount)) - return 0; - return _loop[loopNo].celCount; -} - -Palette *GfxView::getPalette() { - return _embeddedPal ? &_viewPalette : NULL; -} - } // End of namespace Sci diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index dd25bde3f2..93239e7586 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -64,7 +64,6 @@ public: int16 getWidth(int16 loopNo, int16 celNo) const; int16 getHeight(int16 loopNo, int16 celNo) const; const CelInfo *getCelInfo(int16 loopNo, int16 celNo) const; - const LoopInfo *getLoopInfo(int16 loopNo) const; void getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const; void getCelScaledRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, int16 scaleX, int16 scaleY, Common::Rect &outRect) const; const byte *getBitmap(int16 loopNo, int16 celNo); -- cgit v1.2.3 From 7e0240ab14d29401877ff0c4d827be859e13ea58 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:20:51 +0000 Subject: SCI: Comment cleanup svn-id: r50423 --- engines/sci/graphics/cursor.cpp | 12 +++++++----- engines/sci/graphics/screen.cpp | 26 ++++++++++++++++++-------- engines/sci/graphics/screen.h | 34 ++++++++++++++++++++++------------ 3 files changed, 47 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index c5f4de9cf5..20472d14c4 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -205,7 +205,7 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu // See http://developer.apple.com/legacy/mac/library/documentation/mac/QuickDraw/QuickDraw-402.html // for more information. - // View 998 seems to be a fake resource used to call for for the Mac CURS resources + // View 998 seems to be a fake resource used to call for the Mac CURS resources. // For other resources, they're still in the views, so use them. if (viewNum != 998) { kernelSetView(viewNum, loopNum, celNum, hotspot); @@ -255,10 +255,12 @@ void GfxCursor::kernelSetMacCursor(GuiResourceId viewNum, int loopNum, int celNu } void GfxCursor::setPosition(Common::Point pos) { - // Don't set position, when cursor is not visible - // This fixes eco quest 1 (floppy) right at the start, which is setting mouse cursor to 0, 0 all the time during the - // intro. It's escapeable (now) by moving to the left or top, but it's getting on your nerves. - // This could theoretically break some things, although sierra normally sets position only when showing the cursor. + // Don't set position, when cursor is not visible. + // This fixes eco quest 1 (floppy) right at the start, which is setting + // mouse cursor to (0,0) all the time during the intro. It's escapeable + // (now) by moving to the left or top, but it's getting on your nerves. This + // could theoretically break some things, although sierra normally sets + // position only when showing the cursor. if (!_isVisible) return; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 519020f3a1..fa1f7019fd 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -106,8 +106,8 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _unditherState = true; if (_resMan->isVGA() || (_resMan->isAmiga32color())) { - // It's not 100% accurate to set white to be 255 for amiga 32-color games - // 255 is defined as white in our sci at all times, so it doesnt matter + // It is not 100% accurate to set white to be 255 for Amiga 32-color games. + // But 255 is defined as white in our SCI at all times, so it doesn't matter. _colorWhite = 255; if (getSciVersion() >= SCI_VERSION_1_1) _colorDefaultVectorData = 255; @@ -167,7 +167,10 @@ void GfxScreen::copyRectToScreen(const Common::Rect &rect) { } } -// This copies a rect to screen w/o scaling adjustment and is only meant to be used on hires graphics used in upscaled hires mode +/** + * This copies a rect to screen w/o scaling adjustment and is only meant to be + * used on hires graphics used in upscaled hires mode. + */ void GfxScreen::copyDisplayRectToScreen(const Common::Rect &rect) { if (!_upscaledHires) error("copyDisplayRectToScreen: not in upscaled hires mode"); @@ -218,15 +221,21 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, _controlScreen[offset] = control; } -// This will just change a pixel directly on displayscreen. Its supposed to get only used on upscaled-Hires games where -// hires content needs to get drawn ONTO the upscaled display screen (like japanese fonts, hires portraits, etc.) +/** + * This will just change a pixel directly on displayscreen. It is supposed to be + * only used on upscaled-Hires games where hires content needs to get drawn ONTO + * the upscaled display screen (like japanese fonts, hires portraits, etc.). + */ void GfxScreen::putPixelOnDisplay(int x, int y, byte color) { int offset = y * _displayWidth + x; _displayScreen[offset] = color; } -// Sierra's Bresenham line drawing -// WARNING: Do not just blindly replace this with Graphics::drawLine(), as it seems to create issues with flood fill +/** + * Sierra's Bresenham line drawing. + * WARNING: Do not replace this with Graphics::drawLine(), as this causes issues + * with flood fill, due to small difference in the Bresenham logic. + */ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte priority, byte control) { int16 left = startPoint.x; int16 top = startPoint.y; @@ -289,7 +298,8 @@ void GfxScreen::drawLine(Common::Point startPoint, Common::Point endPoint, byte } } -// We put hires kanji chars onto upscaled background, so we need to adjust coordinates. Caller gives use low-res ones +// We put hires kanji chars onto upscaled background, so we need to adjust +// coordinates. Caller gives use low-res ones. void GfxScreen::putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color) { byte *displayPtr = _displayScreen + y * _displayWidth * 2 + x * 2; // we don't use outline, so color 0 is actually not used diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index c1e10fabc8..03dfd3529c 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -55,9 +55,12 @@ enum { }; /** - * Screen class, actually creates 3 (4) screens internally - which is visual/display (for the user), - * priority (contains priority information) and control (contains control information). Handles all operations to it - * and copies parts of visual/display screen to the actual screen, so the user can really see it. + * Screen class, actually creates 3 (4) screens internally: + * - visual/display (for the user), + * - priority (contains priority information) and + * - control (contains control information). + * Handles all operations to it and copies parts of visual/display screen to + * the actual screen, so the user can really see it. */ class GfxScreen { public: @@ -85,10 +88,10 @@ public: void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) { drawLine(Common::Point(left, top), Common::Point(right, bottom), color, prio, control); } - int getUpscaledHires() { + int getUpscaledHires() const { return _upscaledHires; } - bool getUnditherState() { + bool getUnditherState() const { return _unditherState; } void putKanjiChar(Graphics::FontSJIS *commonFont, int16 x, int16 y, uint16 chr, byte color); @@ -140,27 +143,34 @@ private: bool _unditherState; int16 _unditherMemorial[SCI_SCREEN_UNDITHERMEMORIAL_SIZE]; - // these screens have the real resolution of the game engine (320x200 for SCI0/SCI1/SCI11 games, 640x480 for SCI2 games) - // SCI0 games will be dithered in here at any time + // These screens have the real resolution of the game engine (320x200 for + // SCI0/SCI1/SCI11 games, 640x480 for SCI2 games). SCI0 games will be + // dithered in here at any time. byte *_visualScreen; byte *_priorityScreen; byte *_controlScreen; - // this screen is the one that is actually displayed to the user. It may be 640x400 for japanese SCI1 games - // SCI0 games may be undithered in here. Only read from this buffer for Save/ShowBits usage. + // This screen is the one that is actually displayed to the user. It may be + // 640x400 for japanese SCI1 games. SCI0 games may be undithered in here. + // Only read from this buffer for Save/ShowBits usage. byte *_displayScreen; Common::Rect getScaledRect(Common::Rect rect); ResourceManager *_resMan; - // this is a pointer to the currently active screen (changing it only required for debug purposes) + /** + * Pointer to the currently active screen (changing it only required for + * debug purposes). + */ byte *_activeScreen; - // this variable defines, if upscaled hires is active and what upscaled mode is used + // This variable defines, if upscaled hires is active and what upscaled mode + // is used. int _upscaledHires; - // this here holds a translation for vertical coordinates between native (visual) and actual (display) screen + // This here holds a translation for vertical coordinates between native + // (visual) and actual (display) screen. int _upscaledMapping[SCI_SCREEN_UPSCALEDMAXHEIGHT + 1]; }; -- cgit v1.2.3 From 793d482f4fccd8999d71c9a0dbed518216cbb6ac Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:21:07 +0000 Subject: SCI: Optimized GfxScreen::scale2x a bit svn-id: r50424 --- engines/sci/graphics/screen.cpp | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index fa1f7019fd..a86f64c44f 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -594,18 +594,19 @@ void GfxScreen::debugShowMap(int mapNo) { } void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { - int newWidth = srcWidth * 2; + const int newWidth = srcWidth * 2; const byte *srcPtr = src; for (int y = 0; y < srcHeight; y++) { for (int x = 0; x < srcWidth; x++) { - int destOffset = y * 2 * newWidth + x * 2; - dst[destOffset] = *srcPtr; - dst[destOffset + 1] = *srcPtr; - dst[destOffset + newWidth] = *srcPtr; - dst[destOffset + newWidth + 1] = *srcPtr; - srcPtr++; + const byte color = *srcPtr++; + dst[0] = color; + dst[1] = color; + dst[newWidth] = color; + dst[newWidth + 1] = color; + dst += 2; } + dst += srcWidth; } } -- cgit v1.2.3 From 14530933919cfcfb86c0542ed2408b8e47675036 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:21:23 +0000 Subject: SCI: Cleanup GfxView code (formatting etc.); also insert some asserts to protect scalingX/Y arrays svn-id: r50425 --- engines/sci/graphics/view.cpp | 92 +++++++++++++++++++++++++------------------ 1 file changed, 53 insertions(+), 39 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index b255b18adc..71261490e4 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -460,7 +460,8 @@ const byte *GfxView::getBitmap(int16 loopNo, int16 celNo) { void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte clearKey) { int16 *unditherMemorial = _screen->unditherGetMemorial(); - // It makes no sense to go further, if no memorial data from current picture is available + // It makes no sense to go further, if no memorial data from current picture + // is available if (!unditherMemorial) return; @@ -480,7 +481,8 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl memset(&bitmapMemorial, 0, sizeof(bitmapMemorial)); - // Count all seemingly dithered pixel-combinations as soon as at least 4 pixels are adjacent + // Count all seemingly dithered pixel-combinations as soon as at least 4 + // pixels are adjacent curPtr = bitmapPtr; for (y = 0; y < height; y++) { color1 = curPtr[0]; color2 = (curPtr[1] << 4) | curPtr[2]; @@ -493,13 +495,15 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl } } - // Now compare both memorial tables to find out matching dithering-combinations + // Now compare both memorial tables to find out matching + // dithering-combinations bool unditherTable[SCI_SCREEN_UNDITHERMEMORIAL_SIZE]; byte color, unditherCount = 0; memset(&unditherTable, false, sizeof(unditherTable)); for (color = 0; color < 255; color++) { if ((bitmapMemorial[color] > 5) && (unditherMemorial[color] > 200)) { - // match found, check if colorKey is contained -> if so, we ignore of course + // match found, check if colorKey is contained -> if so, we ignore + // of course color1 = color & 0x0F; color2 = color >> 4; if ((color1 != clearKey) && (color2 != clearKey) && (color1 != color2)) { // so set this and the reversed color-combination for undithering @@ -533,15 +537,15 @@ void GfxView::unditherBitmap(byte *bitmapPtr, int16 width, int16 height, byte cl } } -void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { - Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; +void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, + int16 loopNo, int16 celNo, byte priority, uint16 EGAmappingNr, bool upscaledHires) { + const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; const CelInfo *celInfo = getCelInfo(loopNo, celNo); const byte *bitmap = getBitmap(loopNo, celNo); - int16 celHeight = celInfo->height, celWidth = celInfo->width; - int16 width, height; - byte clearKey = celInfo->clearKey; - byte color; - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; + const int16 celHeight = celInfo->height; + const int16 celWidth = celInfo->width; + const byte clearKey = celInfo->clearKey; + const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; int x, y; if (_embeddedPal) { @@ -549,24 +553,27 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const _palette->set(&_viewPalette, false); } - width = MIN(clipRect.width(), celWidth); - height = MIN(clipRect.height(), celHeight); + const int16 width = MIN(clipRect.width(), celWidth); + const int16 height = MIN(clipRect.height(), celHeight); bitmap += (clipRect.top - rect.top) * celWidth + (clipRect.left - rect.left); if (!_EGAmapping) { for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { - color = bitmap[x]; + const byte color = bitmap[x]; if (color != clearKey) { + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; if (!upscaledHires) { - if (priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0); + if (priority >= _screen->getPriority(x2, y2)) + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } else { - // UpscaledHires means view is hires and is supposed to get drawn onto lowres screen - // FIXME(?): we can't read priority directly with the hires coordinates. may not be needed at all - // in kq6 - _screen->putPixelOnDisplay(clipRectTranslated.left + x, clipRectTranslated.top + y, palette->mapping[color]); + // UpscaledHires means view is hires and is supposed to + // get drawn onto lowres screen. + // FIXME(?): we can't read priority directly with the + // hires coordinates. may not be needed at all in kq6 + _screen->putPixelOnDisplay(x2, y2, palette->mapping[color]); } } } @@ -575,9 +582,11 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const byte *EGAmapping = _EGAmapping + (EGAmappingNr * SCI_VIEW_EGAMAPPING_SIZE); for (y = 0; y < height; y++, bitmap += celWidth) { for (x = 0; x < width; x++) { - color = EGAmapping[bitmap[x]]; - if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, color, priority, 0); + const byte color = EGAmapping[bitmap[x]]; + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; + if (color != clearKey && priority >= _screen->getPriority(x2, y2)) + _screen->putPixel(x2, y2, drawMask, color, priority, 0); } } } @@ -588,20 +597,19 @@ void GfxView::draw(const Common::Rect &rect, const Common::Rect &clipRect, const * is definitely not pixel-perfect with the one sierra is using. It shouldn't * matter because the scaled cel rect is definitely the same as in sierra sci. */ -void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { - Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; +void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, const Common::Rect &clipRectTranslated, + int16 loopNo, int16 celNo, byte priority, int16 scaleX, int16 scaleY) { + const Palette *palette = _embeddedPal ? &_viewPalette : &_palette->_sysPalette; const CelInfo *celInfo = getCelInfo(loopNo, celNo); const byte *bitmap = getBitmap(loopNo, celNo); - int16 celHeight = celInfo->height, celWidth = celInfo->width; - byte clearKey = celInfo->clearKey; - byte color; - byte drawMask = priority == 255 ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; - int x, y; + const int16 celHeight = celInfo->height; + const int16 celWidth = celInfo->width; + const byte clearKey = celInfo->clearKey; + const byte drawMask = (priority == 255) ? GFX_SCREEN_MASK_VISUAL : GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY; uint16 scalingX[640]; uint16 scalingY[480]; int16 scaledWidth, scaledHeight; int16 pixelNo, scaledPixel, scaledPixelNo, prevScaledPixelNo; - uint16 offsetX, offsetY; if (_embeddedPal) { // Merge view palette in... @@ -622,6 +630,7 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, scaledPixel = scaledPixelNo = prevScaledPixelNo = 0; while (pixelNo < celHeight) { scaledPixelNo = scaledPixel >> 7; + assert(scaledPixelNo < ARRAYSIZE(scalingY)); if (prevScaledPixelNo < scaledPixelNo) memset(&scalingY[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo); scalingY[scaledPixelNo] = pixelNo; @@ -638,6 +647,7 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, scaledPixel = scaledPixelNo = prevScaledPixelNo = 0; while (pixelNo < celWidth) { scaledPixelNo = scaledPixel >> 7; + assert(scaledPixelNo < ARRAYSIZE(scalingX)); if (prevScaledPixelNo < scaledPixelNo) memset(&scalingX[prevScaledPixelNo], pixelNo, scaledPixelNo - prevScaledPixelNo); scalingX[scaledPixelNo] = pixelNo; @@ -652,14 +662,18 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, scaledWidth = MIN(clipRect.width(), scaledWidth); scaledHeight = MIN(clipRect.height(), scaledHeight); - offsetY = clipRect.top - rect.top; - offsetX = clipRect.left - rect.left; - - for (y = 0; y < scaledHeight; y++) { - for (x = 0; x < scaledWidth; x++) { - color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]]; - if (color != clearKey && priority >= _screen->getPriority(clipRectTranslated.left + x, clipRectTranslated.top + y)) { - _screen->putPixel(clipRectTranslated.left + x, clipRectTranslated.top + y, drawMask, palette->mapping[color], priority, 0); + const uint16 offsetY = clipRect.top - rect.top; + const uint16 offsetX = clipRect.left - rect.left; + + assert(scaledHeight + offsetY <= ARRAYSIZE(scalingY)); + assert(scaledWidth + offsetX <= ARRAYSIZE(scalingX)); + for (int y = 0; y < scaledHeight; y++) { + for (int x = 0; x < scaledWidth; x++) { + const byte color = bitmap[scalingY[y + offsetY] * celWidth + scalingX[x + offsetX]]; + const int x2 = clipRectTranslated.left + x; + const int y2 = clipRectTranslated.top + y; + if (color != clearKey && priority >= _screen->getPriority(x2, y2)) { + _screen->putPixel(x2, y2, drawMask, palette->mapping[color], priority, 0); } } } -- cgit v1.2.3 From 12099176f712c65b9822a5874f705d63d82228ce Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:21:39 +0000 Subject: SCI: More formatting cleanup svn-id: r50426 --- engines/sci/engine/script.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 2bb405372a..b6bcbb7646 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -275,10 +275,10 @@ void Script::relocate(reg_t block) { for (int i = 0; i < count; i++) { pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; - // This occurs in SCI01/SCI1 games where usually one export value - // is zero. It seems that in this situation, we should skip the - // export and move to the next one, though the total count of valid - // exports remains the same + // This occurs in SCI01/SCI1 games where usually one export value is + // zero. It seems that in this situation, we should skip the export and + // move to the next one, though the total count of valid exports remains + // the same if (!pos) { exportIndex++; pos = READ_SCI11ENDIAN_UINT16(heap + block.offset + 2 + (exportIndex * 2)) + heapOffset; @@ -286,9 +286,10 @@ void Script::relocate(reg_t block) { error("Script::relocate(): Consecutive zero exports found"); } - // In SCI0-SCI1, script local variables, objects and code are relocated. We only relocate - // locals and objects here, and ignore relocation of code blocks. In SCI1.1 and newer - // versions, only locals and objects are relocated. + // In SCI0-SCI1, script local variables, objects and code are relocated. + // We only relocate locals and objects here, and ignore relocation of + // code blocks. In SCI1.1 and newer versions, only locals and objects + // are relocated. if (!relocateLocal(block.segment, pos)) { // Not a local? It's probably an object or code block. If it's an object, relocate it. const ObjMap::iterator end = _objects.end(); @@ -497,10 +498,10 @@ void Script::initialiseObjectsSci11(SegManager *segMan) { obj->setSuperClassSelector( segMan->getClassAddress(obj->getSuperClassSelector().offset, SCRIPT_GET_LOCK, NULL_REG)); - // If object is instance, get -propDict- from class and set it for this object - // This is needed for ::isMemberOf() to work. - // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, talk-clicks on the robot will act like - // clicking on ego + // If object is instance, get -propDict- from class and set it for this + // object. This is needed for ::isMemberOf() to work. + // Example testcase - room 381 of sq4cd - if isMemberOf() doesn't work, + // talk-clicks on the robot will act like clicking on ego if (!obj->isClass()) { reg_t classObject = obj->getSuperClassSelector(); Object *classObj = segMan->getObject(classObject); -- cgit v1.2.3 From 85038e7d6c272555c54d9f4b87665392bfa96aaf Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:21:55 +0000 Subject: SCI: Change warning back to error in Script::initialiseObjectsSci0 Instead of turning the error into a warning globally, we now have code which ignores the error in Script 202 of KQ5 French, but will keep reporting if it turns up in other places. svn-id: r50427 --- engines/sci/engine/script.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index b6bcbb7646..f9584a2897 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -471,8 +471,11 @@ void Script::initialiseObjectsSci0(SegManager *segMan) { obj->initSpecies(segMan, addr); if (!obj->initBaseObject(segMan, addr)) { - // Script 202 of KQ5 French has an invalid object. This is non-fatal. - warning("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + if (_nr == 202 && g_sci->getGameId() == GID_KQ5 && g_sci->getSciLanguage() == K_LANG_FRENCH) { + // Script 202 of KQ5 French has an invalid object. This is non-fatal. + } else { + error("Failed to locate base object for object at %04X:%04X; skipping", PRINT_REG(addr)); + } scriptObjRemove(addr); } } -- cgit v1.2.3 From 30218a2c324bc67f724100051ab9884a351928fb Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:22:20 +0000 Subject: SCI: Make Script member vars private; add const qualifiers Only three Script members remain public (for now) svn-id: r50428 --- engines/sci/console.cpp | 10 +++---- engines/sci/engine/features.cpp | 10 +++---- engines/sci/engine/kernel.cpp | 2 +- engines/sci/engine/savegame.cpp | 4 +-- engines/sci/engine/script.cpp | 33 ++++++++++++----------- engines/sci/engine/script.h | 54 ++++++++++++++++++++------------------ engines/sci/engine/scriptdebug.cpp | 6 ++--- engines/sci/engine/seg_manager.cpp | 24 +++++++---------- engines/sci/engine/vm.cpp | 6 ++--- engines/sci/engine/vm.h | 2 +- 10 files changed, 76 insertions(+), 75 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 611d1481ad..f682e0e524 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1381,7 +1381,7 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { switch (mobj->getType()) { case SEG_TYPE_SCRIPT: - DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj)._nr, (*(Script *)mobj).getLockers()); + DebugPrintf("S script.%03d l:%d ", (*(Script *)mobj).getScriptNumber(), (*(Script *)mobj).getLockers()); break; case SEG_TYPE_CLONES: @@ -1455,9 +1455,9 @@ bool Console::segmentInfo(int nr) { case SEG_TYPE_SCRIPT: { Script *scr = (Script *)mobj; - DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->_nr, scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); + DebugPrintf("script.%03d locked by %d, bufsize=%d (%x)\n", scr->getScriptNumber(), scr->getLockers(), (uint)scr->getBufSize(), (uint)scr->getBufSize()); if (scr->getExportTable()) - DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->_buf))); + DebugPrintf(" Exports: %4d at %d\n", scr->getExportsNr(), (int)(((const byte *)scr->getExportTable()) - ((const byte *)scr->getBuf()))); else DebugPrintf(" Exports: none\n"); @@ -2377,7 +2377,7 @@ bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" script: %d", (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment])._nr); + DebugPrintf(" script: %d", (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber()); DebugPrintf("\n"); } @@ -3351,7 +3351,7 @@ int Console::printObject(reg_t pos) { DebugPrintf(" [%03x] %s = %04x:%04x\n", obj->getFuncSelector(i), _engine->getKernel()->getSelectorName(obj->getFuncSelector(i)).c_str(), PRINT_REG(fptr)); } if (s->_segMan->_heap[pos.segment]->getType() == SEG_TYPE_SCRIPT) - DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->_nr); + DebugPrintf("\nOwner script: %d\n", s->_segMan->getScript(pos.segment)->getScriptNumber()); return 0; } diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 75f271f3ad..2ad494b37f 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -84,7 +84,7 @@ bool GameFeatures::autoDetectSoundType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -220,7 +220,7 @@ bool GameFeatures::autoDetectLofsType(int methodNum) { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -306,7 +306,7 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -409,7 +409,7 @@ bool GameFeatures::autoDetectSci21KernelType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script @@ -462,7 +462,7 @@ bool GameFeatures::autoDetectMoveCountType() { int16 opparams[4]; byte extOpcode; byte opcode; - offset += readPMachineInstruction(script->_buf + offset, extOpcode, opparams); + offset += readPMachineInstruction(script->getBuf(offset), extOpcode, opparams); opcode = extOpcode >> 1; // Check for end of script diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d6dcf650bc..9bf0371a7a 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -644,7 +644,7 @@ int Kernel::findRegType(reg_t reg) { case SEG_TYPE_SCRIPT: if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && - RAW_IS_OBJECT((*(Script *)mobj)._buf + reg.offset)) { + RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { return ((Script *)mobj)->getObject(reg.offset) ? KSIG_OBJECT : KSIG_REF; } else return KSIG_REF; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index f6a6afd196..c0ed515981 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -278,7 +278,7 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { // If we are loading a script, hook it up in the script->segment map. if (s.isLoading() && type == SEG_TYPE_SCRIPT) { - _scriptSegMap[((Script *)mobj)->_nr] = i; + _scriptSegMap[((Script *)mobj)->getScriptNumber()] = i; } } @@ -765,7 +765,7 @@ void SegManager::reconstructScripts(EngineState *s) { scr->_localsBlock = (scr->_localsSegment == 0) ? NULL : (LocalVariables *)(_heap[scr->_localsSegment]); for (ObjMap::iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) - it->_value._baseObj = scr->_buf + it->_value.getPos().offset; + it->_value._baseObj = scr->getBuf(it->_value.getPos().offset); } for (i = 0; i < _heap.size(); i++) { diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index f9584a2897..ac6fb6f26d 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -88,14 +88,13 @@ void Script::init(int script_nr, ResourceManager *resMan) { if (getSciVersion() == SCI_VERSION_0_EARLY) { _bufSize += READ_LE_UINT16(script->data) * 2; } else if (getSciVersion() >= SCI_VERSION_1_1) { - /** - * In SCI11, the heap was in a separate space from the script. - * We append it to the end of the script, and adjust addressing accordingly. - * However, since we address the heap with a 16-bit pointer, the combined - * size of the stack and the heap must be 64KB. So far this has worked - * for SCI11, SCI2 and SCI21 games. SCI3 games use a different script format, - * and theoretically they can exceed the 64KB boundary using relocation. - */ + // In SCI11, the heap was in a separate space from the script. We append + // it to the end of the script, and adjust addressing accordingly. + // However, since we address the heap with a 16-bit pointer, the + // combined size of the stack and the heap must be 64KB. So far this has + // worked for SCI11, SCI2 and SCI21 games. SCI3 games use a different + // script format, and theoretically they can exceed the 64KB boundary + // using relocation. Resource *heap = resMan->findResource(ResourceId(kResourceTypeHeap, script_nr), 0); _bufSize += heap->size; _heapSize = heap->size; @@ -109,8 +108,8 @@ void Script::init(int script_nr, ResourceManager *resMan) { // As mentioned above, the script and the heap together should not exceed 64KB if (script->size + heap->size > 65535) error("Script and heap sizes combined exceed 64K. This means a fundamental " - "design bug was made regarding SCI1.1 and newer games.\nPlease " - "report this error to the ScummVM team"); + "design bug was made regarding SCI1.1 and newer games.\n" + "Please report this error to the ScummVM team"); } } @@ -256,7 +255,7 @@ bool Script::relocateLocal(SegmentId segment, int location) { } void Script::relocate(reg_t block) { - byte *heap = _buf; + const byte *heap = _buf; uint16 heapSize = (uint16)_bufSize; uint16 heapOffset = 0; @@ -452,10 +451,9 @@ void Script::initialiseClasses(SegManager *segMan) { } } -void Script::initialiseObjectsSci0(SegManager *segMan) { +void Script::initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId) { bool oldScriptHeader = (getSciVersion() == SCI_VERSION_0_EARLY); const byte *seeker = _buf + (oldScriptHeader ? 2 : 0); - SegmentId segmentId = segMan->getScriptSegment(_nr); do { uint16 objType = READ_SCI11ENDIAN_UINT16(seeker); @@ -487,11 +485,14 @@ void Script::initialiseObjectsSci0(SegManager *segMan) { seeker += READ_SCI11ENDIAN_UINT16(seeker + 2); } while ((uint32)(seeker - _buf) < getScriptSize() - 2); + + byte *relocationBlock = findBlock(SCI_OBJ_POINTERS); + if (relocationBlock) + relocate(make_reg(segmentId, relocationBlock - getBuf() + 4)); } -void Script::initialiseObjectsSci11(SegManager *segMan) { +void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) { const byte *seeker = _heapStart + 4 + READ_SCI11ENDIAN_UINT16(_heapStart + 2) * 2; - SegmentId segmentId = segMan->getScriptSegment(_nr); while (READ_SCI11ENDIAN_UINT16(seeker) == SCRIPT_OBJECT_MAGIC_NUMBER) { reg_t reg = make_reg(segmentId, seeker - _buf); @@ -521,6 +522,8 @@ void Script::initialiseObjectsSci11(SegManager *segMan) { seeker += READ_SCI11ENDIAN_UINT16(seeker + 2) * 2; } + + relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart))); } } // End of namespace Sci diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 296570c218..aab073f3a1 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -51,19 +51,12 @@ enum ScriptObjectTypes { typedef Common::HashMap ObjMap; class Script : public SegmentObj { -public: +private: int _nr; /**< Script number */ byte *_buf; /**< Static data buffer, or NULL if not used */ byte *_heapStart; /**< Start of heap if SCI1.1, NULL otherwise */ - uint32 getScriptSize() { return _scriptSize; } - uint32 getHeapSize() { return _heapSize; } - uint32 getBufSize() { return _bufSize; } - -protected: int _lockers; /**< Number of classes and objects that require this script */ - -private: size_t _scriptSize; size_t _heapSize; uint16 _bufSize; @@ -77,19 +70,27 @@ private: int _localsOffset; uint16 _localsCount; + bool _markedAsDeleted; + public: /** * Table for objects, contains property variables. * Indexed by the TODO offset. */ ObjMap _objects; + SegmentId _localsSegment; /**< The local variable segment */ + LocalVariables *_localsBlock; +public: int getLocalsOffset() const { return _localsOffset; } uint16 getLocalsCount() const { return _localsCount; } - SegmentId _localsSegment; /**< The local variable segment */ - LocalVariables *_localsBlock; - bool _markedAsDeleted; + uint32 getScriptSize() const { return _scriptSize; } + uint32 getHeapSize() const { return _heapSize; } + uint32 getBufSize() const { return _bufSize; } + const byte *getBuf(uint offset = 0) const { return _buf + offset; } + + int getScriptNumber() const { return _nr; } public: Script(); @@ -129,15 +130,6 @@ public: */ void scriptObjRemove(reg_t obj_pos); - /** - * Processes a relocation block witin a script - * This function is idempotent, but it must only be called after all - * objects have been instantiated, or a run-time error will occur. - * @param obj_pos Location (segment, offset) of the block - * @return Location of the relocation block - */ - void relocate(reg_t block); - /** * Initializes the script's local variables * @param segMan A reference to the segment manager @@ -153,19 +145,17 @@ public: /** * Initializes the script's objects (SCI0) * @param segMan A reference to the segment manager + * @param segmentId The script's segment id */ - void initialiseObjectsSci0(SegManager *segMan); + void initialiseObjectsSci0(SegManager *segMan, SegmentId segmentId); /** * Initializes the script's objects (SCI1.1+) * @param segMan A reference to the segment manager + * @param segmentId The script's segment id */ - void initialiseObjectsSci11(SegManager *segMan); - -private: - bool relocateLocal(SegmentId segment, int location); + void initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId); -public: // script lock operations /** Increments the number of lockers of this script by one. */ @@ -246,6 +236,18 @@ public: * Finds the pointer where a block of a specific type starts from */ byte *findBlock(int type); + +private: + /** + * Processes a relocation block witin a script + * This function is idempotent, but it must only be called after all + * objects have been instantiated, or a run-time error will occur. + * @param obj_pos Location (segment, offset) of the block + * @return Location of the relocation block + */ + void relocate(reg_t block); + + bool relocateLocal(SegmentId segment, int location); }; } // End of namespace Sci diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index d730856332..4813e083fd 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -69,7 +69,7 @@ DebugState g_debugState; // FIXME: Avoid non-const global vars reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) { SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); Script *script_entity = NULL; - byte *scr; + const byte *scr; int scr_size; reg_t retval = make_reg(pos.segment, pos.offset + 1); uint16 param_value; @@ -82,7 +82,7 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } else script_entity = (Script *)mobj; - scr = script_entity->_buf; + scr = script_entity->getBuf(); scr_size = script_entity->getBufSize(); if (pos.offset >= scr_size) { @@ -291,7 +291,7 @@ void script_debug(EngineState *s) { if (mobj) { Script *scr = (Script *)mobj; - byte *code_buf = scr->_buf; + const byte *code_buf = scr->getBuf(); int code_buf_size = scr->getBufSize(); int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset]; int op = opcode >> 1; diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index b56a539c63..56591c4726 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -157,7 +157,7 @@ int SegManager::deallocate(SegmentId seg, bool recursive) { if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; - _scriptSegMap.erase(scr->_nr); + _scriptSegMap.erase(scr->getScriptNumber()); if (recursive && scr->_localsSegment) deallocate(scr->_localsSegment, recursive); } @@ -173,7 +173,7 @@ bool SegManager::isHeapObject(reg_t pos) { if (obj == NULL || (obj && obj->isFreed())) return false; Script *scr = getScriptIfLoaded(pos.segment); - return !(scr && scr->_markedAsDeleted); + return !(scr && scr->isMarkedAsDeleted()); } void SegManager::deallocateScript(int script_nr) { @@ -237,7 +237,7 @@ Object *SegManager::getObject(reg_t pos) { } else if (mobj->getType() == SEG_TYPE_SCRIPT) { Script *scr = (Script *)mobj; if (pos.offset <= scr->getBufSize() && pos.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET - && RAW_IS_OBJECT(scr->_buf + pos.offset)) { + && RAW_IS_OBJECT(scr->getBuf(pos.offset))) { obj = scr->getObject(pos.offset); } } @@ -384,12 +384,12 @@ LocalVariables *SegManager::allocLocalsSegment(Script *scr) { locals = (LocalVariables *)_heap[scr->_localsSegment]; VERIFY(locals != NULL, "Re-used locals segment was NULL'd out"); VERIFY(locals->getType() == SEG_TYPE_LOCALS, "Re-used locals segment did not consist of local variables"); - VERIFY(locals->script_id == scr->_nr, "Re-used locals segment belonged to other script"); + VERIFY(locals->script_id == scr->getScriptNumber(), "Re-used locals segment belonged to other script"); } else locals = (LocalVariables *)allocSegment(new LocalVariables(), &scr->_localsSegment); scr->_localsBlock = locals; - locals->script_id = scr->_nr; + locals->script_id = scr->getScriptNumber(); locals->_locals.resize(scr->getLocalsCount()); return locals; @@ -1012,13 +1012,9 @@ int SegManager::instantiateScript(int scriptNum) { scr->initialiseClasses(this); if (getSciVersion() >= SCI_VERSION_1_1) { - scr->initialiseObjectsSci11(this); - scr->relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(scr->_heapStart))); + scr->initialiseObjectsSci11(this, segmentId); } else { - scr->initialiseObjectsSci0(this); - byte *relocationBlock = scr->findBlock(SCI_OBJ_POINTERS); - if (relocationBlock) - scr->relocate(make_reg(segmentId, relocationBlock - scr->_buf + 4)); + scr->initialiseObjectsSci0(this, segmentId); } return segmentId; @@ -1067,16 +1063,16 @@ void SegManager::uninstantiateScriptSci0(int script_nr) { do { reg.offset += objLength; // Step over the last checked object - objType = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset); + objType = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset)); if (!objType) break; - objLength = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); + objLength = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); reg.offset += 4; // Step over header if ((objType == SCI_OBJ_OBJECT) || (objType == SCI_OBJ_CLASS)) { // object or class? reg.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) - int16 superclass = READ_SCI11ENDIAN_UINT16(scr->_buf + reg.offset + 2); + int16 superclass = READ_SCI11ENDIAN_UINT16(scr->getBuf(reg.offset + 2)); if (superclass >= 0) { int superclass_script = getClass(superclass).script; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 555576f579..686603ae21 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -299,7 +299,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i EngineState *state = g_sci->getEngineState(); ExecStack *lastCall = state->xs; Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); - int curScriptNr = local_script->_nr; + int curScriptNr = local_script->getScriptNumber(); if (lastCall->localCallOffset != -1) { // if lastcall was actually a local call search back for a real call @@ -943,7 +943,7 @@ void run_vm(EngineState *s, bool restoring) { s->_executionStackPosChanged = false; obj = s->_segMan->getObject(s->xs->objp); - code_buf = scr->_buf; + code_buf = scr->getBuf(); code_buf_size = scr->getBufSize(); local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); if (!local_script) { @@ -1287,7 +1287,7 @@ void run_vm(EngineState *s, bool restoring) { // for (int i = 0; i < opparams[0]; i++) // s->xs->sp[i] = make_reg(0, 'ss'); - //if (local_script->_nr == 140 && isIslandOfDrBrain) { + //if (local_script->getScriptNumber() == 140 && isIslandOfDrBrain) { // // WORKAROUND for The Island of Dr. Brain, room 140. // // Script 140 runs in an endless loop if we set its // // variables to 0 here. diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index ed4cc4a456..49169a456c 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -64,7 +64,7 @@ struct Class { reg_t reg; ///< offset; script-relative offset, segment: 0 if not instantiated }; -#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) +#define RAW_IS_OBJECT(datablock) (READ_SCI11ENDIAN_UINT16(((const byte *) datablock) + SCRIPT_OBJECT_MAGIC_OFFSET) == SCRIPT_OBJECT_MAGIC_NUMBER) // A reference to an object's variable. // The object is stored as a reg_t, the variable as an index into _variables -- cgit v1.2.3 From 31b29027144e3a76ab6e8c71a0014ca6121218c0 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:22:41 +0000 Subject: SCI: Revise GC interface: use Common::Array instead of callbacks This means a little bit more overhead but makes the code much more readable and understandable. svn-id: r50429 --- engines/sci/console.cpp | 15 +++---- engines/sci/engine/gc.cpp | 35 ++++++++--------- engines/sci/engine/script.h | 6 ++- engines/sci/engine/segment.cpp | 89 +++++++++++++++++++++++++++++------------- engines/sci/engine/segment.h | 35 +++++++++-------- 5 files changed, 109 insertions(+), 71 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f682e0e524..8ea7daa7c6 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1847,11 +1847,6 @@ bool Console::cmdGCObjects(int argc, const char **argv) { return true; } -void _print_address(void * _, reg_t addr) { - if (addr.segment) - g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(addr)); -} - bool Console::cmdGCShowReachable(int argc, const char **argv) { if (argc != 2) { DebugPrintf("Prints all addresses directly reachable from the memory object specified as parameter.\n"); @@ -1875,7 +1870,10 @@ bool Console::cmdGCShowReachable(int argc, const char **argv) { } DebugPrintf("Reachable from %04x:%04x:\n", PRINT_REG(addr)); - mobj->listAllOutgoingReferences(addr, NULL, _print_address); + const Common::Array tmp = mobj->listAllOutgoingReferences(addr); + for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + if (it->segment) + g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } @@ -1904,7 +1902,10 @@ bool Console::cmdGCShowFreeable(int argc, const char **argv) { } DebugPrintf("Freeable in segment %04x:\n", addr.segment); - mobj->listAllDeallocatable(addr.segment, NULL, _print_address); + const Common::Array tmp = mobj->listAllDeallocatable(addr.segment); + for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + if (it->segment) + g_sci->getSciDebugger()->DebugPrintf(" %04x:%04x\n", PRINT_REG(*it)); return true; } diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index c2f1c15776..59f62c8996 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -46,6 +46,11 @@ struct WorklistManager { _map.setVal(reg, true); _worklist.push_back(reg); } + + void push(const Common::Array &tmp) { + for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + push(*it); + } }; static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map &nonnormal_map) { @@ -65,11 +70,6 @@ static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map } -void add_outgoing_refs(void *refcon, reg_t addr) { - WorklistManager *wm = (WorklistManager *)refcon; - wm->push(addr); -} - reg_t_hash_map *find_all_used_references(EngineState *s) { SegManager *segMan = s->_segMan; reg_t_hash_map *normal_map = NULL; @@ -125,15 +125,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { Script *script = (Script *)segMan->_heap[i]; if (script->getLockers()) { // Explicitly loaded? - // Locals, if present - wm.push(make_reg(script->_localsSegment, 0)); - - // All objects (may be classes, may be indirectly reachable) - ObjMap::iterator it; - const ObjMap::iterator end = script->_objects.end(); - for (it = script->_objects.begin(); it != end; ++it) { - wm.push(it->_value.getPos()); - } + wm.push(script->listObjectReferences()); } } @@ -146,8 +138,10 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm._worklist.pop_back(); if (reg.segment != stack_seg) { // No need to repeat this one debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); - if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment]) - segMan->_heap[reg.segment]->listAllOutgoingReferences(reg, &wm, add_outgoing_refs); + if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment]) { + // Valid heap object? Find its outgoing references! + wm.push(segMan->_heap[reg.segment]->listAllOutgoingReferences(reg)); + } } } @@ -167,8 +161,7 @@ struct deallocator_t { reg_t_hash_map *use_map; }; -void free_unless_used(void *refcon, reg_t addr) { - deallocator_t *deallocator = (deallocator_t *)refcon; +static void free_unless_used(deallocator_t *deallocator, reg_t addr) { reg_t_hash_map *use_map = deallocator->use_map; if (!use_map->contains(addr)) { @@ -201,7 +194,11 @@ void run_gc(EngineState *s) { #ifdef DEBUG_GC deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name" #endif - deallocator.mobj->listAllDeallocatable(seg_nr, &deallocator, free_unless_used); + const Common::Array tmp = deallocator.mobj->listAllDeallocatable(seg_nr); + for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { + free_unless_used(&deallocator, *it); + } + } } diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index aab073f3a1..490a7a81a3 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -104,8 +104,10 @@ public: virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllDeallocatable(SegmentId segId) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; + + Common::Array listObjectReferences() const; virtual void saveLoadWithSerializer(Common::Serializer &ser); diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 2bbedf2dcf..f8a941fa7a 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -218,20 +218,22 @@ void Script::freeAtAddress(SegManager *segMan, reg_t addr) { segMan->deallocateScript(_nr); } -void Script::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { - (*note)(param, make_reg(segId, 0)); +Common::Array Script::listAllDeallocatable(SegmentId segId) const { + const reg_t r = make_reg(segId, 0); + return Common::Array(&r, 1); } -void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array Script::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { const Object *obj = getObject(addr.offset); if (obj) { // Note all local variables, if we have a local variable environment if (_localsSegment) - (*note)(param, make_reg(_localsSegment, 0)); + tmp.push_back(make_reg(_localsSegment, 0)); for (uint i = 0; i < obj->getVarCount(); i++) - (*note)(param, obj->getVariable(i)); + tmp.push_back(obj->getVariable(i)); } else { error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); } @@ -239,12 +241,30 @@ void Script::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback not /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ /* Happens e.g. when we're looking into strings */ } + return tmp; } +Common::Array Script::listObjectReferences() const { + Common::Array tmp; + + // Locals, if present + if (_localsSegment) + tmp.push_back(make_reg(_localsSegment, 0)); + + // All objects (may be classes, may be indirectly reachable) + ObjMap::iterator it; + const ObjMap::iterator end = _objects.end(); + for (it = _objects.begin(); it != end; ++it) { + tmp.push_back(it->_value.getPos()); + } + + return tmp; +} //-------------------- clones -------------------- -void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array CloneTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; // assert(addr.segment == _segId); if (!isValidEntry(addr.offset)) { @@ -255,11 +275,13 @@ void CloneTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback // Emit all member variables (including references to the 'super' delegate) for (uint i = 0; i < clone->getVarCount(); i++) - (*note)(param, clone->getVariable(i)); + tmp.push_back(clone->getVariable(i)); // Note that this also includes the 'base' object, which is part of the script and therefore also emits the locals. - (*note)(param, clone->getPos()); + tmp.push_back(clone->getPos()); //debugC(2, kDebugLevelGC, "[GC] Reporting clone-pos %04x:%04x", PRINT_REG(clone->pos)); + + return tmp; } void CloneTable::freeAtAddress(SegManager *segMan, reg_t addr) { @@ -293,11 +315,14 @@ reg_t LocalVariables::findCanonicAddress(SegManager *segMan, reg_t addr) const { return make_reg(owner_seg, 0); } -void LocalVariables::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array LocalVariables::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; // assert(addr.segment == _segId); for (uint i = 0; i < _locals.size(); i++) - (*note)(param, _locals[i]); + tmp.push_back(_locals[i]); + + return tmp; } @@ -307,11 +332,14 @@ reg_t DataStack::findCanonicAddress(SegManager *segMan, reg_t addr) const { return addr; } -void DataStack::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array DataStack::listAllOutgoingReferences(reg_t object) const { + Common::Array tmp; fprintf(stderr, "Emitting %d stack entries\n", _capacity); for (int i = 0; i < _capacity; i++) - (*note)(param, _entries[i]); + tmp.push_back(_entries[i]); fprintf(stderr, "DONE"); + + return tmp; } @@ -320,18 +348,20 @@ void ListTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ListTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array ListTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; if (!isValidEntry(addr.offset)) { error("Invalid list referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; } const List *list = &(_table[addr.offset]); - note(param, list->first); - note(param, list->last); + tmp.push_back(list->first); + tmp.push_back(list->last); // We could probably get away with just one of them, but // let's be conservative here. + + return tmp; } @@ -340,19 +370,21 @@ void NodeTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void NodeTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array NodeTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; if (!isValidEntry(addr.offset)) { error("Invalid node referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; } const Node *node = &(_table[addr.offset]); // We need all four here. Can't just stick with 'pred' OR 'succ' because node operations allow us // to walk around from any given node - note(param, node->pred); - note(param, node->succ); - note(param, node->key); - note(param, node->value); + tmp.push_back(node->pred); + tmp.push_back(node->succ); + tmp.push_back(node->key); + tmp.push_back(node->value); + + return tmp; } @@ -473,8 +505,9 @@ reg_t DynMem::findCanonicAddress(SegManager *segMan, reg_t addr) const { return addr; } -void DynMem::listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { - (*note)(param, make_reg(segId, 0)); +Common::Array DynMem::listAllDeallocatable(SegmentId segId) const { + const reg_t r = make_reg(segId, 0); + return Common::Array(&r, 1); } #ifdef ENABLE_SCI32 @@ -492,10 +525,10 @@ void ArrayTable::freeAtAddress(SegManager *segMan, reg_t sub_addr) { freeEntry(sub_addr.offset); } -void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback note) const { +Common::Array ArrayTable::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; if (!isValidEntry(addr.offset)) { error("Invalid array referenced for outgoing references: %04x:%04x", PRINT_REG(addr)); - return; } const SciArray *array = &(_table[addr.offset]); @@ -503,8 +536,10 @@ void ArrayTable::listAllOutgoingReferences(reg_t addr, void *param, NoteCallback for (uint32 i = 0; i < array->getSize(); i++) { reg_t value = array->getValue(i); if (value.segment != 0) - note(param, value); + tmp.push_back(value); } + + return tmp; } Common::String SciString::toString() const { diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index b621e53412..c12efecf1c 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -80,8 +80,6 @@ enum SegmentType { struct SegmentObj : public Common::Serializable { SegmentType _type; - typedef void (*NoteCallback)(void *param, reg_t addr); // FIXME: Bad choice of name - public: static SegmentObj *createSegmentObj(SegmentType type); @@ -125,16 +123,19 @@ public: * @param note Invoked for each address on which free_at_address() makes sense * @param param parameter passed to 'note' */ - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const {} + virtual Common::Array listAllDeallocatable(SegmentId segId) const { + return Common::Array(); + } /** * Iterates over all references reachable from the specified object. - * @param object object (within the current segment) to analyse - * @param param parameter passed to 'note' - * @param note Invoked for each outgoing reference within the object + * @param object object (within the current segment) to analyse + * @return refs a list of outgoing references within the object * Note: This function may also choose to report numbers (segment 0) as adresses */ - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const {} + virtual Common::Array listAllOutgoingReferences(reg_t object) const { + return Common::Array(); + } }; @@ -195,7 +196,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -349,7 +350,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -437,10 +438,12 @@ public: entries_used--; } - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const { + virtual Common::Array listAllDeallocatable(SegmentId segId) const { + Common::Array tmp; for (uint i = 0; i < _table.size(); i++) if (isValidEntry(i)) - (*note)(param, make_reg(segId, i)); + tmp.push_back(make_reg(segId, i)); + return tmp; } }; @@ -450,7 +453,7 @@ struct CloneTable : public Table { CloneTable() : Table(SEG_TYPE_CLONES) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -461,7 +464,7 @@ struct NodeTable : public Table { NodeTable() : Table(SEG_TYPE_NODES) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -472,7 +475,7 @@ struct ListTable : public Table { ListTable() : Table(SEG_TYPE_LISTS) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -511,7 +514,7 @@ public: virtual bool isValidOffset(uint16 offset) const; virtual SegmentRef dereference(reg_t pointer); virtual reg_t findCanonicAddress(SegManager *segMan, reg_t sub_addr) const; - virtual void listAllDeallocatable(SegmentId segId, void *param, NoteCallback note) const; + virtual Common::Array listAllDeallocatable(SegmentId segId) const; virtual void saveLoadWithSerializer(Common::Serializer &ser); }; @@ -645,7 +648,7 @@ struct ArrayTable : public Table > { ArrayTable() : Table >(SEG_TYPE_ARRAY) {} virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr); - virtual void listAllOutgoingReferences(reg_t object, void *param, NoteCallback note) const; + virtual Common::Array listAllOutgoingReferences(reg_t object) const; void saveLoadWithSerializer(Common::Serializer &ser); SegmentRef dereference(reg_t pointer); -- cgit v1.2.3 From 6c0205b104e30a60b2c5f9ff5c5e417fde497808 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:23:00 +0000 Subject: SCI: Fix DEBUG_GC mode and permanently enable it svn-id: r50430 --- engines/sci/engine/gc.cpp | 67 ++++++++++++------------------------------ engines/sci/engine/segment.cpp | 44 +++++++++++++++++++++++++++ engines/sci/engine/segment.h | 1 + 3 files changed, 64 insertions(+), 48 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 59f62c8996..a306045cb7 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -28,8 +28,6 @@ namespace Sci { -//#define DEBUG_GC - struct WorklistManager { Common::Array _worklist; reg_t_hash_map _map; @@ -151,68 +149,41 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { return normal_map; } -struct deallocator_t { - SegManager *segMan; - SegmentObj *mobj; -#ifdef DEBUG_GC - char *segnames[SEG_TYPE_MAX + 1]; - int segcount[SEG_TYPE_MAX + 1]; -#endif - reg_t_hash_map *use_map; -}; - -static void free_unless_used(deallocator_t *deallocator, reg_t addr) { - reg_t_hash_map *use_map = deallocator->use_map; - - if (!use_map->contains(addr)) { - // Not found -> we can free it - deallocator->mobj->freeAtAddress(deallocator->segMan, addr); -#ifdef DEBUG_GC - debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); - deallocator->segcount[deallocator->mobj->getType()]++; -#endif - } - -} - void run_gc(EngineState *s) { uint seg_nr; - deallocator_t deallocator; SegManager *segMan = s->_segMan; -#ifdef DEBUG_GC + const char *segnames[SEG_TYPE_MAX + 1]; + int segcount[SEG_TYPE_MAX + 1]; debugC(2, kDebugLevelGC, "[GC] Running..."); - memset(&(deallocator.segcount), 0, sizeof(int) * (SEG_TYPE_MAX + 1)); -#endif + memset(segcount, 0, sizeof(segcount)); - deallocator.segMan = segMan; - deallocator.use_map = find_all_used_references(s); + reg_t_hash_map *use_map = find_all_used_references(s); for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) { if (segMan->_heap[seg_nr] != NULL) { - deallocator.mobj = segMan->_heap[seg_nr]; -#ifdef DEBUG_GC - deallocator.segnames[deallocator.mobj->getType()] = deallocator.mobj->type; // FIXME: add a segment "name" -#endif - const Common::Array tmp = deallocator.mobj->listAllDeallocatable(seg_nr); + SegmentObj *mobj = segMan->_heap[seg_nr]; + segnames[mobj->getType()] = SegmentObj::getSegmentTypeName(mobj->getType()); + const Common::Array tmp = mobj->listAllDeallocatable(seg_nr); for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { - free_unless_used(&deallocator, *it); + const reg_t addr = *it; + if (!use_map->contains(addr)) { + // Not found -> we can free it + mobj->freeAtAddress(segMan, addr); + debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); + segcount[mobj->getType()]++; + } } } } - delete deallocator.use_map; + delete use_map; -#ifdef DEBUG_GC - { - int i; - debugC(2, kDebugLevelGC, "[GC] Summary:"); - for (i = 0; i <= SEG_TYPE_MAX; i++) - if (deallocator.segcount[i]) - debugC(2, kDebugLevelGC, "\t%d\t* %s", deallocator.segcount[i], deallocator.segnames[i]); - } -#endif + debugC(2, kDebugLevelGC, "[GC] Summary:"); + for (int i = 0; i <= SEG_TYPE_MAX; i++) + if (segcount[i]) + debugC(2, kDebugLevelGC, "\t%d\t* %s", segcount[i], segnames[i]); } } // End of namespace Sci diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index f8a941fa7a..21ca1fe9b4 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -86,6 +86,50 @@ SegmentObj *SegmentObj::createSegmentObj(SegmentType type) { return mem; } +const char *SegmentObj::getSegmentTypeName(SegmentType type) { + switch (type) { + case SEG_TYPE_SCRIPT: + return "script"; + break; + case SEG_TYPE_CLONES: + return "clones"; + break; + case SEG_TYPE_LOCALS: + return "locals"; + break; + case SEG_TYPE_SYS_STRINGS: + return "strings"; + break; + case SEG_TYPE_STACK: + return "stack"; + break; + case SEG_TYPE_HUNK: + return "hunk"; + break; + case SEG_TYPE_LISTS: + return "lists"; + break; + case SEG_TYPE_NODES: + return "nodes"; + break; + case SEG_TYPE_DYNMEM: + return "dynmem"; + break; +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + return "array"; + break; + case SEG_TYPE_STRING: + return "string"; + break; +#endif + default: + error("Unknown SegmentObj type %d", type); + break; + } + return NULL; +} + // This helper function is used by Script::relocateLocal and Object::relocate // Duplicate in segment.cpp and script.cpp static bool relocateBlock(Common::Array &block, int block_location, SegmentId segment, int location, size_t scriptSize) { diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index c12efecf1c..d290475593 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -82,6 +82,7 @@ struct SegmentObj : public Common::Serializable { public: static SegmentObj *createSegmentObj(SegmentType type); + static const char *getSegmentTypeName(SegmentType type); public: SegmentObj(SegmentType type) : _type(type) {} -- cgit v1.2.3 From e5509d38b609b23c6fa65f0c511baa6895162ec1 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 11:23:16 +0000 Subject: SCI: More comment rewrapping svn-id: r50431 --- engines/sci/engine/features.cpp | 73 ++++++++++++++++++++++++----------------- 1 file changed, 42 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index 2ad494b37f..f0abdde694 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -91,10 +91,10 @@ bool GameFeatures::autoDetectSoundType() { if (opcode == op_ret || offset >= script->getBufSize()) break; - // The play method of the Sound object pushes the DoSound command - // that it'll use just before it calls DoSound. We intercept that here - // in order to check what sound semantics are used, cause the position - // of the sound commands has changed at some point during SCI1 middle + // The play method of the Sound object pushes the DoSound command that + // it will use just before it calls DoSound. We intercept that here in + // order to check what sound semantics are used, cause the position of + // the sound commands has changed at some point during SCI1 middle. if (opcode == op_pushi) { // Load the pushi parameter intParam = opparams[0]; @@ -105,8 +105,8 @@ bool GameFeatures::autoDetectSoundType() { if (kFuncNum == 6) { // kIsObject (SCI0-SCI11) foundTarget = true; } else if (kFuncNum == 45) { // kDoSound (SCI1) - // First, check which DoSound function is called by the play method of - // the Sound object + // First, check which DoSound function is called by the play + // method of the Sound object switch (intParam) { case 1: _doSoundType = SCI_VERSION_0_EARLY; @@ -119,8 +119,8 @@ bool GameFeatures::autoDetectSoundType() { break; default: // Unknown case... should never happen. We fall back to - // alternative detection here, which works in general, apart from - // some transitive games like Jones CD + // alternative detection here, which works in general, apart + // from some transitive games like Jones CD _doSoundType = foundTarget ? SCI_VERSION_1_LATE : SCI_VERSION_1_EARLY; break; } @@ -137,7 +137,8 @@ bool GameFeatures::autoDetectSoundType() { SciVersion GameFeatures::detectDoSoundType() { if (_doSoundType == SCI_VERSION_NONE) { if (getSciVersion() == SCI_VERSION_0_EARLY) { - // This game is using early SCI0 sound code (different headers than SCI0 late) + // This game is using early SCI0 sound code (different headers than + // SCI0 late) _doSoundType = SCI_VERSION_0_EARLY; } else if (SELECTOR(nodePtr) == -1) { // No nodePtr selector, so this game is definitely using newer @@ -172,14 +173,16 @@ SciVersion GameFeatures::detectSetCursorType() { // SCI1.1 games always use cursor views _setCursorType = SCI_VERSION_1_1; } else { // SCI1 late game, detect cursor semantics - // If the Cursor object doesn't exist, we're using the SCI0 early kSetCursor semantics. + // If the Cursor object doesn't exist, we're using the SCI0 early + // kSetCursor semantics. if (_segMan->findObjectByName("Cursor") == NULL_REG) { _setCursorType = SCI_VERSION_0_EARLY; debugC(1, kDebugLevelGraphics, "Detected SetCursor type: %s", getSciVersionDesc(_setCursorType)); return _setCursorType; } - // Check for the existence of the handCursor object (first found). This is based on KQ5. + // Check for the existence of the handCursor object (first found). + // This is based on KQ5. reg_t objAddr = _segMan->findObjectByName("handCursor", 0); // If that doesn't exist, we assume it uses SCI1.1 kSetCursor semantics @@ -189,11 +192,13 @@ SciVersion GameFeatures::detectSetCursorType() { return _setCursorType; } - // Now we check what the number variable holds in the handCursor object. + // Now we check what the number variable holds in the handCursor + // object. uint16 number = readSelectorValue(_segMan, objAddr, SELECTOR(number)); - // If the number is 0, it uses views and therefore the SCI1.1 kSetCursor semantics, - // otherwise it uses the SCI0 early kSetCursor semantics. + // If the number is 0, it uses views and therefore the SCI1.1 + // kSetCursor semantics, otherwise it uses the SCI0 early kSetCursor + // semantics. if (number == 0) _setCursorType = SCI_VERSION_1_1; else @@ -318,10 +323,10 @@ bool GameFeatures::autoDetectGfxFunctionsType(int methodNum) { uint16 argc = opparams[1]; if (kFuncNum == 8) { // kDrawPic (SCI0 - SCI11) - // If kDrawPic is called with 6 parameters from the - // overlay selector, the game is using old graphics functions. + // If kDrawPic is called with 6 parameters from the overlay + // selector, the game is using old graphics functions. // Otherwise, if it's called with 8 parameters, it's using new - // graphics functions + // graphics functions. _gfxFunctionsType = (argc == 8) ? SCI_VERSION_0_LATE : SCI_VERSION_0_EARLY; return true; } @@ -345,32 +350,35 @@ SciVersion GameFeatures::detectGfxFunctionsType() { reg_t rmObjAddr = _segMan->findObjectByName("Rm"); if (SELECTOR(overlay) != -1) { - // The game has an overlay selector, check how it calls kDrawPicto determine - // the graphics functions type used + // The game has an overlay selector, check how it calls kDrawPic + // to determine the graphics functions type used if (lookupSelector(_segMan, rmObjAddr, SELECTOR(overlay), NULL, NULL) == kSelectorMethod) { if (!autoDetectGfxFunctionsType()) { warning("Graphics functions detection failed, taking an educated guess"); - // Try detecting the graphics function types from the existence of the motionCue - // selector (which is a bit of a hack) + // Try detecting the graphics function types from the + // existence of the motionCue selector (which is a bit + // of a hack) if (_kernel->findSelector("motionCue") != -1) _gfxFunctionsType = SCI_VERSION_0_LATE; else _gfxFunctionsType = SCI_VERSION_0_EARLY; } } else { - // The game has an overlay selector, but it's not a method of the Rm object - // (like in Hoyle 1 and 2), so search for other methods + // The game has an overlay selector, but it's not a method + // of the Rm object (like in Hoyle 1 and 2), so search for + // other methods searchRoomObj = true; } } else { - // The game doesn't have an overlay selector, so search for it manually + // The game doesn't have an overlay selector, so search for it + // manually searchRoomObj = true; } if (searchRoomObj) { - // If requested, check if any method of the Rm object is calling kDrawPic, - // as the overlay selector might be missing in demos + // If requested, check if any method of the Rm object is calling + // kDrawPic, as the overlay selector might be missing in demos bool found = false; const Object *obj = _segMan->getObject(rmObjAddr); @@ -381,8 +389,9 @@ SciVersion GameFeatures::detectGfxFunctionsType() { } if (!found) { - // No method of the Rm object is calling kDrawPic, thus the game - // doesn't have overlays and is using older graphics functions + // No method of the Rm object is calling kDrawPic, thus the + // game doesn't have overlays and is using older graphics + // functions _gfxFunctionsType = SCI_VERSION_0_EARLY; } } @@ -420,9 +429,11 @@ bool GameFeatures::autoDetectSci21KernelType() { uint16 kFuncNum = opparams[0]; // Here we check for the kDoSound opcode that's used in SCI2.1. - // Finding 0x40 as kDoSound in the Sound::play() function means the game is using - // the modified SCI2 kernel table found in some older SCI2.1 games (GK2 demo, KQ7 v1.4). - // Finding 0x75 as kDoSound means the game is using the regular SCI2.1 kernel table. + // Finding 0x40 as kDoSound in the Sound::play() function means the + // game is using the modified SCI2 kernel table found in some older + // SCI2.1 games (GK2 demo, KQ7 v1.4). + // Finding 0x75 as kDoSound means the game is using the regular + // SCI2.1 kernel table. if (kFuncNum == 0x40) { _sci21KernelType = SCI_VERSION_2; return true; -- cgit v1.2.3 From 6063a9cba32443234be31d77e3a7a57870c88007 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 28 Jun 2010 11:40:39 +0000 Subject: Bugfix to properly erase text messages when they expire svn-id: r50432 --- engines/m4/mads_views.cpp | 17 ++++++++--------- engines/m4/mads_views.h | 1 + 2 files changed, 9 insertions(+), 9 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 7b0b1443a8..1766603dc8 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -313,7 +313,7 @@ int MadsTextDisplay::add(int xp, int yp, uint fontColour, int charSpacing, const void MadsTextDisplay::setDirtyAreas() { // Determine dirty areas for active text areas for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) { - if ((_entries[idx].expire < 0) || !_entries[idx].active) + if ((_entries[idx].expire >= 0) || !_entries[idx].active) _owner._dirtyAreas[dirtyIdx].active = false; else { _owner._dirtyAreas[dirtyIdx].textActive = true; @@ -341,14 +341,6 @@ void MadsTextDisplay::draw(View *view, int yOffset) { _entries[idx].spacing); } } - - // Clear up any now text display entries that are to be expired - for (uint idx = 0; idx < _entries.size(); ++idx) { - if (_entries[idx].expire < 0) { - _entries[idx].active = false; - _entries[idx].expire = 0; - } - } } /** @@ -827,6 +819,7 @@ void MadsDirtyAreas::setTextDisplay(int dirtyIdx, const MadsTextDisplayEntry &te * @param count Number of entries to process */ void MadsDirtyAreas::merge(int startIndex, int count) { +return;//***DEBUG*** if (startIndex >= count) return; @@ -878,6 +871,11 @@ void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset, const Co } } +void MadsDirtyAreas::clear() { + for (uint i = 0; i < _entries.size(); ++i) + _entries[i].active = false; +} + /*--------------------------------------------------------------------------*/ MadsSequenceList::MadsSequenceList(MadsView &owner): _owner(owner) { @@ -1209,6 +1207,7 @@ MadsView::~MadsView() { void MadsView::refresh() { // Draw any sprites + _dirtyAreas.clear(); _spriteSlots.drawBackground(_yOffset); // Process dirty areas diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index fc001740d3..8bc507f20b 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -294,6 +294,7 @@ public: bool intersects(int idx1, int idx2); void mergeAreas(int idx1, int idx2); void copy(M4Surface *dest, M4Surface *src, int yOffset, const Common::Point &posAdjust); + void clear(); }; enum SpriteAnimType {ANIMTYPE_CYCLED = 1, ANIMTYPE_REVERSIBLE = 2}; -- cgit v1.2.3 From 6981b943b51f4ae1348e06992e8f7333824d05c5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 12:04:35 +0000 Subject: SCI: fix regression of r50424, 2x scaling svn-id: r50433 --- engines/sci/graphics/screen.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index a86f64c44f..f991f4b8a8 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -594,9 +594,9 @@ void GfxScreen::debugShowMap(int mapNo) { } void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { - const int newWidth = srcWidth * 2; - const byte *srcPtr = src; - + int newWidth = srcWidth * 2; + const byte *srcPtr = src; + for (int y = 0; y < srcHeight; y++) { for (int x = 0; x < srcWidth; x++) { const byte color = *srcPtr++; @@ -606,7 +606,7 @@ void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHei dst[newWidth + 1] = color; dst += 2; } - dst += srcWidth; + dst += newWidth; } } -- cgit v1.2.3 From 445bfee08c6d78457514701aaa4701d7883eea15 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 12:09:48 +0000 Subject: SCI: add const again to newWidth svn-id: r50434 --- engines/sci/graphics/screen.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index f991f4b8a8..8cda42e9aa 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -594,7 +594,7 @@ void GfxScreen::debugShowMap(int mapNo) { } void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { - int newWidth = srcWidth * 2; + const int newWidth = srcWidth * 2; const byte *srcPtr = src; for (int y = 0; y < srcHeight; y++) { -- cgit v1.2.3 From 0f0977535c0fa07ca28ed696c906279153b1c9d8 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Mon, 28 Jun 2010 12:13:04 +0000 Subject: Remove CRs svn-id: r50435 --- engines/sci/graphics/screen.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 8cda42e9aa..eee6898a23 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -594,9 +594,9 @@ void GfxScreen::debugShowMap(int mapNo) { } void GfxScreen::scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight) { - const int newWidth = srcWidth * 2; - const byte *srcPtr = src; - + const int newWidth = srcWidth * 2; + const byte *srcPtr = src; + for (int y = 0; y < srcHeight; y++) { for (int x = 0; x < srcWidth; x++) { const byte color = *srcPtr++; -- cgit v1.2.3 From a278c07aa61fb6790b0f0eb57c8b8b0df4ab1b90 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:27:48 +0000 Subject: SCI: get rid of Script::allocateObject svn-id: r50438 --- engines/sci/engine/script.cpp | 13 ++++--------- engines/sci/engine/script.h | 1 - 2 files changed, 4 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index ac6fb6f26d..2c2325a730 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -181,10 +181,6 @@ void Script::load(ResourceManager *resMan) { } } -Object *Script::allocateObject(uint16 offset) { - return &_objects[offset]; -} - Object *Script::getObject(uint16 offset) { if (_objects.contains(offset)) return &_objects[offset]; @@ -200,17 +196,16 @@ const Object *Script::getObject(uint16 offset) const { } Object *Script::scriptObjInit(reg_t obj_pos, bool fullObjectInit) { - Object *obj; - if (getSciVersion() < SCI_VERSION_1_1 && fullObjectInit) obj_pos.offset += 8; // magic offset (SCRIPT_OBJECT_MAGIC_OFFSET) VERIFY(obj_pos.offset < _bufSize, "Attempt to initialize object beyond end of script\n"); - obj = allocateObject(obj_pos.offset); - VERIFY(obj_pos.offset + kOffsetFunctionArea < (int)_bufSize, "Function area pointer stored beyond end of script\n"); + // Get the object at the specified position and init it. This will + // automatically "allocate" space for it in the _objects map if necessary. + Object *obj = &_objects[obj_pos.offset]; obj->init(_buf, obj_pos, fullObjectInit); return obj; @@ -508,7 +503,7 @@ void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) { // talk-clicks on the robot will act like clicking on ego if (!obj->isClass()) { reg_t classObject = obj->getSuperClassSelector(); - Object *classObj = segMan->getObject(classObject); + const Object *classObj = segMan->getObject(classObject); obj->setPropDictSelector(classObj->getPropDictSelector()); } diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index 490a7a81a3..d1e6a4509e 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -111,7 +111,6 @@ public: virtual void saveLoadWithSerializer(Common::Serializer &ser); - Object *allocateObject(uint16 offset); Object *getObject(uint16 offset); const Object *getObject(uint16 offset) const; -- cgit v1.2.3 From b3011faaef07e607dc3b7a9813d3bd788179a225 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:28:12 +0000 Subject: SCI: Make various SegManager const svn-id: r50439 --- engines/sci/engine/seg_manager.cpp | 14 +++++++------- engines/sci/engine/seg_manager.h | 16 ++++++++-------- 2 files changed, 15 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 56591c4726..ea1fc389cd 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -168,7 +168,7 @@ int SegManager::deallocate(SegmentId seg, bool recursive) { return 1; } -bool SegManager::isHeapObject(reg_t pos) { +bool SegManager::isHeapObject(reg_t pos) const { const Object *obj = getObject(pos); if (obj == NULL || (obj && obj->isFreed())) return false; @@ -194,36 +194,36 @@ Script *SegManager::getScript(const SegmentId seg) { return (Script *)_heap[seg]; } -Script *SegManager::getScriptIfLoaded(const SegmentId seg) { +Script *SegManager::getScriptIfLoaded(const SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg] || _heap[seg]->getType() != SEG_TYPE_SCRIPT) return 0; return (Script *)_heap[seg]; } -SegmentId SegManager::findSegmentByType(int type) { +SegmentId SegManager::findSegmentByType(int type) const { for (uint i = 0; i < _heap.size(); i++) if (_heap[i] && _heap[i]->getType() == type) return i; return 0; } -SegmentObj *SegManager::getSegmentObj(SegmentId seg) { +SegmentObj *SegManager::getSegmentObj(SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg]) return 0; return _heap[seg]; } -SegmentType SegManager::getSegmentType(SegmentId seg) { +SegmentType SegManager::getSegmentType(SegmentId seg) const { if (seg < 1 || (uint)seg >= _heap.size() || !_heap[seg]) return SEG_TYPE_INVALID; return _heap[seg]->getType(); } -SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) { +SegmentObj *SegManager::getSegment(SegmentId seg, SegmentType type) const { return getSegmentType(seg) == type ? _heap[seg] : NULL; } -Object *SegManager::getObject(reg_t pos) { +Object *SegManager::getObject(reg_t pos) const { SegmentObj *mobj = getSegmentObj(pos.segment); Object *obj = NULL; diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 4af2965bc7..0ef904618b 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -161,7 +161,7 @@ public: * @param seg ID of the script segment to check for * @return A pointer to the Script object, or NULL */ - Script *getScriptIfLoaded(SegmentId seg); + Script *getScriptIfLoaded(SegmentId seg) const; // 2. Clones @@ -387,33 +387,33 @@ public: * @param type The type of the segment to find * @return The segment number, or -1 if the segment wasn't found */ - SegmentId findSegmentByType(int type); + SegmentId findSegmentByType(int type) const; // TODO: document this - SegmentObj *getSegmentObj(SegmentId seg); + SegmentObj *getSegmentObj(SegmentId seg) const; // TODO: document this - SegmentType getSegmentType(SegmentId seg); + SegmentType getSegmentType(SegmentId seg) const; // TODO: document this - SegmentObj *getSegment(SegmentId seg, SegmentType type); + SegmentObj *getSegment(SegmentId seg, SegmentType type) const; /** * Retrieves an object from the specified location * @param[in] offset Location (segment, offset) of the object * @return The object in question, or NULL if there is none */ - Object *getObject(reg_t pos); + Object *getObject(reg_t pos) const; /** * Checks whether a heap address contains an object * @parm obj The address to check * @return True if it is an object, false otherwise */ - bool isObject(reg_t obj) { return getObject(obj) != NULL; } + bool isObject(reg_t obj) const { return getObject(obj) != NULL; } // TODO: document this - bool isHeapObject(reg_t pos); + bool isHeapObject(reg_t pos) const; /** * Determines the name of an object -- cgit v1.2.3 From 4f606cc10df1253cb035e3828f974c03f92e631f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:28:29 +0000 Subject: SCI: Clarify docs of GC related SegmentObj methods svn-id: r50440 --- engines/sci/engine/script.h | 6 ++++++ engines/sci/engine/segment.h | 14 +++++++++----- 2 files changed, 15 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.h b/engines/sci/engine/script.h index d1e6a4509e..3817f8aae1 100644 --- a/engines/sci/engine/script.h +++ b/engines/sci/engine/script.h @@ -107,6 +107,12 @@ public: virtual Common::Array listAllDeallocatable(SegmentId segId) const; virtual Common::Array listAllOutgoingReferences(reg_t object) const; + /** + * Return a list of all references to objects in this script + * (and also to the locals segment, if any). + * Used by the garbage collector. + * @return a list of outgoing references within the object + */ Common::Array listObjectReferences() const; virtual void saveLoadWithSerializer(Common::Serializer &ser); diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index d290475593..b1e89e6357 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -105,6 +105,7 @@ public: /** * Finds the canonic address associated with sub_reg. + * Used by the garbage collector. * * For each valid address a, there exists a canonic address c(a) such that c(a) = c(c(a)). * This address "governs" a in the sense that deallocating c(a) will deallocate a. @@ -115,14 +116,15 @@ public: /** * Deallocates all memory associated with the specified address. + * Used by the garbage collector. * @param sub_addr address (within the given segment) to deallocate */ virtual void freeAtAddress(SegManager *segMan, reg_t sub_addr) {} /** - * Iterates over and reports all addresses within the current segment. - * @param note Invoked for each address on which free_at_address() makes sense - * @param param parameter passed to 'note' + * Iterates over and reports all addresses within the segment. + * Used by the garbage collector. + * @return a list of addresses within the segment */ virtual Common::Array listAllDeallocatable(SegmentId segId) const { return Common::Array(); @@ -130,9 +132,11 @@ public: /** * Iterates over all references reachable from the specified object. + * Used by the garbage collector. * @param object object (within the current segment) to analyse - * @return refs a list of outgoing references within the object - * Note: This function may also choose to report numbers (segment 0) as adresses + * @return a list of outgoing references within the object + * + * @note This function may also choose to report numbers (segment 0) as adresses */ virtual Common::Array listAllOutgoingReferences(reg_t object) const { return Common::Array(); -- cgit v1.2.3 From 4fdbd14a60afc72c3b936b02dffd39935594e8e5 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:28:46 +0000 Subject: SCI: Move a few remaining Script methods to engine/script.cpp svn-id: r50441 --- engines/sci/engine/script.cpp | 59 +++++++++++++++++++++++++++++++++++++++++ engines/sci/engine/segment.cpp | 60 ------------------------------------------ 2 files changed, 59 insertions(+), 60 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 2c2325a730..bc63afece5 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -521,4 +521,63 @@ void Script::initialiseObjectsSci11(SegManager *segMan, SegmentId segmentId) { relocate(make_reg(segmentId, READ_SCI11ENDIAN_UINT16(_heapStart))); } +reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { + addr.offset = 0; + return addr; +} + +void Script::freeAtAddress(SegManager *segMan, reg_t addr) { + /* + debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr)); + if (_localsSegment) + debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment); + */ + + if (_markedAsDeleted) + segMan->deallocateScript(_nr); +} + +Common::Array Script::listAllDeallocatable(SegmentId segId) const { + const reg_t r = make_reg(segId, 0); + return Common::Array(&r, 1); +} + +Common::Array Script::listAllOutgoingReferences(reg_t addr) const { + Common::Array tmp; + if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { + const Object *obj = getObject(addr.offset); + if (obj) { + // Note all local variables, if we have a local variable environment + if (_localsSegment) + tmp.push_back(make_reg(_localsSegment, 0)); + + for (uint i = 0; i < obj->getVarCount(); i++) + tmp.push_back(obj->getVariable(i)); + } else { + error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); + } + } else { + /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ + /* Happens e.g. when we're looking into strings */ + } + return tmp; +} + +Common::Array Script::listObjectReferences() const { + Common::Array tmp; + + // Locals, if present + if (_localsSegment) + tmp.push_back(make_reg(_localsSegment, 0)); + + // All objects (may be classes, may be indirectly reachable) + ObjMap::iterator it; + const ObjMap::iterator end = _objects.end(); + for (it = _objects.begin(); it != end; ++it) { + tmp.push_back(it->_value.getPos()); + } + + return tmp; +} + } // End of namespace Sci diff --git a/engines/sci/engine/segment.cpp b/engines/sci/engine/segment.cpp index 21ca1fe9b4..cb908979a3 100644 --- a/engines/sci/engine/segment.cpp +++ b/engines/sci/engine/segment.cpp @@ -245,66 +245,6 @@ SegmentRef SystemStrings::dereference(reg_t pointer) { } -//-------------------- script -------------------- -reg_t Script::findCanonicAddress(SegManager *segMan, reg_t addr) const { - addr.offset = 0; - return addr; -} - -void Script::freeAtAddress(SegManager *segMan, reg_t addr) { - /* - debugC(2, kDebugLevelGC, "[GC] Freeing script %04x:%04x", PRINT_REG(addr)); - if (_localsSegment) - debugC(2, kDebugLevelGC, "[GC] Freeing locals %04x:0000", _localsSegment); - */ - - if (_markedAsDeleted) - segMan->deallocateScript(_nr); -} - -Common::Array Script::listAllDeallocatable(SegmentId segId) const { - const reg_t r = make_reg(segId, 0); - return Common::Array(&r, 1); -} - -Common::Array Script::listAllOutgoingReferences(reg_t addr) const { - Common::Array tmp; - if (addr.offset <= _bufSize && addr.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT(_buf + addr.offset)) { - const Object *obj = getObject(addr.offset); - if (obj) { - // Note all local variables, if we have a local variable environment - if (_localsSegment) - tmp.push_back(make_reg(_localsSegment, 0)); - - for (uint i = 0; i < obj->getVarCount(); i++) - tmp.push_back(obj->getVariable(i)); - } else { - error("Request for outgoing script-object reference at %04x:%04x failed", PRINT_REG(addr)); - } - } else { - /* warning("Unexpected request for outgoing script-object references at %04x:%04x", PRINT_REG(addr));*/ - /* Happens e.g. when we're looking into strings */ - } - return tmp; -} - -Common::Array Script::listObjectReferences() const { - Common::Array tmp; - - // Locals, if present - if (_localsSegment) - tmp.push_back(make_reg(_localsSegment, 0)); - - // All objects (may be classes, may be indirectly reachable) - ObjMap::iterator it; - const ObjMap::iterator end = _objects.end(); - for (it = _objects.begin(); it != end; ++it) { - tmp.push_back(it->_value.getPos()); - } - - return tmp; -} - //-------------------- clones -------------------- Common::Array CloneTable::listAllOutgoingReferences(reg_t addr) const { -- cgit v1.2.3 From 8ae9774a009a2c12123d4bc9070a3d8f043a1c34 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:29:06 +0000 Subject: SCI: Turn more warnings into errors. If one of these is triggered for you, you can add an exception to the error, together with a comment explaining why this exception is necessary. Ideally after verifying that the cause is a script bug and not a bug in our code... svn-id: r50442 --- engines/sci/engine/klists.cpp | 40 ++++++++++++++++++++-------------------- engines/sci/engine/kmath.cpp | 10 +++++----- engines/sci/engine/kmisc.cpp | 12 ++++++------ 3 files changed, 31 insertions(+), 31 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index eb5334c3b9..eff0e725b8 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -37,12 +37,12 @@ static bool isSaneNodePointer(SegManager *segMan, reg_t addr) { Node *node = segMan->lookupNode(addr); if (!node) { - warning("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr)); + error("isSaneNodePointer: Node at %04x:%04x wasn't found", PRINT_REG(addr)); return false; } if (havePrev && node->pred != prev) { - warning("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)", + error("isSaneNodePointer: Node at %04x:%04x points to invalid predecessor %04x:%04x (should be %04x:%04x)", PRINT_REG(addr), PRINT_REG(node->pred), PRINT_REG(prev)); //node->pred = prev; // fix the problem in the node @@ -61,7 +61,7 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { List *list = segMan->lookupList(addr); if (!list) { - warning("isSaneListPointer (list %04x:%04x): The requested list wasn't found", + error("checkListPointer (list %04x:%04x): The requested list wasn't found", PRINT_REG(addr)); return; } @@ -74,17 +74,17 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { Node *node_z = segMan->lookupNode(list->last); if (!node_a) { - warning("isSaneListPointer (list %04x:%04x): missing first node", PRINT_REG(addr)); + error("checkListPointer (list %04x:%04x): missing first node", PRINT_REG(addr)); return; } if (!node_z) { - warning("isSaneListPointer (list %04x:%04x): missing last node", PRINT_REG(addr)); + error("checkListPointer (list %04x:%04x): missing last node", PRINT_REG(addr)); return; } if (!node_a->pred.isNull()) { - warning("isSaneListPointer (list %04x:%04x): First node of the list points to a predecessor node", + error("checkListPointer (list %04x:%04x): First node of the list points to a predecessor node", PRINT_REG(addr)); //node_a->pred = NULL_REG; // fix the problem in the node @@ -93,7 +93,7 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { } if (!node_z->succ.isNull()) { - warning("isSaneListPointer (list %04x:%04x): Last node of the list points to a successor node", + error("checkListPointer (list %04x:%04x): Last node of the list points to a successor node", PRINT_REG(addr)); //node_z->succ = NULL_REG; // fix the problem in the node @@ -105,10 +105,10 @@ static void checkListPointer(SegManager *segMan, reg_t addr) { } else { // Not sane list... it's missing pointers to the first or last element if (list->first.isNull()) - warning("isSaneListPointer (list %04x:%04x): missing pointer to first element", + error("checkListPointer (list %04x:%04x): missing pointer to first element", PRINT_REG(addr)); if (list->last.isNull()) - warning("isSaneListPointer (list %04x:%04x): missing pointer to last element", + error("checkListPointer (list %04x:%04x): missing pointer to last element", PRINT_REG(addr)); } } @@ -267,12 +267,12 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { } if (argc != 3 && argc != 4) { - warning("kAddAfter: Haven't got 3 or 4 arguments, aborting"); + error("kAddAfter: Haven't got 3 or 4 arguments, aborting"); return NULL_REG; } if (argc == 4) // Torin's Passage - warning("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); + error("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); if (firstnode) { // We're really appending after reg_t oldnext = firstnode->succ; @@ -426,14 +426,14 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { reg_t kListAt(EngineState *s, int argc, reg_t *argv) { if (argc != 2) { - warning("kListAt called with %d parameters", argc); + error("kListAt called with %d parameters", argc); return NULL_REG; } List *list = s->_segMan->lookupList(argv[0]); reg_t curAddress = list->first; if (list->first.isNull()) { - warning("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); + error("kListAt tried to reference empty list (%04x:%04x)", PRINT_REG(argv[0])); return NULL_REG; } Node *curNode = s->_segMan->lookupNode(curAddress); @@ -495,7 +495,7 @@ reg_t kListEachElementDo(EngineState *s, int argc, reg_t *argv) { if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // This can only happen with 3 params (list, target selector, variable) if (argc != 3) { - warning("kListEachElementDo: Attempted to modify a variable selector with %d params", argc); + error("kListEachElementDo: Attempted to modify a variable selector with %d params", argc); } else { writeSelector(s->_segMan, curObject, slc, argv[2]); } @@ -527,7 +527,7 @@ reg_t kListFirstTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // Can this happen with variable selectors? - warning("kListFirstTrue: Attempted to access a variable selector"); + error("kListFirstTrue: Attempted to access a variable selector"); } else { invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); @@ -561,7 +561,7 @@ reg_t kListAllTrue(EngineState *s, int argc, reg_t *argv) { // First, check if the target selector is a variable if (lookupSelector(s->_segMan, curObject, slc, &address, NULL) == kSelectorVariable) { // Can this happen with variable selectors? - warning("kListAllTrue: Attempted to access a variable selector"); + error("kListAllTrue: Attempted to access a variable selector"); } else { invokeSelector(s, curObject, slc, argc, argv, argc - 2, argv + 2); @@ -604,15 +604,15 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) { case 11: return kAddToEnd(s, argc - 1, argv + 1); case 12: - warning("kList: unimplemented subfunction kAddBefore"); + error("kList: unimplemented subfunction kAddBefore"); //return kAddBefore(s, argc - 1, argv + 1); return NULL_REG; case 13: - warning("kList: unimplemented subfunction kMoveToFront"); + error("kList: unimplemented subfunction kMoveToFront"); //return kMoveToFront(s, argc - 1, argv + 1); return NULL_REG; case 14: - warning("kList: unimplemented subfunction kMoveToEnd"); + error("kList: unimplemented subfunction kMoveToEnd"); //return kMoveToEnd(s, argc - 1, argv + 1); return NULL_REG; case 15: @@ -632,7 +632,7 @@ reg_t kList(EngineState *s, int argc, reg_t *argv) { case 22: return kSort(s, argc - 1, argv + 1); default: - warning("kList: Unhandled case %d", argv[0].toUint16()); + error("kList: Unhandled case %d", argv[0].toUint16()); return NULL_REG; } } diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index 3c0ab814f1..a7baf72b65 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -115,7 +115,7 @@ reg_t kCosDiv(EngineState *s, int argc, reg_t *argv) { double cosval = cos(angle * PI / 180.0); if ((cosval < 0.0001) && (cosval > -0.0001)) { - warning("kCosDiv: Attempted division by zero"); + error("kCosDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / cosval)); @@ -127,7 +127,7 @@ reg_t kSinDiv(EngineState *s, int argc, reg_t *argv) { double sinval = sin(angle * PI / 180.0); if ((sinval < 0.0001) && (sinval > -0.0001)) { - warning("kSinDiv: Attempted division by zero"); + error("kSinDiv: Attempted division by zero"); return SIGNAL_REG; } else return make_reg(0, (int16)(value / sinval)); @@ -139,7 +139,7 @@ reg_t kTimesTan(EngineState *s, int argc, reg_t *argv) { param -= 90; if ((param % 90) == 0) { - warning("kTimesTan: Attempted tan(pi/2)"); + error("kTimesTan: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16) - (tan(param * PI / 180.0) * scale)); @@ -150,7 +150,7 @@ reg_t kTimesCot(EngineState *s, int argc, reg_t *argv) { int scale = (argc > 1) ? argv[1].toSint16() : 1; if ((param % 90) == 0) { - warning("kTimesCot: Attempted tan(pi/2)"); + error("kTimesCot: Attempted tan(pi/2)"); return SIGNAL_REG; } else return make_reg(0, (int16)(tan(param * PI / 180.0) * scale)); @@ -165,7 +165,7 @@ reg_t kMulDiv(EngineState *s, int argc, reg_t *argv) { // Sanity check... if (!denominator) { - warning("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); + error("kMulDiv: attempt to divide by zero (%d * %d / %d", multiplicant, multiplier, denominator); return NULL_REG; } diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index f742734ad7..3d206d0358 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -123,7 +123,7 @@ reg_t kMemoryInfo(EngineState *s, int argc, reg_t *argv) { return make_reg(0, size); default: - warning("Unknown MemoryInfo operation: %04x", argv[0].offset); + error("Unknown MemoryInfo operation: %04x", argv[0].offset); } return NULL_REG; @@ -198,7 +198,7 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) { int mode = (argc > 0) ? argv[0].toUint16() : 0; if (getSciVersion() <= SCI_VERSION_0_LATE && mode > 1) - warning("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode); + error("kGetTime called in SCI0 with mode %d (expected 0 or 1)", mode); switch (mode) { case K_NEW_GETTIME_TICKS : @@ -218,7 +218,7 @@ reg_t kGetTime(EngineState *s, int argc, reg_t *argv) { debugC(2, kDebugLevelTime, "GetTime(date) returns %d", retval); break; default: - warning("Attempt to use unknown GetTime mode %d", mode); + error("Attempt to use unknown GetTime mode %d", mode); break; } @@ -264,7 +264,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { SegmentRef ref = s->_segMan->dereference(argv[1]); if (!ref.isValid() || ref.maxSize < 2) { - warning("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1])); + error("Attempt to peek invalid memory at %04x:%04x", PRINT_REG(argv[1])); return s->r_acc; } if (ref.isRaw) @@ -280,7 +280,7 @@ reg_t kMemory(EngineState *s, int argc, reg_t *argv) { SegmentRef ref = s->_segMan->dereference(argv[1]); if (!ref.isValid() || ref.maxSize < 2) { - warning("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1])); + error("Attempt to poke invalid memory at %04x:%04x", PRINT_REG(argv[1])); return s->r_acc; } @@ -375,7 +375,7 @@ reg_t kPlatform(EngineState *s, int argc, reg_t *argv) { case kPlatformIsItWindows: return make_reg(0, isWindows); default: - warning("Unsupported kPlatform operation %d", operation); + error("Unsupported kPlatform operation %d", operation); } return NULL_REG; -- cgit v1.2.3 From 9b4406fd350458e1fe194dadd76a0cb97c2ca324 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 28 Jun 2010 12:55:47 +0000 Subject: SCI: Some more GC cleanup svn-id: r50443 --- engines/sci/engine/gc.cpp | 33 +++++++++++++++++++++------------ 1 file changed, 21 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index a306045cb7..3c8c1f17a8 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -150,36 +150,45 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { } void run_gc(EngineState *s) { - uint seg_nr; SegManager *segMan = s->_segMan; + // Some debug stuff + debugC(2, kDebugLevelGC, "[GC] Running..."); const char *segnames[SEG_TYPE_MAX + 1]; int segcount[SEG_TYPE_MAX + 1]; - debugC(2, kDebugLevelGC, "[GC] Running..."); + memset(segnames, 0, sizeof(segnames)); memset(segcount, 0, sizeof(segcount)); - reg_t_hash_map *use_map = find_all_used_references(s); - - for (seg_nr = 1; seg_nr < segMan->_heap.size(); seg_nr++) { - if (segMan->_heap[seg_nr] != NULL) { - SegmentObj *mobj = segMan->_heap[seg_nr]; - segnames[mobj->getType()] = SegmentObj::getSegmentTypeName(mobj->getType()); - const Common::Array tmp = mobj->listAllDeallocatable(seg_nr); + // Compute the set of all segments references currently in use. + reg_t_hash_map *activeRefs = find_all_used_references(s); + + // Iterate over all segments, and check for each whether it + // contains stuff that can be collected. + for (uint seg = 1; seg < segMan->_heap.size(); seg++) { + SegmentObj *mobj = segMan->_heap[seg]; + if (mobj != NULL) { + const SegmentType type = mobj->getType(); + segnames[type] = SegmentObj::getSegmentTypeName(type); + + // Get a list of all deallocatable objects in this segment, + // then free any which are not referenced from somewhere. + const Common::Array tmp = mobj->listAllDeallocatable(seg); for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) { const reg_t addr = *it; - if (!use_map->contains(addr)) { + if (!activeRefs->contains(addr)) { // Not found -> we can free it mobj->freeAtAddress(segMan, addr); debugC(2, kDebugLevelGC, "[GC] Deallocating %04x:%04x", PRINT_REG(addr)); - segcount[mobj->getType()]++; + segcount[type]++; } } } } - delete use_map; + delete activeRefs; + // Output debug summary of garbage collection debugC(2, kDebugLevelGC, "[GC] Summary:"); for (int i = 0; i <= SEG_TYPE_MAX; i++) if (segcount[i]) -- cgit v1.2.3 From 6402d644199e17cbf7770c98ebf8c1edca7c4cca Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 14:21:56 +0000 Subject: SCI: cleanup of execstack, output of backtrace slightly modified, is now also displaying local calls and exports svn-id: r50445 --- engines/sci/console.cpp | 27 ++++++++++++++++----------- engines/sci/engine/vm.cpp | 30 +++++++++++++++--------------- engines/sci/engine/vm.h | 8 ++++---- 3 files changed, 35 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 8ea7daa7c6..b30349dd5a 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2320,8 +2320,6 @@ bool Console::cmdScriptSteps(int argc, const char **argv) { } bool Console::cmdBacktrace(int argc, const char **argv) { - DebugPrintf("Dumping the send/self/super/call/calle/callb stack:\n"); - DebugPrintf("Call stack (current base: 0x%x):\n", _engine->_gamestate->executionStackBase); Common::List::iterator iter; uint i = 0; @@ -2333,19 +2331,25 @@ bool Console::cmdBacktrace(int argc, const char **argv) { int paramc, totalparamc; switch (call.type) { - case EXEC_STACK_TYPE_CALL: // Normal function - DebugPrintf(" %x:[%x] %s::%s(", i, call.origin, objname, (call.selector == -1) ? "" : - _engine->getKernel()->getSelectorName(call.selector).c_str()); + if (call.type == EXEC_STACK_TYPE_CALL) + DebugPrintf(" %x: script %d - ", i, (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber()); + if (call.debugSelector != -1) { + DebugPrintf("%s::%s(", objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); + } else if (call.debugExportId != -1) { + DebugPrintf("export %d (", call.debugExportId); + } else if (call.debugLocalCallOffset != -1) { + DebugPrintf("call %x (", call.debugLocalCallOffset); + } break; case EXEC_STACK_TYPE_KERNEL: // Kernel function - DebugPrintf(" %x:[%x] k%s(", i, call.origin, _engine->getKernel()->getKernelName(call.selector).c_str()); + DebugPrintf(" %x:[%x] k%s(", i, call.debugOrigin, _engine->getKernel()->getKernelName(call.debugSelector).c_str()); break; case EXEC_STACK_TYPE_VARSELECTOR: - DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.origin, (call.argc) ? "write" : "read", - objname, _engine->getKernel()->getSelectorName(call.selector).c_str()); + DebugPrintf(" %x:[%x] vs%s %s::%s (", i, call.debugOrigin, (call.argc) ? "write" : "read", + objname, _engine->getKernel()->getSelectorName(call.debugSelector).c_str()); break; } @@ -2364,7 +2368,10 @@ bool Console::cmdBacktrace(int argc, const char **argv) { if (call.argc > 16) DebugPrintf("..."); - DebugPrintf(")\n obj@%04x:%04x", PRINT_REG(call.objp)); + DebugPrintf(")\n "); + if (call.debugOrigin != -1) + DebugPrintf("by %x ", call.debugOrigin); + DebugPrintf("obj@%04x:%04x", PRINT_REG(call.objp)); if (call.type == EXEC_STACK_TYPE_CALL) { DebugPrintf(" pc=%04x:%04x", PRINT_REG(call.addr.pc)); if (call.sp == CALL_SP_CARRY) @@ -2377,8 +2384,6 @@ bool Console::cmdBacktrace(int argc, const char **argv) { DebugPrintf(" pc:none"); DebugPrintf(" argp:ST:%04x", (unsigned)(call.variables_argp - _engine->_gamestate->stack_base)); - if (call.type == EXEC_STACK_TYPE_CALL) - DebugPrintf(" script: %d", (*(Script *)_engine->_gamestate->_segMan->_heap[call.addr.pc.segment]).getScriptNumber()); DebugPrintf("\n"); } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 686603ae21..2047482bac 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -301,15 +301,15 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); int curScriptNr = local_script->getScriptNumber(); - if (lastCall->localCallOffset != -1) { + if (lastCall->debugLocalCallOffset != -1) { // if lastcall was actually a local call search back for a real call Common::List::iterator callIterator = state->_executionStack.end(); while (callIterator != state->_executionStack.begin()) { callIterator--; ExecStack loopCall = *callIterator; - if ((loopCall.selector != -1) || (loopCall.exportId != -1)) { - lastCall->selector = loopCall.selector; - lastCall->exportId = loopCall.exportId; + if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) { + lastCall->debugSelector = loopCall.debugSelector; + lastCall->debugExportId = loopCall.debugExportId; break; } } @@ -320,11 +320,11 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i const SciGameId gameId = g_sci->getGameId(); if (lastCall->type == EXEC_STACK_TYPE_CALL) { - if (lastCall->selector != -1) { - curMethodName = g_sci->getKernel()->getSelectorName(lastCall->selector); - } else if (lastCall->exportId != -1) { + if (lastCall->debugSelector != -1) { + curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector); + } else if (lastCall->debugExportId != -1) { curObjectName = ""; - curMethodName = curMethodName.printf("export %d", lastCall->exportId); + curMethodName = curMethodName.printf("export %d", lastCall->debugExportId); } } @@ -336,7 +336,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i workaround = uninitializedReadWorkarounds; while (workaround->objectName) { if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->objectName == searchObjectName) - && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->localCallOffset && workaround->index == index) { + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { // Workaround found r[index] = make_reg(0, workaround->newValue); return r[index]; @@ -348,7 +348,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (!searchObject.isNull()) searchObjectName = state->_segMan->getObjectName(searchObject); } while (!searchObject.isNull()); // no parent left? - error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->localCallOffset); + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->debugLocalCallOffset); } return r[index]; } else @@ -718,10 +718,10 @@ static ExecStack *add_exec_stack_entry(Common::List &execStack, reg_t *argp = make_reg(0, argc); // SCI code relies on the zeroeth argument to equal argc // Additional debug information - xstack.selector = selector; - xstack.exportId = exportId; - xstack.localCallOffset = localCallOffset; - xstack.origin = origin; + xstack.debugSelector = selector; + xstack.debugExportId = exportId; + xstack.debugLocalCallOffset = localCallOffset; + xstack.debugOrigin = origin; xstack.type = EXEC_STACK_TYPE_CALL; // Normal call @@ -777,7 +777,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { ExecStack *xstack; xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->selector = kernelFuncNr; + xstack->debugSelector = kernelFuncNr; xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h index 49169a456c..81ec4f1c61 100644 --- a/engines/sci/engine/vm.h +++ b/engines/sci/engine/vm.h @@ -97,10 +97,10 @@ struct ExecStack { StackPtr variables_argp; // Argument pointer SegmentId local_segment; // local variables etc - Selector selector; // The selector which was used to call or -1 if not applicable - int exportId; // The exportId which was called or -1 if not applicable - int localCallOffset; // Local call offset or -1 if not applicable - int origin; // The stack frame position the call was made from, or -1 if it was the initial call + Selector debugSelector; // The selector which was used to call or -1 if not applicable + int debugExportId; // The exportId which was called or -1 if not applicable + int debugLocalCallOffset; // Local call offset or -1 if not applicable + int debugOrigin; // The stack frame position the call was made from, or -1 if it was the initial call ExecStackType type; reg_t* getVarPointer(SegManager *segMan) const; -- cgit v1.2.3 From 66fb9e7a90874e27486db98f0eb8d6f0512a00c5 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 14:46:28 +0000 Subject: SCI: fixing valgrind issue in Script::initialiseClasses thx to wjp for valgrind testing svn-id: r50446 --- engines/sci/engine/script.cpp | 13 ++++++++----- 1 file changed, 8 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index bc63afece5..4100ca6448 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -410,12 +410,14 @@ void Script::initialiseClasses(SegManager *segMan) { if (!seeker) return; + uint16 marker; + bool isClass; + uint16 classpos = seeker - _buf; + int16 species = 0; + while (true) { // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234) - uint16 marker = READ_SCI11ENDIAN_UINT16(seeker); - bool isClass; - uint16 classpos = seeker - _buf; - int16 species; + marker = READ_SCI11ENDIAN_UINT16(seeker); if (!marker) break; @@ -425,7 +427,8 @@ void Script::initialiseClasses(SegManager *segMan) { species = READ_SCI11ENDIAN_UINT16(seeker + 10); } else { isClass = (marker == SCI_OBJ_CLASS); - species = READ_SCI11ENDIAN_UINT16(seeker + 12); + if (isClass) + species = READ_SCI11ENDIAN_UINT16(seeker + 12); classpos += 12; } -- cgit v1.2.3 From 8410dbab539a8c278b29e9047bd5c192a3048e32 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 14:49:54 +0000 Subject: SCI: stupid oversight fix r50446, too hot here :P svn-id: r50447 --- engines/sci/engine/script.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/script.cpp b/engines/sci/engine/script.cpp index 4100ca6448..a293f81d2f 100644 --- a/engines/sci/engine/script.cpp +++ b/engines/sci/engine/script.cpp @@ -412,12 +412,13 @@ void Script::initialiseClasses(SegManager *segMan) { uint16 marker; bool isClass; - uint16 classpos = seeker - _buf; + uint16 classpos; int16 species = 0; while (true) { // In SCI0-SCI1, this is the segment type. In SCI11, it's a marker (0x1234) marker = READ_SCI11ENDIAN_UINT16(seeker); + classpos = seeker - _buf; if (!marker) break; -- cgit v1.2.3 From e857cc623e86211ae0c59630342cbeea65214e6e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 16:35:20 +0000 Subject: SCI: added comment - lsl5 also has too large windows svn-id: r50450 --- engines/sci/graphics/ports.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 36f84c3582..611db1061a 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -251,6 +251,7 @@ Window *GfxPorts::newWindow(const Common::Rect &dims, const Common::Rect *restor r = dims; if (r.width() > _screen->getWidth()) { // We get invalid dimensions at least at the end of sq3 (script bug!) + // same happens very often in lsl5, sierra sci didnt fix it but it looked awful warning("fixing too large window, given left&right was %d, %d", dims.left, dims.right); r.left = 0; r.right = _screen->getWidth() - 1; -- cgit v1.2.3 From 06648cb186608e845c4dc214249b863632bbbb3c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 16:56:15 +0000 Subject: SCI: fix regression of r50422, please no refactoring without proper testing - fixes animations in all sorts of games svn-id: r50451 --- engines/sci/graphics/view.cpp | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 71261490e4..b3bc733383 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -279,10 +279,8 @@ const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const { } uint16 GfxView::getCelCount(int16 loopNo) const { -// assert(_loopCount); -// loopNo = CLIP(loopNo, 0, _loopCount - 1); - if ((loopNo < 0) || (loopNo >= _loopCount)) - return 0; + assert(_loopCount); + loopNo = CLIP(loopNo, 0, _loopCount - 1); return _loop[loopNo].celCount; } -- cgit v1.2.3 From a0f42b07ceb836226521fbf90feb50fb470d8ad8 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Mon, 28 Jun 2010 17:03:04 +0000 Subject: KYRA: change audio detection flags setting (since most users don't own a real mt-32/lapc1/cm32l/cm64 device and our emulator is incomplete) svn-id: r50452 --- engines/kyra/kyra_v1.cpp | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/kyra/kyra_v1.cpp b/engines/kyra/kyra_v1.cpp index be8f976053..abe13cec2b 100644 --- a/engines/kyra/kyra_v1.cpp +++ b/engines/kyra/kyra_v1.cpp @@ -105,8 +105,11 @@ Common::Error KyraEngine_v1::init() { _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); if (!_flags.useDigSound) { - // We prefer AdLib over MIDI, since generally AdLib is better supported - MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | MDT_PREFER_MT32); + // We prefer AdLib over MIDI in Kyra 1, since it offers MT-32 support only, most users don't have a real + // MT-32/LAPC1/CM32L/CM64 device and AdLib sounds better than our incomplete MT-32 emulator and also better than + // MT-32/GM mapping. For Kyra 2 and LoL which have real GM tracks which sound better than AdLib tracks we prefer GM + // since most users have a GM compatible device. + MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_PCSPK | MDT_MIDI | MDT_ADLIB | ((_flags.gameID == GI_KYRA2 || _flags.gameID == GI_LOL) ? MDT_PREFER_GM : 0)); if (_flags.platform == Common::kPlatformFMTowns) { if (_flags.gameID == GI_KYRA1) -- cgit v1.2.3 From bc777403066e7a14b3b25d1ef4cf038723b85a02 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 18:07:40 +0000 Subject: SCI: kAnimate resetting _lastCastCount all the time svn-id: r50453 --- engines/sci/graphics/animate.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 6a5bbff6bb..25c0fe6432 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -159,8 +159,8 @@ void GfxAnimate::makeSortedList(List *list) { _lastCastData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry)); if (!_lastCastData) error("Could not allocate memory for _lastCastData"); - _lastCastCount = 0; } + _lastCastCount = 0; // Fill the list curAddress = list->first; -- cgit v1.2.3 From 473c429b5cb7f96112f752a99fc62c7d4d4d55ee Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 18:10:21 +0000 Subject: SCI: updated comment about transparent pixels in views svn-id: r50454 --- engines/sci/graphics/view.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index b3bc733383..ee9611b046 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -332,8 +332,8 @@ void GfxView::unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCou pixelNo += runLength; } } else { - // We skip over transparent pixels, so the buffer needs to be already - // filled with "it". (FIXME: What is "it" supposed to mean here?) + // We fill the buffer with transparent pixels, so that we can later skip + // over pixels to automatically have them transparent // Also some RLE compressed cels are possibly ending with the last // non-transparent pixel (is this even possible with the current code?) memset(outPtr, _loop[loopNo].cel[celNo].clearKey, pixelCount); -- cgit v1.2.3 From d8e4160f34787cb239e8073946249fcbfd8e8a34 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 20:17:43 +0000 Subject: SCI: remove clipping of volume inside SciMidiParser::setvolume svn-id: r50456 --- engines/sci/sound/midiparser_sci.cpp | 7 ------- 1 file changed, 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 2a86ef8942..3c2c0cb3ce 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -665,13 +665,6 @@ void MidiParser_SCI::allNotesOff() { } void MidiParser_SCI::setVolume(byte volume) { - // FIXME: This receives values > 127... throw a warning for now and clip the variable - if (volume > MUSIC_VOLUME_MAX) { - // FIXME: please write where we get an invalid volume, so we can track down the issue - error("attempted to set an invalid volume(%d)", volume); - volume = MUSIC_VOLUME_MAX; // reset - } - assert(volume <= MUSIC_VOLUME_MAX); _volume = volume; -- cgit v1.2.3 From 438e670166768df06025f50c68e2d8fbe0f93407 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 28 Jun 2010 20:31:30 +0000 Subject: Applied patch #3022511 - "qfg4 detection cleanup" svn-id: r50457 --- engines/sci/detection_tables.h | 23 +---------------------- 1 file changed, 1 insertion(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index bad7ccc5c3..d2136666a7 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -2398,7 +2398,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { }, // Quest for Glory 4 1.1 Floppy - German DOS (supplied by markcool in bug report #2723850) - // SCI interpreter version 2.000.000 (a guess?) + // Executable scanning reports "2.000.000", VERSION file reports "1.1" {"qfg4", "", { {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, @@ -2415,27 +2415,6 @@ static const struct ADGameDescription SciGameDescriptions[] = { Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, -#if 0 - // NOTE: This version looks to be exactly the same as the English one - // Perhaps it's the English one? - - // Quest for Glory 4 - German DOS/Windows (from PCJoker 2/98) - {"qfg4", "", { - {"resource.map", 0, "aba367f2102e81782d961b14fbe3d630", 10246}, - {"resource.000", 0, "263dce4aa34c49d3ad29bec889007b1c", 11571394}, - {NULL, 0, NULL, 0}}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH - }, -#endif - - // Quest for Glory 4 - German DOS/Windows Disk V1.1 (from PCJoker 2/89) - // SCI interpreter version 2.000.000 (a guess?) - {"qfg4", "", { - {"resource.map", 0, "9e0abba8746f40565bc7eb5720522ecd", 9301}, - {"resource.000", 0, "57f22cdc54eeb35fce1f26b31b5c3ee1", 11076197}, - {NULL, 0, NULL, 0}}, - Common::DE_DEU, Common::kPlatformPC, 0, GUIO_NOSPEECH - }, #endif // Slater & Charlie go camping -- cgit v1.2.3 From 0b33cc0dab3c71d631d38742c3125bd88f4e759a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 28 Jun 2010 20:58:32 +0000 Subject: Fixed loading of saved games from the launcher svn-id: r50460 --- engines/sci/sci.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 822adb592b..fd4c4e9137 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -236,8 +236,9 @@ Common::Error SciEngine::run() { debug("Emulating SCI version %s\n", getSciVersionDesc(getSciVersion())); // Check whether loading a savestate was requested - if (ConfMan.hasKey("save_slot")) { - reg_t restoreArgv[2] = { NULL_REG, make_reg(0, ConfMan.getInt("save_slot")) }; // special call (argv[0] is NULL) + int saveSlot = ConfMan.getInt("save_slot"); + if (saveSlot >= 0) { + reg_t restoreArgv[2] = { NULL_REG, make_reg(0, saveSlot) }; // special call (argv[0] is NULL) kRestoreGame(_gamestate, 2, restoreArgv); // Initialize the game menu, if there is one. -- cgit v1.2.3 From 58732b9df1f0451f03c2ca01e0cab48314a360d3 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 28 Jun 2010 22:01:26 +0000 Subject: SCI: More changes to the code for loading from the launcher - Added support for the LSL2 menu bar object - We no longer need a reference to the init() selector - it's always the first method of the menu bar object svn-id: r50462 --- engines/sci/engine/selector.cpp | 1 - engines/sci/engine/selector.h | 2 -- engines/sci/sci.cpp | 23 +++++++++-------------- 3 files changed, 9 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/selector.cpp b/engines/sci/engine/selector.cpp index 155aa83883..00480743cc 100644 --- a/engines/sci/engine/selector.cpp +++ b/engines/sci/engine/selector.cpp @@ -161,7 +161,6 @@ void Kernel::mapSelectors() { FIND_SELECTOR(maxScale); FIND_SELECTOR(vanishingX); FIND_SELECTOR(vanishingY); - FIND_SELECTOR(init); FIND_SELECTOR(iconIndex); #ifdef ENABLE_SCI32 diff --git a/engines/sci/engine/selector.h b/engines/sci/engine/selector.h index 1fff7caac8..acb7912d8d 100644 --- a/engines/sci/engine/selector.h +++ b/engines/sci/engine/selector.h @@ -103,8 +103,6 @@ struct SelectorCache { // perform Selector moveDone; ///< used for DoBresen - Selector init; ///< Used for menu initialization when loading from the launcher - // SCI1 selectors which have been moved a bit in SCI1.1, but otherwise static Selector cantBeHere; ///< Checks for movement avoidance in SCI1+. Replaces canBeHere Selector topString; ///< SCI1 scroll lists use this instead of lsTop diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index fd4c4e9137..46d33eda78 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -244,23 +244,18 @@ Common::Error SciEngine::run() { // Initialize the game menu, if there is one. // This is not done when loading, so we must do it manually. reg_t menuBarObj = _gamestate->_segMan->findObjectByName("MenuBar"); + if (menuBarObj.isNull()) + menuBarObj = _gamestate->_segMan->findObjectByName("TheMenuBar"); // LSL2 if (menuBarObj.isNull()) menuBarObj = _gamestate->_segMan->findObjectByName("menuBar"); // LSL6 if (!menuBarObj.isNull()) { - // Game menus are found in SCI0-SCI01 games (but not in demos), which had a selector vocabulary, - // thus the following code should always work (at least theoretically). - // The init selector is being moved around in all games, thus adding it to the list of static - // selectors can be tricky. An alternative way would be to call the first method of the - // MenuBar object (which is init), but this will require refactoring. - if (_kernel->_selectorCache.init != -1) { - // Reset abortScriptProcessing before initializing the game menu, so that the - // VM call performed by invokeSelector will actually run. - _gamestate->abortScriptProcessing = kAbortNone; - invokeSelector(_gamestate, menuBarObj, SELECTOR(init), 0, _gamestate->stack_base); - _gamestate->abortScriptProcessing = kAbortLoadGame; - } else { - warning("Game has a menu but not a selector vocabulary, skipping menu initialization"); - } + // Reset abortScriptProcessing before initializing the game menu, so that the + // VM call performed by invokeSelector will actually run. + _gamestate->abortScriptProcessing = kAbortNone; + Object *menuBar = _gamestate->_segMan->getObject(menuBarObj); + // Invoke the first method (init) of the menuBar object + invokeSelector(_gamestate, menuBarObj, menuBar->getFuncSelector(0), 0, _gamestate->stack_base); + _gamestate->abortScriptProcessing = kAbortLoadGame; } } -- cgit v1.2.3 From 805374ff4eadb42e78dfbda64ad6d308b372fbbc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 22:06:19 +0000 Subject: SCI: ignoring set signal on tick 0 directly in parseNextEvent instead of filtering, also now ignoring channel volume changes on tick 0 (fixes lsl5 fading of sound 274, almost at the end), fixing also fading in gk1 and enabling fading in sci32 again svn-id: r50463 --- engines/sci/sound/midiparser_sci.cpp | 29 ++++++++++++++++------------- engines/sci/sound/music.cpp | 8 -------- 2 files changed, 16 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 3c2c0cb3ce..241405cb1e 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -160,15 +160,6 @@ byte *MidiParser_SCI::midiMixChannels() { ticker += newDelta; midiCommand = channel->data[channel->curPos++]; - if ((midiCommand == 0xCF) && (!ticker)) { - // set signal command at tick 0? - channel->curPos++; - continue; // filter it - // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately - // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to - // get immediately removed, so we currently filter it. - // TODO: find out what exactly happens in sierra sci - } if (midiCommand != kEndOfTrack) { // Write delta while (newDelta > 240) { @@ -480,8 +471,14 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { info.basic.param2 = 0; if (info.channel() == 0xF) {// SCI special case if (info.basic.param1 != kSetSignalLoop) { - _signalSet = true; - _signalToSet = info.basic.param1; + // at least in kq5/french&mac the first scene in the intro has a song that sets signal to 4 immediately + // on tick 0. Signal isn't set at that point by sierra sci and it would cause the castle daventry text to + // get immediately removed, so we currently filter it. + // Sierra SCI ignores them as well at that time + if (_position._play_tick) { + _signalSet = true; + _signalToSet = info.basic.param1; + } } else { _loopTick = _position._play_tick + info.delta; } @@ -556,8 +553,14 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { } } switch (info.basic.param1) { - case 7: // channel volume change -scale it - info.basic.param2 = info.basic.param2 * _volume / MUSIC_VOLUME_MAX; + case 7: // channel volume change + if (!_position._play_tick) { + // if this is tried on tick 0, ignore the command + // this is needed for lsl5 sound resource 274, it sets channel volume to very low at the start + // sierra sci ignores those + parseNextEvent(_next_event); + return; + } break; } info.length = 0; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index f10ff6d09a..ba103ee746 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -629,14 +629,6 @@ void MusicEntry::doFade() { fadeStep = 0; fadeCompleted = true; } -#ifdef ENABLE_SCI32 - // Disable fading for SCI32 - sound drivers have issues when fading in (gabriel knight 1 sierra title) - if (getSciVersion() >= SCI_VERSION_2) { - volume = fadeTo; - fadeStep = 0; - fadeCompleted = true; - } -#endif // Only process MIDI streams in this thread, not digital sound effects if (pMidiParser) { -- cgit v1.2.3 From ee6aebc78022008ba31a8a24441eeaeed804fd78 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Mon, 28 Jun 2010 22:08:46 +0000 Subject: Don't initialize graphics again when loading svn-id: r50464 --- engines/sci/engine/savegame.cpp | 2 -- 1 file changed, 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index c0ed515981..7804265d0d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -984,8 +984,6 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { // Message state: s->_msgState = new MessageState(s->_segMan); - g_sci->initGraphics(); - s->abortScriptProcessing = kAbortLoadGame; s->shrinkStackToBase(); } -- cgit v1.2.3 From 668d820afd77ed8efd309f1d380005ab828f9cb8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 22:14:03 +0000 Subject: SCI: its lsl5 sound resource 294, not 274 (changed comment only) svn-id: r50465 --- engines/sci/sound/midiparser_sci.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index 241405cb1e..d6c0b2080f 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -556,7 +556,7 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { case 7: // channel volume change if (!_position._play_tick) { // if this is tried on tick 0, ignore the command - // this is needed for lsl5 sound resource 274, it sets channel volume to very low at the start + // this is needed for lsl5 sound resource 294, it sets channel volume to very low at the start // sierra sci ignores those parseNextEvent(_next_event); return; -- cgit v1.2.3 From 15f9f37d4d15e8c8972fa0ecdbbdaf138ea2a8da Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 28 Jun 2010 22:26:28 +0000 Subject: SCI: removing ignoring of channel volume change code from r50463, the lsl5 issue was actually caused by the old volume adjust code that was also causing the issues in gk1 svn-id: r50466 --- engines/sci/sound/midiparser_sci.cpp | 11 ----------- 1 file changed, 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/midiparser_sci.cpp b/engines/sci/sound/midiparser_sci.cpp index d6c0b2080f..cc09ba79f0 100644 --- a/engines/sci/sound/midiparser_sci.cpp +++ b/engines/sci/sound/midiparser_sci.cpp @@ -552,17 +552,6 @@ void MidiParser_SCI::parseNextEvent(EventInfo &info) { break; } } - switch (info.basic.param1) { - case 7: // channel volume change - if (!_position._play_tick) { - // if this is tried on tick 0, ignore the command - // this is needed for lsl5 sound resource 294, it sets channel volume to very low at the start - // sierra sci ignores those - parseNextEvent(_next_event); - return; - } - break; - } info.length = 0; break; -- cgit v1.2.3 From 79aa49a509fd82bd3e4a97056efdc1e26913edd5 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 29 Jun 2010 02:55:31 +0000 Subject: Fix the load game dialog in Riven DVD's menu, borrowed from Parallaction. svn-id: r50477 --- engines/mohawk/riven.cpp | 17 +++++++++++++---- engines/mohawk/riven.h | 1 - 2 files changed, 13 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 44b7868373..77559b67e4 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -76,7 +76,6 @@ MohawkEngine_Riven::~MohawkEngine_Riven() { delete _extrasFile; delete _saveLoad; delete[] _vars; - delete _loadDialog; delete _optionsDialog; delete _rnd; delete g_atrusJournalRect1; @@ -100,8 +99,6 @@ Common::Error MohawkEngine_Riven::run() { _console = new RivenConsole(this); _saveLoad = new RivenSaveLoad(this, _saveFileMan); _externalScriptHandler = new RivenExternal(this); - _loadDialog = new GUI::SaveLoadChooser("Load Game:", "Load"); - _loadDialog->setSaveMode(false); _optionsDialog = new RivenOptionsDialog(this); _rnd = new Common::RandomSource(); @@ -600,7 +597,19 @@ void MohawkEngine_Riven::runHotspotScript(uint16 hotspot, uint16 scriptType) { } void MohawkEngine_Riven::runLoadDialog() { - runDialog(*_loadDialog); + GUI::SaveLoadChooser slc("Load Game:", "Load"); + slc.setSaveMode(false); + + Common::String gameId = ConfMan.get("gameid"); + + const EnginePlugin *plugin = 0; + EngineMan.findGame(gameId, &plugin); + + int slot = slc.runModal(plugin, ConfMan.getActiveDomainName()); + if (slot >= 0) + loadGameState(slot); + + slc.close(); } Common::Error MohawkEngine_Riven::loadGameState(int slot) { diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 5fe0de00e9..3e2ab59597 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -128,7 +128,6 @@ private: MohawkArchive *_extrasFile; // We need a separate handle for the extra data RivenConsole *_console; RivenSaveLoad *_saveLoad; - GUI::SaveLoadChooser *_loadDialog; RivenOptionsDialog *_optionsDialog; // Stack/Card-related functions and variables -- cgit v1.2.3 From 146cc7cb3c3d00ce3d235c877d8e9e1e19434d9d Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 29 Jun 2010 03:00:53 +0000 Subject: Silence a valgrind warning. svn-id: r50478 --- engines/mohawk/riven.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 77559b67e4..82be6b291b 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -52,6 +52,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _activatedSLST = false; _ignoreNextMouseUp = false; _extrasFile = NULL; + _curStack = aspit; // TODO: Add support for CD swapping -- cgit v1.2.3 From 48a107b821c21867a3627ac0cb2d072041ddcc56 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Tue, 29 Jun 2010 03:04:08 +0000 Subject: Update comment on CD swapping in Riven. svn-id: r50479 --- engines/mohawk/riven.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 82be6b291b..81e33d6513 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -54,7 +54,11 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _extrasFile = NULL; _curStack = aspit; - // TODO: Add support for CD swapping + // NOTE: We can never really support CD swapping. All of the music files + // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive + // during install and used from there. The same goes for the extras.mhk + // file. The following directories allow Riven to be played directly + // from the DVD. const Common::FSNode gameDataDir(ConfMan.get("path")); SearchMan.addSubDirectoryMatching(gameDataDir, "all"); -- cgit v1.2.3 From 59f4c903a6fab1c60e925ce315fc077e1721eab0 Mon Sep 17 00:00:00 2001 From: David Turner Date: Tue, 29 Jun 2010 03:53:06 +0000 Subject: GOB : Adding workaround for Bug #3018918 UOTODDV Reload Goblin Stuck Issue. This was present in the original interpreter. svn-id: r50480 --- engines/gob/inter_v1.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) (limited to 'engines') diff --git a/engines/gob/inter_v1.cpp b/engines/gob/inter_v1.cpp index b35e0b8a82..9e841e7e68 100644 --- a/engines/gob/inter_v1.cpp +++ b/engines/gob/inter_v1.cpp @@ -813,6 +813,14 @@ bool Inter_v1::o1_if(OpFuncParams ¶ms) { byte cmd; bool boolRes; + // WORKAROUND: Windows Gob1 OUTODDV reload goblin stuck bug present in original + if ((_vm->getGameType() == kGameTypeGob1) && (_vm->_game->_script->pos() == 11294) && + !scumm_stricmp(_vm->_game->_curTotFile, "avt00.tot") && VAR(59) == 1) { + warning("Workaround for Win Gob1 OUTODDV Reload Goblin Stuck Bug..."); + WRITE_VAR(285, 0); + WRITE_VAR(59, 0); + } + boolRes = _vm->_game->_script->evalBoolResult(); if (boolRes) { if ((params.counter == params.cmdCount) && (params.retFlag == 2)) -- cgit v1.2.3 From 9f1320d5cc1d0892e0b3ea9812b6599125bd1c65 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 29 Jun 2010 09:00:08 +0000 Subject: SCI: Made the SoundCommandParser a member of the SciEngine class and removed it from the EngineState, since it's static throughout the course of a game svn-id: r50484 --- engines/sci/console.cpp | 20 ++++++++++---------- engines/sci/engine/kevent.cpp | 2 +- engines/sci/engine/ksound.cpp | 2 +- engines/sci/engine/savegame.cpp | 4 ++-- engines/sci/engine/state.cpp | 1 - engines/sci/engine/state.h | 1 - engines/sci/sci.cpp | 18 ++++++++---------- engines/sci/sci.h | 2 ++ 8 files changed, 24 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b30349dd5a..f9d2ac5090 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -219,8 +219,8 @@ void Console::preEnter() { if (_engine->_gamestate) _engine->_gamestate->_sound.sfx_suspend(true); #endif - if (_engine->_gamestate && _engine->_gamestate->_soundCmd) - _engine->_gamestate->_soundCmd->pauseAll(true); + if (g_sci && g_sci->_soundCmd) + g_sci->_soundCmd->pauseAll(true); } void Console::postEnter() { @@ -228,8 +228,8 @@ void Console::postEnter() { if (_engine->_gamestate) _engine->_gamestate->_sound.sfx_suspend(false); #endif - if (_engine->_gamestate && _engine->_gamestate->_soundCmd) - _engine->_gamestate->_soundCmd->pauseAll(false); + if (g_sci && g_sci->_soundCmd) + g_sci->_soundCmd->pauseAll(false); if (!_videoFile.empty()) { _engine->_gfxCursor->kernelHide(); @@ -1662,7 +1662,7 @@ bool Console::cmdSongLib(int argc, const char **argv) { } while (seeker); DebugPrintf("\n"); #else - _engine->_gamestate->_soundCmd->printPlayList(this); + g_sci->_soundCmd->printPlayList(this); #endif return true; @@ -1683,7 +1683,7 @@ bool Console::cmdSongInfo(int argc, const char **argv) { return true; } - _engine->_gamestate->_soundCmd->printSongInfo(addr, this); + g_sci->_soundCmd->printSongInfo(addr, this); return true; } @@ -1702,7 +1702,7 @@ bool Console::cmdStartSound(int argc, const char **argv) { return true; } - _engine->_gamestate->_soundCmd->startNewSound(number); + g_sci->_soundCmd->startNewSound(number); return false; } @@ -1743,9 +1743,9 @@ bool Console::cmdToggleSound(int argc, const char **argv) { newState.toLowercase(); if (newState == "play") - _engine->_gamestate->_soundCmd->playSound(id); + g_sci->_soundCmd->playSound(id); else if (newState == "stop") - _engine->_gamestate->_soundCmd->stopSound(id); + g_sci->_soundCmd->stopSound(id); else DebugPrintf("New state can either be 'play' or 'stop'"); #endif @@ -1755,7 +1755,7 @@ bool Console::cmdToggleSound(int argc, const char **argv) { bool Console::cmdStopAllSounds(int argc, const char **argv) { #ifndef USE_OLD_MUSIC_FUNCTIONS - _engine->_gamestate->_soundCmd->stopAllSounds(); + g_sci->_soundCmd->stopAllSounds(); #endif DebugPrintf("All sounds have been stopped\n"); diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index e38550adee..bc8ddc34fc 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -156,7 +156,7 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // like SCI01 and later do with cmdUpdateSoundCues. kGetEvent is called // quite often, so emulate the SCI01 behavior of cmdUpdateSoundCues with // this call - s->_soundCmd->updateSci0Cues(); + g_sci->_soundCmd->updateSci0Cues(); } #endif diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 0172b005ac..3d8869e89e 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -39,7 +39,7 @@ namespace Sci { * Used for synthesized music playback */ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { - return s->_soundCmd->parseCommand(argc, argv, s->r_acc); + return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc); } reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 7804265d0d..bf7b88b699 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -385,7 +385,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { #ifdef USE_OLD_MUSIC_FUNCTIONS sync_songlib(s, _sound._songlib); #else - _soundCmd->syncPlayList(s); + g_sci->_soundCmd->syncPlayList(s); #endif } @@ -978,7 +978,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->_sound._suspended = s->_sound._suspended; reconstruct_sounds(s); #else - s->_soundCmd->reconstructPlayList(meta.savegame_version); + g_sci->_soundCmd->reconstructPlayList(meta.savegame_version); #endif // Message state: diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 9bd8f380a1..f13a44e704 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -87,7 +87,6 @@ void EngineState::reset(bool isRestoring) { if (!isRestoring) { _memorySegmentSize = 0; - _soundCmd = 0; _fileHandles.resize(5); diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 2fcad5b2e4..07843a68e3 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -109,7 +109,6 @@ public: SfxState _sound; /**< sound subsystem */ int sfx_init_flags; /**< flags the sfx subsystem was initialised with */ #endif - SoundCommandParser *_soundCmd; uint32 gameStartTime; /**< The time at which the interpreter was started */ uint32 lastWaitTime; /**< The last time the game invoked Wait() */ diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 46d33eda78..e90ca9de5d 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -154,6 +154,7 @@ SciEngine::~SciEngine() { delete _gfxScreen; delete _audio; + delete _soundCmd; delete _kernel; delete _vocabulary; delete _console; @@ -161,7 +162,6 @@ SciEngine::~SciEngine() { delete _gfxMacIconBar; delete _eventMan; - delete _gamestate->_soundCmd; delete _gamestate->_segMan; delete _gamestate; delete _resMan; // should be deleted last @@ -216,16 +216,14 @@ Common::Error SciEngine::run() { return Common::kUnknownError; } - _kernel->loadKernelNames(_features); // Must be called after game_init() - script_adjust_opcode_formats(); - SciVersion soundVersion = _features->detectDoSoundType(); - - _gamestate->_soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, soundVersion); + // Must be called after game_init(), as they use _features + _kernel->loadKernelNames(_features); + _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType()); #ifdef USE_OLD_MUSIC_FUNCTIONS - initGameSound(0, soundVersion); + initGameSound(0, _features->detectDoSoundType()); #endif syncSoundSettings(); @@ -463,7 +461,7 @@ void SciEngine::exitGame() { initGameSound(SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType()); #else _audio->stopAllAudio(); - _gamestate->_soundCmd->clearPlayList(); + g_sci->_soundCmd->clearPlayList(); #endif } @@ -562,9 +560,9 @@ void SciEngine::syncSoundSettings() { int soundVolumeMusic = (mute ? 0 : ConfMan.getInt("music_volume")); - if (_gamestate && _gamestate->_soundCmd) { + if (_gamestate && g_sci->_soundCmd) { int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume; - _gamestate->_soundCmd->setMasterVolume(vol); + g_sci->_soundCmd->setMasterVolume(vol); } #endif } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index f60aad67a7..d7ca1345bf 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -52,6 +52,7 @@ class Kernel; class GameFeatures; class Console; class AudioPlayer; +class SoundCommandParser; class EventManager; class GfxAnimate; @@ -291,6 +292,7 @@ public: #endif AudioPlayer *_audio; + SoundCommandParser *_soundCmd; GameFeatures *_features; private: -- cgit v1.2.3 From 316e96df2b48b1986488bfd57db37b9708f3e4ca Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 29 Jun 2010 09:01:17 +0000 Subject: SCI: Removed reg_t_EqualTo, since reg_t already defines an equals operator svn-id: r50485 --- engines/sci/engine/gc.h | 8 +------- 1 file changed, 1 insertion(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index 9f9347ca18..cfae517790 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -33,12 +33,6 @@ namespace Sci { -struct reg_t_EqualTo { - bool operator()(const reg_t& x, const reg_t& y) const { - return (x.segment == y.segment) && (x.offset == y.offset); - } -}; - struct reg_t_Hash { uint operator()(const reg_t& x) const { return (x.segment << 3) | x.offset; @@ -48,7 +42,7 @@ struct reg_t_Hash { /* * The reg_t_hash_map is actually really a hashset */ -typedef Common::HashMap reg_t_hash_map; +typedef Common::HashMap reg_t_hash_map; /** * Finds all used references and normalises them to their memory addresses -- cgit v1.2.3 From 0b470dde636f4706a9f56c13364d87a76dd9ec86 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 29 Jun 2010 09:02:59 +0000 Subject: SCI: Some cleanup of the GC code. The version of push() that pushes arrays inside WorklistManager has been renamed to pushArray(), so that it's more apparent where arrays are pushed. svn-id: r50486 --- engines/sci/engine/gc.cpp | 30 ++++++++++++++---------------- 1 file changed, 14 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 3c8c1f17a8..3dd7acfa1c 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -45,7 +45,7 @@ struct WorklistManager { _worklist.push_back(reg); } - void push(const Common::Array &tmp) { + void pushArray(const Common::Array &tmp) { for (Common::Array::const_iterator it = tmp.begin(); it != tmp.end(); ++it) push(*it); } @@ -82,22 +82,19 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm.push(s->r_prev); // Init: Value Stack // We do this one by hand since the stack doesn't know the current execution stack - Common::List::iterator iter; - { - iter = s->_executionStack.reverse_begin(); + Common::List::iterator iter = s->_executionStack.reverse_begin(); - // Skip fake kernel stack frame if it's on top - if (((*iter).type == EXEC_STACK_TYPE_KERNEL)) - --iter; + // Skip fake kernel stack frame if it's on top + if (((*iter).type == EXEC_STACK_TYPE_KERNEL)) + --iter; - assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL)); + assert((iter != s->_executionStack.end()) && ((*iter).type != EXEC_STACK_TYPE_KERNEL)); - ExecStack &xs = *iter; - reg_t *pos; + ExecStack &xs = *iter; + reg_t *pos; - for (pos = s->stack_base; pos < xs.sp; pos++) - wm.push(*pos); - } + for (pos = s->stack_base; pos < xs.sp; pos++) + wm.push(*pos); debugC(2, kDebugLevelGC, "[GC] -- Finished adding value stack"); @@ -117,15 +114,16 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack"); // Init: Explicitly loaded scripts - for (i = 1; i < segMan->_heap.size(); i++) + for (i = 1; i < segMan->_heap.size(); i++) { if (segMan->_heap[i] && segMan->_heap[i]->getType() == SEG_TYPE_SCRIPT) { Script *script = (Script *)segMan->_heap[i]; if (script->getLockers()) { // Explicitly loaded? - wm.push(script->listObjectReferences()); + wm.pushArray(script->listObjectReferences()); } } + } debugC(2, kDebugLevelGC, "[GC] -- Finished explicitly loaded scripts, done with root set"); @@ -138,7 +136,7 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment]) { // Valid heap object? Find its outgoing references! - wm.push(segMan->_heap[reg.segment]->listAllOutgoingReferences(reg)); + wm.pushArray(segMan->_heap[reg.segment]->listAllOutgoingReferences(reg)); } } } -- cgit v1.2.3 From f75a6a6f479dbde58fc0e9778d4811ca9a05419f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 10:39:13 +0000 Subject: SCI: print out actual and supposed parameter types when having a kernel call signature mismatch svn-id: r50487 --- engines/sci/engine/kernel.cpp | 96 ++++++++++++++++++++++++++++++++++++------- engines/sci/engine/kernel.h | 3 ++ 2 files changed, 85 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 9bf0371a7a..75eadb9a64 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -669,40 +669,108 @@ int Kernel::findRegType(reg_t reg) { } } +struct SignatureDebugType { + char typeCheck; + const char *text; +}; + +static const SignatureDebugType signatureDebugTypeList[] = { + { KSIG_NULL, "null" }, + { KSIG_ARITHMETIC, "value" }, + { KSIG_OBJECT, "object" }, + { KSIG_REF, "reference" }, + { KSIG_LIST, "list" }, + { KSIG_NODE, "node" }, + { 0, NULL } +}; + +static void kernelSignatureDebugType(const char type) { + bool firstPrint = true; + + const SignatureDebugType *list = signatureDebugTypeList; + while (list->typeCheck) { + if (type & list->typeCheck) { + if (!firstPrint) + printf(", "); + printf("%s", list->text); + firstPrint = false; + } + list++; + } +} + +// Shows kernel call signature and current arguments for debugging purposes +void Kernel::signatureDebug(const char *sig, int argc, const reg_t *argv) { + int argnr = 0; + while (*sig || argc) { + printf("parameter %d: ", argnr++); + if (argc) { + reg_t parameter = *argv; + printf("%04x:%04x (", PRINT_REG(parameter)); + kernelSignatureDebugType(findRegType(parameter)); + printf(")"); + argv++; + argc--; + } else { + printf("not passed"); + } + if (*sig) { + const char signature = *sig; + if ((signature & KSIG_ANY) == KSIG_ANY) { + printf(", may be any"); + } else { + printf(", should be "); + kernelSignatureDebugType(signature); + } + if (signature & KSIG_ELLIPSIS) + printf(" (optional)"); + sig++; + } + printf("\n"); + } +} + bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { + const char *checkSig = sig; + const reg_t *checkParam = argv; + int checkCount = argc; // Always "match" if no signature is given if (!sig) return true; - while (*sig && argc) { - if ((*sig & KSIG_ANY) != KSIG_ANY) { - int type = findRegType(*argv); + while (*checkSig && checkCount) { + if ((*checkSig & KSIG_ANY) != KSIG_ANY) { + int type = findRegType(*checkParam); if (!type) { - warning("[KERN] Could not determine type of ref %04x:%04x; failing signature check", PRINT_REG(*argv)); + warning("[KERNEL] call signature: couldn't determine type of ref %04x:%04x", PRINT_REG(*argv)); + signatureDebug(sig, argc, argv); return false; } - if (!(type & *sig)) { - warning("kernel_matches_signature: %d args left, is %d, should be %d", argc, type, *sig); + if (!(type & *checkSig)) { + warning("[KERNEL] call signature: %d args left, is %d, should be %d", argc, type, *sig); + signatureDebug(sig, argc, argv); return false; } } - if (!(*sig & KSIG_ELLIPSIS)) - ++sig; - ++argv; - --argc; + if (!(*checkSig & KSIG_ELLIPSIS)) + ++checkSig; + ++checkParam; + --checkCount; } - if (argc) { - warning("kernel_matches_signature: too many arguments"); + if (checkCount) { + warning("[KERNEL] call signature: too many arguments"); + signatureDebug(sig, argc, argv); return false; // Too many arguments } - if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) + if (*checkSig == 0 || (*checkSig & KSIG_ELLIPSIS)) return true; - warning("kernel_matches_signature: too few arguments"); + warning("[KERNEL] call signature: too few arguments"); + signatureDebug(sig, argc, argv); return false; } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a347e90d1a..6f7b0d569d 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -169,6 +169,9 @@ public: */ bool signatureMatch(const char *sig, int argc, const reg_t *argv); + // Prints out debug information in case a signature check fails + void signatureDebug(const char *sig, int argc, const reg_t *argv); + /** * Determines the type of the object indicated by reg. * @param reg register to check -- cgit v1.2.3 From b91ba9c56ea0bad8ae194149bfb2b370c8f01a95 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 10:40:24 +0000 Subject: Bugfixes to reading in the animation font name correctly, as well as converted some Common::String usage to char buffers to fix incorrect String usage svn-id: r50488 --- engines/m4/animation.cpp | 40 +++++++++++++++++++++++++--------------- engines/m4/font.cpp | 25 ++++++++++++++++--------- engines/m4/font.h | 8 ++++---- 3 files changed, 45 insertions(+), 28 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 4dc645991e..192c096640 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -57,10 +57,10 @@ MadsAnimation::~MadsAnimation() { if (_field12) { _view->_spriteSlots.deleteSprites(_spriteListIndexes[_spriteListIndex]); } - - delete _font; } +#define FILENAME_SIZE 13 + /** * Initialises and loads the data of an animation */ @@ -93,25 +93,35 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S _scrollTicks = animStream->readUint16LE(); animStream->skip(8); - animStream->read(buffer, 13); - _interfaceFile = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _interfaceFile = Common::String(buffer); for (int i = 0; i < 10; ++i) { - animStream->read(buffer, 13); - _spriteSetNames[i] = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spriteSetNames[i] = Common::String(buffer); } animStream->skip(81); - animStream->read(buffer, 13); - _lbmFilename = Common::String(buffer, 13); - animStream->read(buffer, 13); - _spritesFilename = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _lbmFilename = Common::String(buffer); + + animStream->skip(365); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _spritesFilename = Common::String(buffer); + animStream->skip(48); - animStream->read(buffer, 13); - _soundName = Common::String(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _soundName = Common::String(buffer); + animStream->skip(26); - animStream->read(buffer, 13); - Common::String fontResource(buffer, 13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + Common::String fontResource(buffer); if (_animMode == 4) flags |= 0x4000; @@ -205,7 +215,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S fontName += fontResource; if (fontName != "") - _font = _vm->_font->getFont(fontName); + _font = _vm->_font->getFont(fontName.c_str()); else warning("Attempted to set a font with an empty name"); } diff --git a/engines/m4/font.cpp b/engines/m4/font.cpp index 4afa158976..b5965732e5 100644 --- a/engines/m4/font.cpp +++ b/engines/m4/font.cpp @@ -35,27 +35,34 @@ FontManager::~FontManager() { _entries.clear(); } -Font *FontManager::getFont(const Common::String &filename) { +Font *FontManager::getFont(const char *filename) { + // Append an extension if the filename doesn't already have one + char buffer[20]; + strncpy(buffer, filename, 19); + if (!strchr(buffer, '.')) + strcat(buffer, ".ff"); + // Check if the font is already loaded - for (uint i = 0; i < _entries.size(); ++i) - { - if (_entries[i]->_filename.equals(filename)) + for (uint i = 0; i < _entries.size(); ++i) { + if (!strcmp(_entries[i]->_filename, buffer)) return _entries[i]; } - Font *f = new Font(_vm, filename); + Font *f = new Font(_vm, buffer); _entries.push_back(f); return f; } -void FontManager::setFont(const Common::String &filename) { +void FontManager::setFont(const char *filename) { _currentFont = getFont(filename); } //-------------------------------------------------------------------------- -Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filename(filename) { +Font::Font(MadsM4Engine *vm, const char *filename) : _vm(vm) { _sysFont = true; + strncpy(_filename, filename, 19); + _filename[19] = '\0'; //TODO: System font _fontColors[0] = _vm->_palette->BLACK; @@ -66,9 +73,9 @@ Font::Font(MadsM4Engine *vm, const Common::String &filename) : _vm(vm), _filenam _sysFont = false; if (_vm->isM4()) - setFontM4(filename.c_str()); + setFontM4(filename); else - setFontMads(filename.c_str()); + setFontMads(filename); } void Font::setFontM4(const char *filename) { diff --git a/engines/m4/font.h b/engines/m4/font.h index ca47848c61..19d15faa1e 100644 --- a/engines/m4/font.h +++ b/engines/m4/font.h @@ -59,7 +59,7 @@ namespace M4 { class Font { public: - Font(MadsM4Engine *vm, const Common::String &filename); + Font(MadsM4Engine *vm, const char *filename); ~Font(); void setColour(uint8 colour); @@ -73,7 +73,7 @@ public: return write(surface, text, x, y, width, spaceWidth, _fontColors); } public: - const Common::String _filename; + char _filename[20]; private: void setFontM4(const char *filename); void setFontMads(const char *filename); @@ -108,8 +108,8 @@ public: FontManager(MadsM4Engine *vm): _vm(vm) { _currentFont = NULL; } ~FontManager(); - Font *getFont(const Common::String &filename); - void setFont(const Common::String &filename); + Font *getFont(const char *filename); + void setFont(const char *filename); Font *current() { assert(_currentFont); -- cgit v1.2.3 From eb4a48bfd99e97540d553ffd51eb5b24d9c05486 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 10:52:59 +0000 Subject: Reserved palette ranges used by on-screen messages svn-id: r50489 --- engines/m4/mads_anim.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index d8976241e1..b7aa8eefb5 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -466,6 +466,10 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): // Set up system palette colors _vm->_palette->setMadsSystemPalette(); + // Block reserved palette ranges + _vm->_palette->blockRange(16, 2); + _vm->_palette->blockRange(250, 4); + clear(); _backgroundSurface.clear(); -- cgit v1.2.3 From 841356ac80a869b199b65e169ee3aa361d657d37 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 11:09:33 +0000 Subject: Added loading of the correct DSR file at the start of each animation scene svn-id: r50490 --- engines/m4/animation.cpp | 10 +++++++++- engines/m4/animation.h | 1 + 2 files changed, 10 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 192c096640..28853938ae 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -118,7 +118,11 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S buffer[FILENAME_SIZE] = '\0'; _soundName = Common::String(buffer); - animStream->skip(26); + animStream->skip(13); + animStream->read(buffer, FILENAME_SIZE); + buffer[FILENAME_SIZE] = '\0'; + _dsrName = Common::String(buffer); + animStream->read(buffer, FILENAME_SIZE); buffer[FILENAME_SIZE] = '\0'; Common::String fontResource(buffer); @@ -220,6 +224,10 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S warning("Attempted to set a font with an empty name"); } + // If a speech file is specified, then load it + if (!_dsrName.empty()) + _vm->_sound->loadDSRFile(_dsrName.c_str()); + // Load all the sprite sets for the animation for (int i = 0; i < spriteListCount; ++i) { if (_field12 && (i == _spriteListIndex)) diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 135618d7e2..21fa411426 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -90,6 +90,7 @@ private: Common::String _lbmFilename; Common::String _spritesFilename; Common::String _soundName; + Common::String _dsrName; Common::Array _spriteListIndexes; int _currentFrame, _oldFrameEntry; -- cgit v1.2.3 From c1176498f146f01832bc4d98b477f4479302cd4f Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 11:15:21 +0000 Subject: Removed the old hardcoded calls to loadDSRFile svn-id: r50491 --- engines/m4/m4.cpp | 9 --------- engines/m4/mads_menus.cpp | 1 - 2 files changed, 10 deletions(-) (limited to 'engines') diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index f1506598d2..fc1caec883 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -568,15 +568,6 @@ Common::Error MadsEngine::run() { _viewManager->systemHotkeys().add(Common::KEYCODE_ESCAPE, &escapeHotkeyHandler); _viewManager->systemHotkeys().add(Common::KEYCODE_KP_MULTIPLY, &textviewHotkeyHandler); - // Load the general game SFX/voices - if (getGameType() == GType_RexNebular) { - _sound->loadDSRFile("rex009.dsr"); - } else if (getGameType() == GType_Phantom) { - _sound->loadDSRFile("phan009.dsr"); - } else if (getGameType() == GType_DragonSphere) { - _sound->loadDSRFile("drag009.dsr"); - } - uint32 nextFrame = g_system->getMillis(); while (!_events->quitFlag) { eventHandler(); diff --git a/engines/m4/mads_menus.cpp b/engines/m4/mads_menus.cpp index 0addfc57cb..d7d9cf4150 100644 --- a/engines/m4/mads_menus.cpp +++ b/engines/m4/mads_menus.cpp @@ -309,7 +309,6 @@ void RexMainMenuView::handleAction(MadsGameAction action) { return; case SHOW_INTRO: - vm->_sound->loadDSRFile("act002.dsr"); vm->_viewManager->showAnimView("@rexopen"); break; -- cgit v1.2.3 From 5f2c184e4ef2e5519645b699b5dafa27148c59f4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 11:26:48 +0000 Subject: Changed reading of sprite frame depths to signed bytes - this fixes the problem with the Slippery Pig not showing up in the landing scene in the intro sequence svn-id: r50492 --- engines/m4/animation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 28853938ae..51d3970e12 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -183,7 +183,7 @@ void MadsAnimation::initialise(const Common::String &filename, uint16 flags, M4S rec.spriteSlot.frameNumber = animStream->readUint16LE(); rec.spriteSlot.xp = animStream->readSint16LE(); rec.spriteSlot.yp = animStream->readSint16LE(); - rec.spriteSlot.depth = animStream->readByte(); + rec.spriteSlot.depth = animStream->readSByte(); rec.spriteSlot.scale = (int8)animStream->readByte(); _frameEntries.push_back(rec); -- cgit v1.2.3 From c96d44d928a2cb47e70e428b4e61bcf80ceda42b Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 29 Jun 2010 11:51:05 +0000 Subject: Added code to properly detect when an animation sequence is complete svn-id: r50493 --- engines/m4/mads_anim.cpp | 21 ++++++++++++++------- engines/m4/mads_anim.h | 1 + 2 files changed, 15 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index b7aa8eefb5..ebc684bec4 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -460,6 +460,7 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): _activeAnimation = NULL; _bgLoadFlag = true; _startFrame = -1; + _scriptDone = false; reset(); @@ -519,7 +520,7 @@ bool AnimviewView::onEvent(M4EventType eventType, int32 param, int x, int y, boo void AnimviewView::updateState() { MadsView::update(); - if (!_script) + if (!_script || _scriptDone) return; if (!_activeAnimation) { @@ -537,16 +538,16 @@ void AnimviewView::updateState() { _backgroundSurface.reset(); clearLists(); - // Check if script is finished - if (_script->eos() || _script->err()) { - scriptDone(); - return; - } - // Reset flags _startFrame = -1; readNextCommand(); + + // Check if script is finished + if (_scriptDone) { + scriptDone(); + return; + } } refresh(); @@ -589,6 +590,12 @@ static bool tempFlag = true;//****DEBUG - Temporarily allow me to skip several i break; } + if (!_currentLine[0]) { + // A blank line at this point means that the end of the animation has been reached + _scriptDone = true; + return; + } + if (strchr(_currentLine, '.') == NULL) strcat(_currentLine, ".aa"); diff --git a/engines/m4/mads_anim.h b/engines/m4/mads_anim.h index 78cc8727f8..b33ea24071 100644 --- a/engines/m4/mads_anim.h +++ b/engines/m4/mads_anim.h @@ -81,6 +81,7 @@ class AnimviewView : public View, MadsView { private: char _resourceName[80]; Common::SeekableReadStream *_script; + bool _scriptDone; uint32 _previousUpdate; char _currentLine[80]; M4Surface _backgroundSurface; -- cgit v1.2.3 From 32b69ccd9dc76f5d0750d23150fac5f5783134ca Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 14:54:15 +0000 Subject: SCI: Simplify GfxAnimate code, get rid of _listData svn-id: r50496 --- engines/sci/graphics/animate.cpp | 158 ++++++++++++++------------------------- engines/sci/graphics/animate.h | 11 +-- 2 files changed, 61 insertions(+), 108 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 25c0fe6432..d0103c9752 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -50,15 +50,10 @@ GfxAnimate::GfxAnimate(EngineState *state, GfxCache *cache, GfxPorts *ports, Gfx } GfxAnimate::~GfxAnimate() { - free(_listData); - free(_lastCastData); } void GfxAnimate::init() { - _listData = NULL; - _listCount = 0; - _lastCastData = NULL; - _lastCastCount = 0; + _lastCastData.clear(); _ignoreFastCast = false; // fastCast object is not found in any SCI games prior SCI1 @@ -73,7 +68,7 @@ void GfxAnimate::init() { } void GfxAnimate::disposeLastCast() { - _lastCastCount = 0; + _lastCastData.clear(); } bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { @@ -115,93 +110,64 @@ bool GfxAnimate::invoke(List *list, int argc, reg_t *argv) { return true; } -bool sortHelper(const AnimateEntry* entry1, const AnimateEntry* entry2) { - if (entry1->y == entry2->y) { +bool sortHelper(const AnimateEntry &entry1, const AnimateEntry &entry2) { + if (entry1.y == entry2.y) { // if both y and z are the same, use the order we were given originally // this is needed for special cases like iceman room 35 - if (entry1->z == entry2->z) - return entry1->givenOrderNo < entry2->givenOrderNo; + if (entry1.z == entry2.z) + return entry1.givenOrderNo < entry2.givenOrderNo; else - return entry1->z < entry2->z; + return entry1.z < entry2.z; } - return entry1->y < entry2->y; + return entry1.y < entry2.y; } void GfxAnimate::makeSortedList(List *list) { reg_t curAddress = list->first; Node *curNode = _s->_segMan->lookupNode(curAddress); - reg_t curObject; - AnimateEntry *listEntry; - int16 listNr, listCount = 0; - - // Count the list entries - while (curNode) { - listCount++; - curAddress = curNode->succ; - curNode = _s->_segMan->lookupNode(curAddress); - } + int16 listNr; + // Clear lists _list.clear(); - - // No entries -> exit immediately - if (listCount == 0) - return; - - // Adjust list size, if needed - if ((_listData == NULL) || (_listCount < listCount)) { - free(_listData); - _listData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry)); - if (!_listData) - error("Could not allocate memory for _listData"); - _listCount = listCount; - - free(_lastCastData); - _lastCastData = (AnimateEntry *)malloc(listCount * sizeof(AnimateEntry)); - if (!_lastCastData) - error("Could not allocate memory for _lastCastData"); - } - _lastCastCount = 0; + _lastCastData.clear(); // Fill the list - curAddress = list->first; - curNode = _s->_segMan->lookupNode(curAddress); - listEntry = _listData; - for (listNr = 0; listNr < listCount; listNr++) { - curObject = curNode->value; - listEntry->object = curObject; + for (listNr = 0; curNode != 0; listNr++) { + AnimateEntry listEntry; + const reg_t curObject = curNode->value; + listEntry.object = curObject; // Get data from current object - listEntry->givenOrderNo = listNr; - listEntry->viewId = readSelectorValue(_s->_segMan, curObject, SELECTOR(view)); - listEntry->loopNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(loop)); - listEntry->celNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(cel)); - listEntry->paletteNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(palette)); - listEntry->x = readSelectorValue(_s->_segMan, curObject, SELECTOR(x)); - listEntry->y = readSelectorValue(_s->_segMan, curObject, SELECTOR(y)); - listEntry->z = readSelectorValue(_s->_segMan, curObject, SELECTOR(z)); - listEntry->priority = readSelectorValue(_s->_segMan, curObject, SELECTOR(priority)); - listEntry->signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); + listEntry.givenOrderNo = listNr; + listEntry.viewId = readSelectorValue(_s->_segMan, curObject, SELECTOR(view)); + listEntry.loopNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(loop)); + listEntry.celNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(cel)); + listEntry.paletteNo = readSelectorValue(_s->_segMan, curObject, SELECTOR(palette)); + listEntry.x = readSelectorValue(_s->_segMan, curObject, SELECTOR(x)); + listEntry.y = readSelectorValue(_s->_segMan, curObject, SELECTOR(y)); + listEntry.z = readSelectorValue(_s->_segMan, curObject, SELECTOR(z)); + listEntry.priority = readSelectorValue(_s->_segMan, curObject, SELECTOR(priority)); + listEntry.signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if (getSciVersion() >= SCI_VERSION_1_1) { // Cel scaling - listEntry->scaleSignal = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleSignal)); - if (listEntry->scaleSignal & kScaleSignalDoScaling) { - listEntry->scaleX = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX)); - listEntry->scaleY = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY)); + listEntry.scaleSignal = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleSignal)); + if (listEntry.scaleSignal & kScaleSignalDoScaling) { + listEntry.scaleX = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX)); + listEntry.scaleY = readSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY)); } else { - listEntry->scaleX = 128; - listEntry->scaleY = 128; + listEntry.scaleX = 128; + listEntry.scaleY = 128; } } else { - listEntry->scaleSignal = 0; - listEntry->scaleX = 128; - listEntry->scaleY = 128; + listEntry.scaleSignal = 0; + listEntry.scaleX = 128; + listEntry.scaleY = 128; } - // listEntry->celRect is filled in AnimateFill() - listEntry->showBitsFlag = false; + // listEntry.celRect is filled in AnimateFill() + listEntry.showBitsFlag = false; _list.push_back(listEntry); - listEntry++; curAddress = curNode->succ; curNode = _s->_segMan->lookupNode(curAddress); } @@ -220,7 +186,7 @@ void GfxAnimate::fill(byte &old_picNotValid) { listIterator = _list.begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; // Get the corresponding view @@ -315,7 +281,7 @@ void GfxAnimate::update() { // Remove all no-update cels, if requested listIterator = _list.reverse_begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -344,7 +310,7 @@ void GfxAnimate::update() { // Draw always-update cels listIterator = listBegin; while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -367,7 +333,7 @@ void GfxAnimate::update() { // Saving background for all NoUpdate-cels listIterator = listBegin; while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -390,7 +356,7 @@ void GfxAnimate::update() { // Draw NoUpdate cels listIterator = listBegin; while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -412,16 +378,15 @@ void GfxAnimate::update() { void GfxAnimate::drawCels() { reg_t curObject; AnimateEntry *listEntry; - AnimateEntry *lastCastEntry = _lastCastData; uint16 signal; reg_t bitsHandle; AnimateList::iterator listIterator; AnimateList::iterator listEnd = _list.end(); - _lastCastCount = 0; + _lastCastData.clear(); listIterator = _list.begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -440,8 +405,7 @@ void GfxAnimate::drawCels() { listEntry->signal = signal; // Remember that entry in lastCast - memcpy(lastCastEntry, listEntry, sizeof(AnimateEntry)); - lastCastEntry++; _lastCastCount++; + _lastCastData.push_back(*listEntry); } listIterator++; } @@ -458,7 +422,7 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { listIterator = _list.begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -510,7 +474,7 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { // another object. In that case we would overwrite the new signal with our version of the old signal listIterator = _list.begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; signal = listEntry->signal; @@ -521,7 +485,7 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { listIterator = _list.reverse_begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; // We read out signal here again, this is not by accident but to ensure that we got an up-to-date signal signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); @@ -540,24 +504,18 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { } void GfxAnimate::reAnimate(Common::Rect rect) { - AnimateEntry *lastCastEntry; - uint16 lastCastCount; - - if (_lastCastCount > 0) { - lastCastEntry = _lastCastData; - lastCastCount = _lastCastCount; - while (lastCastCount > 0) { - lastCastEntry->castHandle = _paint16->bitsSave(lastCastEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); - _paint16->drawCel(lastCastEntry->viewId, lastCastEntry->loopNo, lastCastEntry->celNo, lastCastEntry->celRect, lastCastEntry->priority, lastCastEntry->paletteNo, lastCastEntry->scaleX, lastCastEntry->scaleY); - lastCastEntry++; lastCastCount--; + if (!_lastCastData.empty()) { + AnimateArray::iterator it; + AnimateArray::iterator end = _lastCastData.end(); + for (it = _lastCastData.begin(); it != end; ++it) { + it->castHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); } _paint16->bitsShow(rect); // restoring - lastCastCount = _lastCastCount; - while (lastCastCount > 0) { - lastCastEntry--; - _paint16->bitsRestore(lastCastEntry->castHandle); - lastCastCount--; + while (it != _lastCastData.begin()) { // FIXME: HACK, this iterator use is not very safe + it--; + _paint16->bitsRestore(it->castHandle); } } else { _paint16->bitsShow(rect); @@ -573,7 +531,7 @@ void GfxAnimate::addToPicDrawCels() { listIterator = _list.begin(); while (listIterator != listEnd) { - listEntry = *listIterator; + listEntry = &*listIterator; curObject = listEntry->object; if (listEntry->priority == -1) @@ -673,7 +631,7 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t updateScreen(old_picNotValid); restoreAndDelete(argc, argv); - if (getLastCastCount() > 1) + if (_lastCastData.size() > 1) _s->_throttleTrigger = true; _ports->setPort(oldPort); diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index a7d925c6e0..7e82187eed 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -73,7 +73,8 @@ struct AnimateEntry { bool showBitsFlag; reg_t castHandle; }; -typedef Common::List AnimateList; +typedef Common::List AnimateList; +typedef Common::Array AnimateArray; class GfxCache; class GfxCursor; @@ -102,8 +103,6 @@ public: void addToPicDrawCels(); void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); - uint16 getLastCastCount() { return _lastCastCount; } - virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv); virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv); virtual void kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); @@ -123,12 +122,8 @@ private: GfxCursor *_cursor; GfxTransitions *_transitions; - uint16 _listCount; - AnimateEntry *_listData; AnimateList _list; - - uint16 _lastCastCount; - AnimateEntry *_lastCastData; + AnimateArray _lastCastData; bool _ignoreFastCast; }; -- cgit v1.2.3 From c8dca083d825779eaecb3eccd04eaa4e2a914d0d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 14:54:31 +0000 Subject: SCI: Simplify List::iterator usage in GfxAnimate svn-id: r50497 --- engines/sci/graphics/animate.cpp | 92 ++++++++++++---------------------------- 1 file changed, 27 insertions(+), 65 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index d0103c9752..9f8e9ce7b9 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -178,15 +178,12 @@ void GfxAnimate::makeSortedList(List *list) { void GfxAnimate::fill(byte &old_picNotValid) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; GfxView *view = NULL; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; // Get the corresponding view @@ -263,25 +260,19 @@ void GfxAnimate::fill(byte &old_picNotValid) { signal &= ~kSignalForceUpdate; } listEntry->signal = signal; - - listIterator++; } } void GfxAnimate::update() { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; reg_t bitsHandle; Common::Rect rect; - AnimateList::iterator listIterator; - AnimateList::iterator listBegin = _list.begin(); - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); // Remove all no-update cels, if requested - listIterator = _list.reverse_begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.reverse_begin(); listEntry != end; --listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -304,13 +295,10 @@ void GfxAnimate::update() { signal |= kSignalNoUpdate; } listEntry->signal = signal; - listIterator--; } // Draw always-update cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -327,13 +315,10 @@ void GfxAnimate::update() { } listEntry->signal = signal; } - listIterator++; } // Saving background for all NoUpdate-cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -350,13 +335,10 @@ void GfxAnimate::update() { } listEntry->signal = signal; } - listIterator++; } // Draw NoUpdate cels - listIterator = listBegin; - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -371,22 +353,18 @@ void GfxAnimate::update() { _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } } - listIterator++; } } void GfxAnimate::drawCels() { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; reg_t bitsHandle; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); _lastCastData.clear(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -407,22 +385,18 @@ void GfxAnimate::drawCels() { // Remember that entry in lastCast _lastCastData.push_back(*listEntry); } - listIterator++; } } void GfxAnimate::updateScreen(byte oldPicNotValid) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); Common::Rect lsRect; Common::Rect workerRect; - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; @@ -455,8 +429,6 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { listEntry->signal |= kSignalRemoveView; } } - - listIterator++; } // use this for debug purposes // _screen->copyToScreen(); @@ -464,30 +436,26 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { reg_t curObject; - AnimateEntry *listEntry; uint16 signal; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); - // This has to be done in a separate loop. At least in sq1 some .dispose modifies FIXEDLOOP flag in signal for - // another object. In that case we would overwrite the new signal with our version of the old signal - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + // This has to be done in a separate loop. At least in sq1 some .dispose + // modifies FIXEDLOOP flag in signal for another object. In that case we + // would overwrite the new signal with our version of the old signal. + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; signal = listEntry->signal; // Finally update signal writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal); - listIterator++; } - listIterator = _list.reverse_begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.reverse_begin(); listEntry != end; --listEntry) { curObject = listEntry->object; - // We read out signal here again, this is not by accident but to ensure that we got an up-to-date signal + // We read out signal here again, this is not by accident but to ensure + // that we got an up-to-date signal signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); if ((signal & (kSignalNoUpdate | kSignalRemoveView)) == 0) { @@ -499,7 +467,6 @@ void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { // Call .delete_ method of that object invokeSelector(_s, curObject, SELECTOR(delete_), argc, argv, 0); } - listIterator--; } } @@ -524,14 +491,11 @@ void GfxAnimate::reAnimate(Common::Rect rect) { void GfxAnimate::addToPicDrawCels() { reg_t curObject; - AnimateEntry *listEntry; GfxView *view = NULL; - AnimateList::iterator listIterator; - AnimateList::iterator listEnd = _list.end(); + AnimateList::iterator listEntry; + const AnimateList::iterator end = _list.end(); - listIterator = _list.begin(); - while (listIterator != listEnd) { - listEntry = &*listIterator; + for (listEntry = _list.begin(); listEntry != end; ++listEntry) { curObject = listEntry->object; if (listEntry->priority == -1) @@ -549,8 +513,6 @@ void GfxAnimate::addToPicDrawCels() { listEntry->celRect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1); _paint16->fillRect(listEntry->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } - - listIterator++; } } -- cgit v1.2.3 From b743fcc9f5f7e6428ecfe9fea69dbcc70c523529 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 14:54:47 +0000 Subject: SCI: Rename listEntry -> 'it' for better readability svn-id: r50498 --- engines/sci/graphics/animate.cpp | 198 +++++++++++++++++++-------------------- 1 file changed, 99 insertions(+), 99 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index 9f8e9ce7b9..6fb427500d 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -180,71 +180,71 @@ void GfxAnimate::fill(byte &old_picNotValid) { reg_t curObject; uint16 signal; GfxView *view = NULL; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; // Get the corresponding view - view = _cache->getView(listEntry->viewId); + view = _cache->getView(it->viewId); // adjust loop and cel, if any of those is invalid - if (listEntry->loopNo >= view->getLoopCount()) { - listEntry->loopNo = 0; - writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), listEntry->loopNo); + if (it->loopNo >= view->getLoopCount()) { + it->loopNo = 0; + writeSelectorValue(_s->_segMan, curObject, SELECTOR(loop), it->loopNo); } - if (listEntry->celNo >= view->getCelCount(listEntry->loopNo)) { - listEntry->celNo = 0; - writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), listEntry->celNo); + if (it->celNo >= view->getCelCount(it->loopNo)) { + it->celNo = 0; + writeSelectorValue(_s->_segMan, curObject, SELECTOR(cel), it->celNo); } // Process global scaling, if needed - if (listEntry->scaleSignal & kScaleSignalDoScaling) { - if (listEntry->scaleSignal & kScaleSignalGlobalScaling) { + if (it->scaleSignal & kScaleSignalDoScaling) { + if (it->scaleSignal & kScaleSignalGlobalScaling) { // Global scaling uses global var 2 and some other stuff to calculate scaleX/scaleY int16 maxScale = readSelectorValue(_s->_segMan, curObject, SELECTOR(maxScale)); - int16 celHeight = view->getHeight(listEntry->loopNo, listEntry->celNo); + int16 celHeight = view->getHeight(it->loopNo, it->celNo); int16 maxCelHeight = (maxScale * celHeight) >> 7; reg_t globalVar2 = _s->variables[VAR_GLOBAL][2]; // current room object int16 vanishingY = readSelectorValue(_s->_segMan, globalVar2, SELECTOR(vanishingY)); int16 fixedPortY = _ports->getPort()->rect.bottom - vanishingY; - int16 fixedEntryY = listEntry->y - vanishingY; + int16 fixedEntryY = it->y - vanishingY; if (!fixedEntryY) fixedEntryY = 1; if ((celHeight == 0) || (fixedPortY == 0)) error("global scaling panic"); - listEntry->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY; - listEntry->scaleY = (listEntry->scaleY * 128) / celHeight; + it->scaleY = ( maxCelHeight * fixedEntryY ) / fixedPortY; + it->scaleY = (it->scaleY * 128) / celHeight; - listEntry->scaleX = listEntry->scaleY; + it->scaleX = it->scaleY; // and set objects scale selectors - writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), listEntry->scaleX); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), listEntry->scaleY); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleX), it->scaleX); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(scaleY), it->scaleY); } } // Create rect according to coordinates and given cel - if (listEntry->scaleSignal & kScaleSignalDoScaling) { - view->getCelScaledRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->scaleX, listEntry->scaleY, listEntry->celRect); + if (it->scaleSignal & kScaleSignalDoScaling) { + view->getCelScaledRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->scaleX, it->scaleY, it->celRect); } else { - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->celRect); + view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect); } - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), listEntry->celRect.left); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), listEntry->celRect.top); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), listEntry->celRect.right); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), listEntry->celRect.bottom); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsLeft), it->celRect.left); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsTop), it->celRect.top); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsRight), it->celRect.right); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(nsBottom), it->celRect.bottom); - signal = listEntry->signal; + signal = it->signal; // Calculate current priority according to y-coordinate if (!(signal & kSignalFixedPriority)) { - listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), listEntry->priority); + it->priority = _ports->kernelCoordinateToPriority(it->y); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(priority), it->priority); } if (signal & kSignalNoUpdate) { @@ -259,7 +259,7 @@ void GfxAnimate::fill(byte &old_picNotValid) { old_picNotValid++; signal &= ~kSignalForceUpdate; } - listEntry->signal = signal; + it->signal = signal; } } @@ -268,20 +268,20 @@ void GfxAnimate::update() { uint16 signal; reg_t bitsHandle; Common::Rect rect; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); // Remove all no-update cels, if requested - for (listEntry = _list.reverse_begin(); listEntry != end; --listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.reverse_begin(); it != end; --it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate) { if (!(signal & kSignalRemoveView)) { bitsHandle = readSelector(_s->_segMan, curObject, SELECTOR(underBits)); if (_screen->_picNotValid != 1) { _paint16->bitsRestore(bitsHandle); - listEntry->showBitsFlag = true; + it->showBitsFlag = true; } else { _paint16->bitsFree(bitsHandle); } @@ -294,33 +294,33 @@ void GfxAnimate::update() { signal &= ~kSignalStopUpdate; signal |= kSignalNoUpdate; } - listEntry->signal = signal; + it->signal = signal; } // Draw always-update cels - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalAlwaysUpdate) { // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; signal &= ~(kSignalStopUpdate | kSignalViewUpdated | kSignalNoUpdate | kSignalForceUpdate); if ((signal & kSignalIgnoreActor) == 0) { - rect = listEntry->celRect; - rect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + rect = it->celRect; + rect.top = CLIP(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1); _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } - listEntry->signal = signal; + it->signal = signal; } } // Saving background for all NoUpdate-cels - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate) { if (signal & kSignalHidden) { @@ -328,28 +328,28 @@ void GfxAnimate::update() { } else { signal &= ~kSignalRemoveView; if (signal & kSignalIgnoreActor) - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_VISUAL|GFX_SCREEN_MASK_PRIORITY); else - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL); writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle); } - listEntry->signal = signal; + it->signal = signal; } } // Draw NoUpdate cels - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (signal & kSignalNoUpdate && !(signal & kSignalHidden)) { // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; if (!(signal & kSignalIgnoreActor)) { - rect = listEntry->celRect; - rect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, rect.top, rect.bottom - 1); + rect = it->celRect; + rect.top = CLIP(_ports->kernelPriorityToCoordinate(it->priority) - 1, rect.top, rect.bottom - 1); _paint16->fillRect(rect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } } @@ -360,30 +360,30 @@ void GfxAnimate::drawCels() { reg_t curObject; uint16 signal; reg_t bitsHandle; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); _lastCastData.clear(); - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; if (!(signal & (kSignalNoUpdate | kSignalHidden | kSignalAlwaysUpdate))) { // Save background - bitsHandle = _paint16->bitsSave(listEntry->celRect, GFX_SCREEN_MASK_ALL); + bitsHandle = _paint16->bitsSave(it->celRect, GFX_SCREEN_MASK_ALL); writeSelector(_s->_segMan, curObject, SELECTOR(underBits), bitsHandle); // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo, listEntry->scaleX, listEntry->scaleY); - listEntry->showBitsFlag = true; + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo, it->scaleX, it->scaleY); + it->showBitsFlag = true; if (signal & kSignalRemoveView) { signal &= ~kSignalRemoveView; } - listEntry->signal = signal; + it->signal = signal; // Remember that entry in lastCast - _lastCastData.push_back(*listEntry); + _lastCastData.push_back(*it); } } } @@ -391,16 +391,16 @@ void GfxAnimate::drawCels() { void GfxAnimate::updateScreen(byte oldPicNotValid) { reg_t curObject; uint16 signal; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); Common::Rect lsRect; Common::Rect workerRect; - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; - if (listEntry->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) || + if (it->showBitsFlag || !(signal & (kSignalRemoveView | kSignalNoUpdate) || (!(signal & kSignalRemoveView) && (signal & kSignalNoUpdate) && oldPicNotValid))) { lsRect.left = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft)); lsRect.top = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop)); @@ -408,25 +408,25 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { lsRect.bottom = readSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom)); workerRect = lsRect; - workerRect.clip(listEntry->celRect); + workerRect.clip(it->celRect); if (!workerRect.isEmpty()) { workerRect = lsRect; - workerRect.extend(listEntry->celRect); + workerRect.extend(it->celRect); } else { _paint16->bitsShow(lsRect); - workerRect = listEntry->celRect; + workerRect = it->celRect; } - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), listEntry->celRect.left); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), listEntry->celRect.top); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), listEntry->celRect.right); - writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), listEntry->celRect.bottom); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsLeft), it->celRect.left); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsTop), it->celRect.top); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsRight), it->celRect.right); + writeSelectorValue(_s->_segMan, curObject, SELECTOR(lsBottom), it->celRect.bottom); // may get used for debugging //_paint16->frameRect(workerRect); _paint16->bitsShow(workerRect); if (signal & kSignalHidden) { - listEntry->signal |= kSignalRemoveView; + it->signal |= kSignalRemoveView; } } } @@ -437,23 +437,23 @@ void GfxAnimate::updateScreen(byte oldPicNotValid) { void GfxAnimate::restoreAndDelete(int argc, reg_t *argv) { reg_t curObject; uint16 signal; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); // This has to be done in a separate loop. At least in sq1 some .dispose // modifies FIXEDLOOP flag in signal for another object. In that case we // would overwrite the new signal with our version of the old signal. - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; - signal = listEntry->signal; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; + signal = it->signal; // Finally update signal writeSelectorValue(_s->_segMan, curObject, SELECTOR(signal), signal); } - for (listEntry = _list.reverse_begin(); listEntry != end; --listEntry) { - curObject = listEntry->object; + for (it = _list.reverse_begin(); it != end; --it) { + curObject = it->object; // We read out signal here again, this is not by accident but to ensure // that we got an up-to-date signal signal = readSelectorValue(_s->_segMan, curObject, SELECTOR(signal)); @@ -492,26 +492,26 @@ void GfxAnimate::reAnimate(Common::Rect rect) { void GfxAnimate::addToPicDrawCels() { reg_t curObject; GfxView *view = NULL; - AnimateList::iterator listEntry; + AnimateList::iterator it; const AnimateList::iterator end = _list.end(); - for (listEntry = _list.begin(); listEntry != end; ++listEntry) { - curObject = listEntry->object; + for (it = _list.begin(); it != end; ++it) { + curObject = it->object; - if (listEntry->priority == -1) - listEntry->priority = _ports->kernelCoordinateToPriority(listEntry->y); + if (it->priority == -1) + it->priority = _ports->kernelCoordinateToPriority(it->y); // Get the corresponding view - view = _cache->getView(listEntry->viewId); + view = _cache->getView(it->viewId); // Create rect according to coordinates and given cel - view->getCelRect(listEntry->loopNo, listEntry->celNo, listEntry->x, listEntry->y, listEntry->z, listEntry->celRect); + view->getCelRect(it->loopNo, it->celNo, it->x, it->y, it->z, it->celRect); // draw corresponding cel - _paint16->drawCel(listEntry->viewId, listEntry->loopNo, listEntry->celNo, listEntry->celRect, listEntry->priority, listEntry->paletteNo); - if ((listEntry->signal & kSignalIgnoreActor) == 0) { - listEntry->celRect.top = CLIP(_ports->kernelPriorityToCoordinate(listEntry->priority) - 1, listEntry->celRect.top, listEntry->celRect.bottom - 1); - _paint16->fillRect(listEntry->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); + _paint16->drawCel(it->viewId, it->loopNo, it->celNo, it->celRect, it->priority, it->paletteNo); + if ((it->signal & kSignalIgnoreActor) == 0) { + it->celRect.top = CLIP(_ports->kernelPriorityToCoordinate(it->priority) - 1, it->celRect.top, it->celRect.bottom - 1); + _paint16->fillRect(it->celRect, GFX_SCREEN_MASK_CONTROL, 0, 0, 15); } } } @@ -575,9 +575,9 @@ void GfxAnimate::kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t fill(old_picNotValid); if (old_picNotValid) { - // beginUpdate()/endUpdate() were introduced SCI1 - // calling those for SCI0 will work most of the time but breaks minor stuff like percentage bar of qfg1ega - // at the character skill screen + // beginUpdate()/endUpdate() were introduced SCI1. + // Calling those for SCI0 will work most of the time but breaks minor + // stuff like percentage bar of qfg1ega at the character skill screen. if (getSciVersion() >= SCI_VERSION_1_EGA) _ports->beginUpdate(_ports->_picWind); update(); -- cgit v1.2.3 From 1027f870a6d78bfbbf151ca0e65cd915676792b2 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 14:55:09 +0000 Subject: SCI: Add some const qualifiers svn-id: r50499 --- engines/sci/graphics/paint16.cpp | 22 +++++++++++----------- engines/sci/graphics/paint16.h | 22 +++++++++++----------- 2 files changed, 22 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index c2e8d2c5d0..9f286b1fda 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -107,12 +107,12 @@ void GfxPaint16::drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, } // This version of drawCel is not supposed to call BitsShow()! -void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { +void GfxPaint16::drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { drawCel(_cache->getView(viewId), loopNo, celNo, celRect, priority, paletteNo, scaleX, scaleY); } // This version of drawCel is not supposed to call BitsShow()! -void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { +void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX, uint16 scaleY) { Common::Rect clipRect = celRect; clipRect.clip(_ports->_curPort->rect); if (clipRect.isEmpty()) // nothing to draw @@ -389,19 +389,19 @@ void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, } } -void GfxPaint16::kernelGraphFillBoxForeground(Common::Rect rect) { +void GfxPaint16::kernelGraphFillBoxForeground(const Common::Rect &rect) { paintRect(rect); } -void GfxPaint16::kernelGraphFillBoxBackground(Common::Rect rect) { +void GfxPaint16::kernelGraphFillBoxBackground(const Common::Rect &rect) { eraseRect(rect); } -void GfxPaint16::kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control) { +void GfxPaint16::kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control) { fillRect(rect, colorMask, color, priority, control); } -void GfxPaint16::kernelGraphFrameBox(Common::Rect rect, int16 color) { +void GfxPaint16::kernelGraphFrameBox(const Common::Rect &rect, int16 color) { int16 oldColor = _ports->getPort()->penClr; _ports->penColor(color); frameRect(rect); @@ -413,11 +413,11 @@ void GfxPaint16::kernelGraphDrawLine(Common::Point startPoint, Common::Point end _screen->drawLine(startPoint.x, startPoint.y, endPoint.x, endPoint.y, color, priority, control); } -reg_t GfxPaint16::kernelGraphSaveBox(Common::Rect rect, uint16 screenMask) { +reg_t GfxPaint16::kernelGraphSaveBox(const Common::Rect &rect, uint16 screenMask) { return bitsSave(rect, screenMask); } -reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(Common::Rect rect) { +reg_t GfxPaint16::kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect) { return bitsSave(rect, GFX_SCREEN_MASK_DISPLAY); } @@ -425,7 +425,7 @@ void GfxPaint16::kernelGraphRestoreBox(reg_t handle) { bitsRestore(handle); } -void GfxPaint16::kernelGraphUpdateBox(Common::Rect rect, bool hiresMode) { +void GfxPaint16::kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode) { // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) bitsShow(rect); @@ -597,12 +597,12 @@ void GfxPaint16::kernelShakeScreen(uint16 shakeCount, uint16 directions) { } } -reg_t GfxPaint16::kernelPortraitLoad(Common::String resourceName) { +reg_t GfxPaint16::kernelPortraitLoad(const Common::String &resourceName) { //Portrait *myPortrait = new Portrait(g_sci->getResMan(), _screen, _palette, resourceName); return NULL_REG; } -void GfxPaint16::kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { +void GfxPaint16::kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceId, uint16 noun, uint16 verb, uint16 cond, uint16 seq) { Portrait *myPortrait = new Portrait(g_sci->getResMan(), g_sci->getEventManager(), _screen, _palette, _audio, resourceName); // TODO: cache portraits // adjust given coordinates to curPort (but dont adjust coordinates on upscaledHires_Save_Box and give us hires coordinates diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index f54b8059c1..4c3ac255c4 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -53,8 +53,8 @@ public: void drawPicture(GuiResourceId pictureId, int16 animationNr, bool mirroredFlag, bool addToFlag, GuiResourceId paletteId); void drawCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); - void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); - void drawCel(GfxView *view, int16 loopNo, int16 celNo, Common::Rect celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); + void drawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); + void drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common::Rect &celRect, byte priority, uint16 paletteNo, uint16 scaleX = 128, uint16 scaleY = 128); void drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX = 128, uint16 scaleY = 128); void clearScreen(byte color = 255); @@ -75,23 +75,23 @@ public: void kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, bool animationBlackoutFlag, bool mirroredFlag, bool addToFlag, int16 EGApaletteNo); void kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle); - void kernelGraphFillBoxForeground(Common::Rect rect); - void kernelGraphFillBoxBackground(Common::Rect rect); - void kernelGraphFillBox(Common::Rect rect, uint16 colorMask, int16 color, int16 priority, int16 control); - void kernelGraphFrameBox(Common::Rect rect, int16 color); + void kernelGraphFillBoxForeground(const Common::Rect &rect); + void kernelGraphFillBoxBackground(const Common::Rect &rect); + void kernelGraphFillBox(const Common::Rect &rect, uint16 colorMask, int16 color, int16 priority, int16 control); + void kernelGraphFrameBox(const Common::Rect &rect, int16 color); void kernelGraphDrawLine(Common::Point startPoint, Common::Point endPoint, int16 color, int16 priority, int16 control); - reg_t kernelGraphSaveBox(Common::Rect rect, uint16 flags); - reg_t kernelGraphSaveUpscaledHiresBox(Common::Rect rect); + reg_t kernelGraphSaveBox(const Common::Rect &rect, uint16 flags); + reg_t kernelGraphSaveUpscaledHiresBox(const Common::Rect &rect); void kernelGraphRestoreBox(reg_t handle); - void kernelGraphUpdateBox(Common::Rect rect, bool hiresMode); + void kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode); void kernelGraphRedrawBox(Common::Rect rect); reg_t kernelDisplay(const char *text, int argc, reg_t *argv); void kernelShakeScreen(uint16 shakeCount, uint16 directions); - reg_t kernelPortraitLoad(Common::String resourceName); - void kernelPortraitShow(Common::String resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); + reg_t kernelPortraitLoad(const Common::String &resourceName); + void kernelPortraitShow(const Common::String &resourceName, Common::Point position, uint16 resourceNum, uint16 noun, uint16 verb, uint16 cond, uint16 seq); void kernelPortraitUnload(uint16 portraitId); private: -- cgit v1.2.3 From 8db0f726c0253300faf8b9691607715fdaa45920 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 14:55:32 +0000 Subject: SCI: Rewrap more comments svn-id: r50500 --- engines/sci/graphics/cursor.cpp | 3 ++- engines/sci/graphics/menu.cpp | 48 ++++++++++++++++++++++-------------- engines/sci/graphics/paint16.cpp | 42 +++++++++++++++++++------------ engines/sci/graphics/screen.cpp | 14 ++++++----- engines/sci/graphics/text16.cpp | 37 ++++++++++++++++----------- engines/sci/graphics/transitions.cpp | 48 ++++++++++++++++++++++-------------- 6 files changed, 116 insertions(+), 76 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 20472d14c4..23c41c4c87 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -174,7 +174,8 @@ void GfxCursor::kernelSetView(GuiResourceId viewNum, int loopNum, int celNum, Co // Compute hotspot from xoffset/yoffset cursorHotspot = new Common::Point((celInfo->width >> 1) - celInfo->displaceX, celInfo->height - celInfo->displaceY - 1); - // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the user. Some scalers don't seem to support this + // Eco Quest 1 uses a 1x1 transparent cursor to hide the cursor from the + // user. Some scalers don't seem to support this if (width < 2 || height < 2) { kernelHide(); delete cursorHotspot; diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index 323539573b..d85d4456fc 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -63,8 +63,9 @@ void GfxMenu::reset() { _itemList.clear(); _listCount = 0; - // We actually set active item in here and remember last selection of the user - // sierra sci always defaulted to first item every time menu was called via ESC, we dont follow that logic + // We actually set active item in here and remember last selection of the + // user. Sierra SCI always defaulted to first item every time menu was + // called via ESC, we don't follow that logic. _curMenuId = 1; _curItemId = 1; } @@ -92,15 +93,16 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t beginPos = curPos; - // Now go through the content till we find end-marker and collect data about it - // ':' is an end-marker for each item + // Now go through the content till we find end-marker and collect data about it. + // ':' is an end-marker for each item. tagPos = 0; rightAlignedPos = 0; controlPos = 0; altPos = 0; functionPos = 0; while ((curPos < contentSize) && (content[curPos] != ':')) { switch (content[curPos]) { case '=': // Set tag - // Special case for normal animation speed - they use right aligned "=" for that one, so we ignore it - // as being recognized as tag marker + // Special case for normal animation speed - they use right + // aligned "=" for that one, so we ignore it as being recognized + // as tag marker. if (rightAlignedPos == curPos - 1) break; if (tagPos) @@ -199,8 +201,9 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t if (separatorCount == tempPos - beginPos) { itemEntry->separatorLine = true; } else { - // we don't strSplit here, because multilingual SCI01 support language switching on the fly, so we have to do - // this everytime the menu is called + // We don't strSplit here, because multilingual SCI01 support + // language switching on the fly, so we have to do this everytime + // the menu is called. itemEntry->text = Common::String(content.c_str() + beginPos, tempPos - beginPos); // LSL6 uses "Ctrl-" prefix string instead of ^ like all the other games do @@ -222,10 +225,12 @@ void GfxMenu::kernelAddEntry(Common::String title, Common::String content, reg_t if (tagPos && tagPos >= rightAlignedPos) tempPos = tagPos; itemEntry->textRightAligned = Common::String(content.c_str() + rightAlignedPos, tempPos - rightAlignedPos); - // Remove ending space, if there is one. Strangely sometimes there are lone spaces at the end in some games + // Remove ending space, if there is one. Strangely sometimes there + // are lone spaces at the end in some games if (itemEntry->textRightAligned.hasSuffix(" ")) itemEntry->textRightAligned.deleteLastChar(); - // - and + are used sometimes for volume control/animation speed, = sometimes for animation speed + // - and + are used sometimes for volume control/animation speed, + // = sometimes for animation speed if (itemEntry->textRightAligned == "-") { itemEntry->keyPress = '-'; } else if (itemEntry->textRightAligned == "+") { @@ -392,7 +397,8 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case SCI_EVENT_KEYBOARD: keyPress = readSelectorValue(_segMan, eventObject, SELECTOR(message)); keyModifier = readSelectorValue(_segMan, eventObject, SELECTOR(modifiers)); - // If tab got pressed, handle it here as if it was Ctrl-I - at least sci0 also did it that way + // If tab got pressed, handle it here as if it was Ctrl-I - at least + // sci0 also did it that way if (keyPress == SCI_KEY_TAB) { keyModifier = SCI_KEYMOD_CTRL; keyPress = 'i'; @@ -562,7 +568,8 @@ void GfxMenu::drawMenu(uint16 oldMenuId, uint16 newMenuId) { if (!maxTextRightAlignedWidth) _menuRect.right -= 5; - // if part of menu window is outside the screen, move it into the screen (this happens in multilingual sq3 and lsl3) + // If part of menu window is outside the screen, move it into the screen + // (this happens in multilingual sq3 and lsl3). if (_menuRect.right > _screen->getWidth()) { _menuRect.translate(-(_menuRect.right - _screen->getWidth()), 0); } @@ -689,8 +696,9 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { GuiMenuItemEntry *newItemEntry = curItemEntry; Common::Point mousePosition; - // We don't 100% follow sierra here: we select last item instead of selecting first item of first menu everytime - // Also sierra sci didnt allow mouse interaction, when menu was activated via keyboard + // We don't 100% follow Sierra here: we select last item instead of + // selecting first item of first menu every time. Also sierra sci didn't + // allow mouse interaction, when menu was activated via keyboard. calculateMenuAndItemWidth(); _oldPort = _ports->setPort(_ports->_menuPort); @@ -710,8 +718,9 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { switch (curEvent.type) { case SCI_EVENT_KEYBOARD: - // We don't 100% follow sierra here: - sierra didn't wrap around when changing item id - // - sierra allowed item id to be 0, which didnt make any sense + // We don't 100% follow sierra here: + // - sierra didn't wrap around when changing item id + // - sierra allowed item id to be 0, which didn't make any sense do { switch (curEvent.data) { case SCI_KEY_ESC: @@ -802,9 +811,10 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { } } -// Mouse button is currently pressed - we are now interpreting mouse coordinates till mouse button is released -// The menu item that is selected at that time is chosen. If no menu item is selected we cancel -// No keyboard interaction is allowed, cause that wouldnt make any sense at all +// Mouse button is currently pressed - we are now interpreting mouse coordinates +// till mouse button is released. The menu item that is selected at that time is +// chosen. If no menu item is selected we cancel. No keyboard interaction is +// allowed, cause that wouldnt make any sense at all. GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { SciEvent curEvent; uint16 newMenuId = 0, newItemId = 0; diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 9f286b1fda..48967c6888 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -127,8 +127,8 @@ void GfxPaint16::drawCel(GfxView *view, int16 loopNo, int16 celNo, const Common: } } -// This is used as replacement for drawCelAndShow() when hires-cels are drawn to screen -// Hires-cels are available only SCI 1.1+ +// This is used as replacement for drawCelAndShow() when hires-cels are drawn to +// screen. Hires-cels are available only SCI 1.1+. void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, byte priority, uint16 paletteNo, reg_t upscaledHiresHandle, uint16 scaleX, uint16 scaleY) { GfxView *view = _cache->getView(viewId); Common::Rect celRect, curPortRect, clipRect, clipRectTranslated; @@ -137,9 +137,10 @@ void GfxPaint16::drawHiresCelAndShow(GuiResourceId viewId, int16 loopNo, int16 c if (view) { if ((leftPos == 0) && (topPos == 0)) { - // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we need to get coordinates from upscaledHiresHandle - // I'm not sure if this is what we are supposed to do or if there is some other bug that actually makes - // coordinates to be 0 in the first place + // HACK: in kq6, we get leftPos&topPos == 0 SOMETIMES, that's why we + // need to get coordinates from upscaledHiresHandle. I'm not sure if + // this is what we are supposed to do or if there is some other bug + // that actually makes coordinates to be 0 in the first place. byte *memoryPtr = NULL; memoryPtr = _segMan->getHunkPointer(upscaledHiresHandle); if (memoryPtr) { @@ -381,7 +382,8 @@ void GfxPaint16::kernelDrawPicture(GuiResourceId pictureId, int16 animationNr, b } void GfxPaint16::kernelDrawCel(GuiResourceId viewId, int16 loopNo, int16 celNo, uint16 leftPos, uint16 topPos, int16 priority, uint16 paletteNo, bool hiresMode, reg_t upscaledHiresHandle) { - // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here + // some calls are hiresMode even under kq6 DOS, that's why we check for + // upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) { drawCelAndShow(viewId, loopNo, celNo, leftPos, topPos, priority, paletteNo); } else { @@ -426,7 +428,8 @@ void GfxPaint16::kernelGraphRestoreBox(reg_t handle) { } void GfxPaint16::kernelGraphUpdateBox(const Common::Rect &rect, bool hiresMode) { - // some calls are hiresMode even under kq6 DOS, that's why we check for upscaled hires here + // some calls are hiresMode even under kq6 DOS, that's why we check for + // upscaled hires here if ((!hiresMode) || (!_screen->getUpscaledHires())) bitsShow(rect); else @@ -466,7 +469,8 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { Common::Rect rect; reg_t result = NULL_REG; - // Make a "backup" of the port settings (required for some SCI0LATE and SCI01+ only) + // Make a "backup" of the port settings (required for some SCI0LATE and + // SCI01+ only) Port oldPort = *_ports->getPort(); // setting defaults @@ -565,14 +569,20 @@ reg_t GfxPaint16::kernelDisplay(const char *text, int argc, reg_t *argv) { uint16 tTop = currport->curTop; uint16 tLeft = currport->curLeft; if (!g_sci->_features->usesOldGfxFunctions()) { - // Restore port settings for some SCI0LATE and SCI01+ only - // the change actually happened inbetween .530 (hoyle1) and .566 (heros quest). We don't have any detection for - // that currently, so we are using oldGfxFunctions (.502). The only games that could get regressions because of - // this are hoyle1, kq4 and funseeker. If there are regressions, we should use interpreter version (which would - // require exe version detection) - // If we restore the port for whole SCI0LATE, at least sq3old will get an issue - font 0 will get used when - // scanning for planets instead of font 600 - a setfont parameter is missing in one of the kDisplay calls in - // script 19. I assume this is a script bug, because it was added in sq3new. + // Restore port settings for some SCI0LATE and SCI01+ only. + // + // The change actually happened inbetween .530 (hoyle1) and .566 (heros + // quest). We don't have any detection for that currently, so we are + // using oldGfxFunctions (.502). The only games that could get + // regressions because of this are hoyle1, kq4 and funseeker. If there + // are regressions, we should use interpreter version (which would + // require exe version detection). + // + // If we restore the port for whole SCI0LATE, at least sq3old will get + // an issue - font 0 will get used when scanning for planets instead of + // font 600 - a setfont parameter is missing in one of the kDisplay + // calls in script 19. I assume this is a script bug, because it was + // added in sq3new. *currport = oldPort; } currport->curTop = tTop; diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index eee6898a23..053372bdac 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -40,9 +40,10 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { // Scale the screen, if needed _upscaledHires = GFX_SCREEN_UPSCALED_DISABLED; - // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able to provide that under DOS as well, but as - // gk1/floppy does support upscaled hires scriptswise, but doesn't actually have the hires content we need to limit - // it to platform windows. + // King's Quest 6 and Gabriel Knight 1 have hires content, gk1/cd was able + // to provide that under DOS as well, but as gk1/floppy does support + // upscaled hires scriptswise, but doesn't actually have the hires content + // we need to limit it to platform windows. if (g_sci->getPlatform() == Common::kPlatformWindows) { if (g_sci->getGameId() == GID_KQ6) _upscaledHires = GFX_SCREEN_UPSCALED_640x440; @@ -60,7 +61,7 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _height = 200; } - // Japanese versions of games use hi-res font on upscaled version of the game + // Japanese versions of games use hi-res font on upscaled version of the game. if ((g_sci->getLanguage() == Common::JA_JPN) && (getSciVersion() <= SCI_VERSION_1_1)) _upscaledHires = GFX_SCREEN_UPSCALED_640x400; @@ -106,8 +107,9 @@ GfxScreen::GfxScreen(ResourceManager *resMan) : _resMan(resMan) { _unditherState = true; if (_resMan->isVGA() || (_resMan->isAmiga32color())) { - // It is not 100% accurate to set white to be 255 for Amiga 32-color games. - // But 255 is defined as white in our SCI at all times, so it doesn't matter. + // It is not 100% accurate to set white to be 255 for Amiga 32-color + // games. But 255 is defined as white in our SCI at all times, so it + // doesn't matter. _colorWhite = 255; if (getSciVersion() >= SCI_VERSION_1_1) _colorDefaultVectorData = 255; diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp index e9adac9572..4aa2346aed 100644 --- a/engines/sci/graphics/text16.cpp +++ b/engines/sci/graphics/text16.cpp @@ -84,10 +84,10 @@ void GfxText16::ClearChar(int16 chr) { _paint16->eraseRect(rect); } -// This internal function gets called as soon as a '|' is found in a text -// It will process the encountered code and set new font/set color -// We only support one-digit codes currently, don't know if multi-digit codes are possible -// Returns textcode character count +// This internal function gets called as soon as a '|' is found in a text. It +// will process the encountered code and set new font/set color. We only support +// one-digit codes currently, don't know if multi-digit codes are possible. +// Returns textcode character count. int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int16 orgPenColor) { const char *textCode = text; int16 textCodeSize = 0; @@ -133,9 +133,11 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1 static const uint16 text16_punctuationSjis[] = { 0x9F82, 0xA182, 0xA382, 0xA582, 0xA782, 0xC182, 0xA782, 0xC182, 0xE182, 0xE382, 0xE582, 0xEC82, 0x4083, 0x4283, 0x4483, 0x4683, 0x4883, 0x6283, 0x8383, 0x8583, 0x8783, 0x8E83, 0x9583, 0x9683, - 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0 }; + 0x5B81, 0x4181, 0x4281, 0x7681, 0x7881, 0x4981, 0x4881, 0 +}; -// return max # of chars to fit maxwidth with full words, does not include breaking space +// return max # of chars to fit maxwidth with full words, does not include +// breaking space int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgFontId) { uint16 curChar = 0; int16 maxChars = 0, curCharCount = 0; @@ -195,9 +197,10 @@ int16 GfxText16::GetLongest(const char *text, int16 maxWidth, GuiResourceId orgF uint16 nextChar; - // we remove the last char only, if maxWidth was actually equal width before adding the last char - // otherwise we won't get the same cutting as in sierra pc98 sci - // note: changing the while() instead will NOT WORK. it would break all sorts of regular sci games + // We remove the last char only, if maxWidth was actually equal width + // before adding the last char. Otherwise we won't get the same cutting + // as in sierra pc98 sci. Note: changing the while() instead will NOT + // WORK. it would break all sorts of regular sci games. if (maxWidth == (width - _font->getCharWidth(curChar))) { maxChars--; if (curChar > 0xFF) @@ -431,11 +434,14 @@ void GfxText16::Box(const char *text, int16 bshow, const Common::Rect &rect, Tex _ports->penColor(orgPenColor); if (doubleByteMode) { - // kanji is written by pc98 rom to screen directly. Because of GetLongest() behaviour (not cutting off the last - // char, that causes a new line), results in the script thinking that the text would need less space. The coordinate - // adjustment in fontsjis.cpp handles the incorrect centering because of that and this code actually shows all of - // the chars - if we don't do this, the scripts will only show most of the chars, but the last few pixels won't get - // shown most of the time. + // Kanji is written by pc98 rom to screen directly. Because of + // GetLongest() behaviour (not cutting off the last char, that causes a + // new line), results in the script thinking that the text would need + // less space. The coordinate adjustment in fontsjis.cpp handles the + // incorrect centering because of that and this code actually shows all + // of the chars - if we don't do this, the scripts will only show most + // of the chars, but the last few pixels won't get shown most of the + // time. Common::Rect kanjiRect = rect; _ports->offsetRect(kanjiRect); kanjiRect.left &= 0xFFC; @@ -456,7 +462,8 @@ void GfxText16::Draw_String(const char *text) { _ports->penColor(orgPenColor); } -// Sierra did this in their PC98 interpreter only, they identify a text as being sjis and then switch to font 900 +// Sierra did this in their PC98 interpreter only, they identify a text as being +// sjis and then switch to font 900 bool GfxText16::SwitchToFont900OnSjis(const char *text) { byte firstChar = (*(const byte *)text++); if (((firstChar >= 0x81) && (firstChar <= 0x9F)) || ((firstChar >= 0xE0) && (firstChar <= 0xEF))) { diff --git a/engines/sci/graphics/transitions.cpp b/engines/sci/graphics/transitions.cpp index 27cda249d0..c1f626449f 100644 --- a/engines/sci/graphics/transitions.cpp +++ b/engines/sci/graphics/transitions.cpp @@ -158,7 +158,8 @@ void GfxTransitions::doit(Common::Rect picRect) { } if (_blackoutFlag) { - // We need to find out what transition we are supposed to use for blackout + // We need to find out what transition we are supposed to use for + // blackout translationEntry = translateNumber(_number, blackoutTransitionIDs); if (translationEntry) { doTransition(translationEntry->newId, true); @@ -174,7 +175,8 @@ void GfxTransitions::doit(Common::Rect picRect) { if (picRect.bottom != _screen->getHeight()) { // TODO: this is a workaround for lsl6 not showing menubar when playing - // There is some new code in the sierra sci in ShowPic that seems to do something similar to this + // There is some new code in the sierra sci in ShowPic that seems to do + // something similar to this _screen->copyToScreen(); g_system->updateScreen(); } @@ -182,8 +184,8 @@ void GfxTransitions::doit(Common::Rect picRect) { _screen->_picNotValid = 0; } -// This may get called twice, if blackoutFlag is set. It will get once called with blackoutFlag set and another time -// with no blackoutFlag. +// This may get called twice, if blackoutFlag is set. It will get once called +// with blackoutFlag set and another time with no blackoutFlag. void GfxTransitions::doTransition(int16 number, bool blackoutFlag) { if (number != SCI_TRANSITIONS_FADEPALETTE) { setNewPalette(blackoutFlag); @@ -278,7 +280,8 @@ void GfxTransitions::copyRectToScreen(const Common::Rect rect, bool blackoutFlag } } -// Note: dont do too many steps in here, otherwise cpu will crap out because of the load +// Note: don't do too many steps in here, otherwise cpu will crap out because of +// the load void GfxTransitions::fadeOut() { byte oldPalette[4 * 256], workPalette[4 * 256]; int16 stepNr, colorNr; @@ -296,7 +299,8 @@ void GfxTransitions::fadeOut() { } } -// Note: dont do too many steps in here, otherwise cpu will crap out because of the load +// Note: don't do too many steps in here, otherwise cpu will crap out because of +// the load void GfxTransitions::fadeIn() { int16 stepNr; @@ -306,9 +310,9 @@ void GfxTransitions::fadeIn() { } } -// pixelates the new picture over the old one - works against the whole screen +// Pixelates the new picture over the old one - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible -void GfxTransitions::pixelation (bool blackoutFlag) { +void GfxTransitions::pixelation(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; Common::Rect pixelRect; @@ -328,7 +332,7 @@ void GfxTransitions::pixelation (bool blackoutFlag) { } while (mask != 0x40); } -// like pixelation but uses 8x8 blocks - works against the whole screen +// Like pixelation but uses 8x8 blocks - works against the whole screen. // TODO: it seems this needs to get applied on _picRect only if possible void GfxTransitions::blocks(bool blackoutFlag) { uint16 mask = 0x40, stepNr = 0; @@ -350,7 +354,8 @@ void GfxTransitions::blocks(bool blackoutFlag) { } while (mask != 0x40); } -// directly shows new screen starting up/down/left/right and going to the opposite direction - works on _picRect area only +// Directly shows new screen starting up/down/left/right and going to the +// opposite direction - works on _picRect area only void GfxTransitions::straight(int16 number, bool blackoutFlag) { int16 stepNr = 0; Common::Rect newScreenRect = _picRect; @@ -402,7 +407,8 @@ void GfxTransitions::straight(int16 number, bool blackoutFlag) { } } -// scroll old screen (up/down/left/right) and insert new screen that way - works on _picRect area only +// Scroll old screen (up/down/left/right) and insert new screen that way - works +// on _picRect area only. void GfxTransitions::scroll(int16 number) { int16 screenWidth, screenHeight; byte *oldScreenPtr; @@ -512,7 +518,8 @@ void GfxTransitions::scroll(int16 number) { } } -// vertically displays new screen starting from center - works on _picRect area only +// Vertically displays new screen starting from center - works on _picRect area +// only void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left + (_picRect.width() / 2) -1, _picRect.top, _picRect.left + (_picRect.width() / 2), _picRect.bottom); Common::Rect rightRect = Common::Rect(leftRect.right, _picRect.top, leftRect.right + 1, _picRect.bottom); @@ -528,7 +535,8 @@ void GfxTransitions::verticalRollFromCenter(bool blackoutFlag) { } } -// vertically displays new screen starting from edges - works on _picRect area only +// Vertically displays new screen starting from edges - works on _picRect area +// only void GfxTransitions::verticalRollToCenter(bool blackoutFlag) { Common::Rect leftRect = Common::Rect(_picRect.left, _picRect.top, _picRect.left + 1, _picRect.bottom); Common::Rect rightRect = Common::Rect(leftRect.right - 1, _picRect.top, leftRect.right, _picRect.bottom); @@ -540,7 +548,8 @@ void GfxTransitions::verticalRollToCenter(bool blackoutFlag) { } } -// horizontally displays new screen starting from center - works on _picRect area only +// Horizontally displays new screen starting from center - works on _picRect +// area only void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top + (_picRect.height() / 2) - 1, _picRect.right, _picRect.top + (_picRect.height() / 2)); Common::Rect lowerRect = Common::Rect(upperRect.left, upperRect.bottom, upperRect.right, upperRect.bottom + 1); @@ -556,7 +565,8 @@ void GfxTransitions::horizontalRollFromCenter(bool blackoutFlag) { } } -// horizontally displays new screen starting from upper and lower edge - works on _picRect area only +// Horizontally displays new screen starting from upper and lower edge - works +// on _picRect area only void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) { Common::Rect upperRect = Common::Rect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect = Common::Rect(upperRect.left, _picRect.bottom - 1, upperRect.right, _picRect.bottom); @@ -568,8 +578,8 @@ void GfxTransitions::horizontalRollToCenter(bool blackoutFlag) { } } -// diagonally displays new screen starting from center - works on _picRect area only -// assumes that height of rect is larger than width +// Diagonally displays new screen starting from center - works on _picRect area +// only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) { int16 halfHeight = _picRect.height() / 2; Common::Rect upperRect(_picRect.left + halfHeight - 2, _picRect.top + halfHeight, _picRect.right - halfHeight + 1, _picRect.top + halfHeight + 1); @@ -598,8 +608,8 @@ void GfxTransitions::diagonalRollFromCenter(bool blackoutFlag) { } } -// diagonally displays new screen starting from edges - works on _picRect area only -// assumes that height of rect is larger than width +// Diagonally displays new screen starting from edges - works on _picRect area +// only. Assumes that height of rect is larger than width. void GfxTransitions::diagonalRollToCenter(bool blackoutFlag) { Common::Rect upperRect(_picRect.left, _picRect.top, _picRect.right, _picRect.top + 1); Common::Rect lowerRect(_picRect.left, _picRect.bottom - 1, _picRect.right, _picRect.bottom); -- cgit v1.2.3 From bf2b059a63ff68d2688d48e24f5bdcf97de46335 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Tue, 29 Jun 2010 18:20:10 +0000 Subject: Silence possible use of uninitialized variable warning in g++. svn-id: r50501 --- engines/tinsel/tinlib.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/tinsel/tinlib.cpp b/engines/tinsel/tinlib.cpp index 677392a35d..766d4ed54a 100644 --- a/engines/tinsel/tinlib.cpp +++ b/engines/tinsel/tinlib.cpp @@ -5557,7 +5557,7 @@ int CallLibraryRoutine(CORO_PARAM, int operand, int32 *pp, const INT_CONTEXT *pi case WALKED: { // Common to both DW1 & DW2 pp -= 3; // 4 parameters - bool tmp; + bool tmp = false; Walked(coroParam, pp[0], pp[1], pp[2], pp[3], pic->escOn, pic->myEscape, tmp); if (!coroParam) { // Only write the result to the stack if walked actually completed running. -- cgit v1.2.3 From 42351265f16779569cf170ff0e85658db26e7ee7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 29 Jun 2010 20:12:42 +0000 Subject: Fixed 2 uninitialized reads in SQ6 svn-id: r50502 --- engines/sci/engine/vm.cpp | 2 ++ 1 file changed, 2 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 2047482bac..fe37f09f31 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -288,6 +288,8 @@ static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller + { GID_SQ6, 0, "Game", "init", -1, 2, 0 }, + { GID_SQ6, 64950, "View", "handleEvent", -1, 0, 0 }, { (SciGameId)0, -1, NULL, NULL, -1, 0, 0 } }; -- cgit v1.2.3 From 3a2ac994d4565beff844aa802211099a4785a3e0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 29 Jun 2010 20:13:57 +0000 Subject: Handle empty clip rectangles in GfxView::drawScaled(). Fixes an assert in the first room of the game svn-id: r50503 --- engines/sci/graphics/view.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index ee9611b046..244114e866 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -660,8 +660,12 @@ void GfxView::drawScaled(const Common::Rect &rect, const Common::Rect &clipRect, scaledWidth = MIN(clipRect.width(), scaledWidth); scaledHeight = MIN(clipRect.height(), scaledHeight); - const uint16 offsetY = clipRect.top - rect.top; - const uint16 offsetX = clipRect.left - rect.left; + const int16 offsetY = clipRect.top - rect.top; + const int16 offsetX = clipRect.left - rect.left; + + // Happens in SQ6, first room + if (offsetX < 0 || offsetY < 0) + return; assert(scaledHeight + offsetY <= ARRAYSIZE(scalingY)); assert(scaledWidth + offsetX <= ARRAYSIZE(scalingX)); -- cgit v1.2.3 From 7951e3ddcf1053686882b6fe4881a4607bcbea05 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 20:44:19 +0000 Subject: SCI: kernelMap cleanup and making it possible to have version (not implemented yet) or platform specific entries - changing signature for kNewWindow - using old dummy-signature for mac-only svn-id: r50504 --- engines/sci/engine/kernel.cpp | 489 +++++++++++++++++++++++------------------- 1 file changed, 270 insertions(+), 219 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 75eadb9a64..f804ce0426 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -199,201 +199,227 @@ static const char *s_defaultKernelNames[] = { /*0x88*/ "Dummy" // DbugStr }; -struct SciKernelFunction { +// [io] -> either integer or object +// (io) -> optionally integer AND an object +// (i) -> optional integer +// . -> any type +// i* -> optional multiple integers +// .* -> any parameters afterwards (or none) + +struct SciKernelMapEntry { const char *name; - KernelFunc *func; /* The actual function */ - const char *signature; /* kfunct signature */ + KernelFunc *function; + + SciVersion fromVersion; + SciVersion toVersion; + byte forPlatform; + + const char *signature; + const char *subSignature; // placeholder }; -static SciKernelFunction s_kernelFuncMap[] = { - /*00*/ { "Load", kLoad, "iii*" }, - /*01*/ { "UnLoad", kUnLoad, "i.*" }, // Work around SQ1 bug, when exiting the Ulence flats bar - /*02*/ { "ScriptID", kScriptID, "Ioi*" }, - /*03*/ { "DisposeScript", kDisposeScript, "Oii*" }, // Work around QfG1 bug - /*04*/ { "Clone", kClone, "o" }, - /*05*/ { "DisposeClone", kDisposeClone, "o" }, - /*06*/ { "IsObject", kIsObject, "." }, - /*07*/ { "RespondsTo", kRespondsTo, ".i" }, - /*08*/ { "DrawPic", kDrawPic, "i*" }, - - /*0a*/ { "PicNotValid", kPicNotValid, "i*" }, - /*0b*/ { "Animate", kAnimate, "LI*" }, // More like (li?)? - /*0c*/ { "SetNowSeen", kSetNowSeen, "oi*" }, // The second parameter is ignored - /*0d*/ { "NumLoops", kNumLoops, "o" }, - /*0e*/ { "NumCels", kNumCels, "o" }, - /*0f*/ { "CelWide", kCelWide, "iOi*" }, - /*10*/ { "CelHigh", kCelHigh, "iOi*" }, - /*11*/ { "DrawCel", kDrawCel, "iiiiii*i*r*" }, - /*12*/ { "AddToPic", kAddToPic, "Il*" }, - // FIXME: signature check removed (set to .*) as kNewWindow is different in Mac versions - /*13*/ { "NewWindow", kNewWindow, "*." }, - ///*13*/ { "NewWindow", kNewWindow, "iiiiZRi*" }, - /*14*/ { "GetPort", kGetPort, "" }, - /*15*/ { "SetPort", kSetPort, "ii*" }, - /*16*/ { "DisposeWindow", kDisposeWindow, "ii*" }, - /*17*/ { "DrawControl", kDrawControl, "o" }, - /*18*/ { "HiliteControl", kHiliteControl, "o" }, - /*19*/ { "EditControl", kEditControl, "ZoZo" }, - /*1a*/ { "TextSize", kTextSize, "rZrii*r*" }, - /*1b*/ { "Display", kDisplay, ".*" }, - /*1c*/ { "GetEvent", kGetEvent, "ioi*" }, // Mac versions pass an extra 3rd parameter (ignored - always 0?) - /*1d*/ { "GlobalToLocal", kGlobalToLocal, "oo*" }, - /*1e*/ { "LocalToGlobal", kLocalToGlobal, "oo*" }, - /*1f*/ { "MapKeyToDir", kMapKeyToDir, "o" }, - /*20*/ { "DrawMenuBar", kDrawMenuBar, "i" }, - /*21*/ { "MenuSelect", kMenuSelect, "oi*" }, - /*22*/ { "AddMenu", kAddMenu, "rr" }, - /*23*/ { "DrawStatus", kDrawStatus, "Zri*" }, - /*24*/ { "Parse", kParse, "ro" }, - /*25*/ { "Said", kSaid, "Zr" }, - /*26*/ { "SetSynonyms", kSetSynonyms, "o" }, - /*27*/ { "HaveMouse", kHaveMouse, "" }, - /*28*/ { "SetCursor", kSetCursor, "i*" }, - // FIXME: The number 0x28 occurs twice :-) - /*28*/ { "MoveCursor", kMoveCursor, "ii" }, - /*29*/ { "FOpen", kFOpen, "ri" }, - /*2a*/ { "FPuts", kFPuts, "ir" }, - /*2b*/ { "FGets", kFGets, "rii" }, - /*2c*/ { "FClose", kFClose, "i" }, - /*2d*/ { "SaveGame", kSaveGame, "rirr*" }, - /*2e*/ { "RestoreGame", kRestoreGame, "rir*" }, - /*2f*/ { "RestartGame", kRestartGame, "" }, - /*30*/ { "GameIsRestarting", kGameIsRestarting, "i*" }, - /*31*/ { "DoSound", kDoSound, "iIo*" }, - /*32*/ { "NewList", kNewList, "" }, - /*33*/ { "DisposeList", kDisposeList, "l" }, - /*34*/ { "NewNode", kNewNode, ".." }, - /*35*/ { "FirstNode", kFirstNode, "Zl" }, - /*36*/ { "LastNode", kLastNode, "l" }, - /*37*/ { "EmptyList", kEmptyList, "l" }, - /*38*/ { "NextNode", kNextNode, "n" }, - /*39*/ { "PrevNode", kPrevNode, "n" }, - /*3a*/ { "NodeValue", kNodeValue, "Zn" }, - /*3b*/ { "AddAfter", kAddAfter, "lnn" }, - /*3c*/ { "AddToFront", kAddToFront, "ln" }, - /*3d*/ { "AddToEnd", kAddToEnd, "ln" }, - /*3e*/ { "FindKey", kFindKey, "l." }, - /*3f*/ { "DeleteKey", kDeleteKey, "l." }, - /*40*/ { "Random", kRandom, "i*" }, - /*41*/ { "Abs", kAbs, "Oi" }, - /*42*/ { "Sqrt", kSqrt, "i" }, - /*43*/ { "GetAngle", kGetAngle, "iiiii*" }, // occasionally KQ6 passes a 5th argument by mistake - /*44*/ { "GetDistance", kGetDistance, "iiiii*" }, - /*45*/ { "Wait", kWait, "i" }, - /*46*/ { "GetTime", kGetTime, "i*" }, - /*47*/ { "StrEnd", kStrEnd, "r" }, - /*48*/ { "StrCat", kStrCat, "rr" }, - /*49*/ { "StrCmp", kStrCmp, "rri*" }, - /*4a*/ { "StrLen", kStrLen, "Zr" }, - /*4b*/ { "StrCpy", kStrCpy, "rZri*" }, - /*4c*/ { "Format", kFormat, "r.*" }, - /*4d*/ { "GetFarText", kGetFarText, "iiZr" }, - /*4e*/ { "ReadNumber", kReadNumber, "r" }, - /*4f*/ { "BaseSetter", kBaseSetter, "o" }, - /*50*/ { "DirLoop", kDirLoop, "oi" }, - // Opcode 51 is defined twice for a reason: In older SCI versions - // it is CanBeHere, whereas in newer version it is CantBeHere - /*51*/ { "CanBeHere", kCanBeHere, "ol*" }, - /*51*/ { "CantBeHere", kCantBeHere, "ol*" }, - /*52*/ { "OnControl", kOnControl, "i*" }, - /*53*/ { "InitBresen", kInitBresen, "oi*" }, - /*54*/ { "DoBresen", kDoBresen, "o" }, - /*55*/ { "DoAvoider", kDoAvoider, "o" }, - /*56*/ { "SetJump", kSetJump, "oiii" }, - /*57*/ { "SetDebug", kSetDebug, "i*" }, - /*5c*/ { "MemoryInfo", kMemoryInfo, "i" }, - /*5f*/ { "GetMenu", kGetMenu, "i." }, - /*60*/ { "SetMenu", kSetMenu, "i.*" }, - /*61*/ { "GetSaveFiles", kGetSaveFiles, "rrr" }, - /*62*/ { "GetCWD", kGetCWD, "r" }, - /*63*/ { "CheckFreeSpace", kCheckFreeSpace, "r.*" }, - /*64*/ { "ValidPath", kValidPath, "r" }, - /*65*/ { "CoordPri", kCoordPri, "ii*" }, - /*66*/ { "StrAt", kStrAt, "rii*" }, - /*67*/ { "DeviceInfo", kDeviceInfo, "i.*" }, - /*68*/ { "GetSaveDir", kGetSaveDir, ".*" }, // accepts a parameter in SCI2+ games - /*69*/ { "CheckSaveGame", kCheckSaveGame, ".*" }, - /*6a*/ { "ShakeScreen", kShakeScreen, "ii*" }, - /*6b*/ { "FlushResources", kFlushResources, "i" }, - /*6c*/ { "TimesSin", kTimesSin, "ii" }, - /*6d*/ { "TimesCos", kTimesCos, "ii" }, - /*6e*/ { "6e", kTimesSin, "ii" }, - /*6f*/ { "6f", kTimesCos, "ii" }, - /*70*/ { "Graph", kGraph, ".*" }, - /*71*/ { "Joystick", kJoystick, ".*" }, - - // Experimental functions - /*74*/ { "FileIO", kFileIO, "i.*" }, - /*(?)*/ { "Memory", kMemory, "i.*" }, - /*(?)*/ { "Sort", kSort, "ooo" }, - /*(?)*/ { "AvoidPath", kAvoidPath, "ii.*" }, - /*(?)*/ { "Lock", kLock, "iii*" }, - /*(?)*/ { "Palette", kPalette, "i.*" }, - /*(?)*/ { "IsItSkip", kIsItSkip, "iiiii" }, - /*7b*/ { "StrSplit", kStrSplit, "rrZr" }, - - // Non-experimental functions without a fixed ID - { "CosMult", kTimesCos, "ii" }, - { "SinMult", kTimesSin, "ii" }, - - // Misc functions - /*(?)*/ { "CosDiv", kCosDiv, "ii" }, - /*(?)*/ { "PriCoord", kPriCoord, "i" }, - /*(?)*/ { "SinDiv", kSinDiv, "ii" }, - /*(?)*/ { "TimesCot", kTimesCot, "ii" }, - /*(?)*/ { "TimesTan", kTimesTan, "ii" }, - { "Message", kMessage, ".*" }, - { "GetMessage", kGetMessage, "iiir" }, - { "DoAudio", kDoAudio, ".*" }, - { "DoSync", kDoSync, ".*" }, - { "MemorySegment", kMemorySegment, "iri*" }, - { "Intersections", kIntersections, "iiiiriiiri" }, - { "MergePoly", kMergePoly, "rli" }, - { "ResCheck", kResCheck, "iii*" }, - { "SetQuitStr", kSetQuitStr, "r" }, - { "ShowMovie", kShowMovie, ".*" }, - { "SetVideoMode", kSetVideoMode, "i" }, - { "Platform", kPlatform, ".*" }, - { "TextColors", kTextColors, ".*" }, - { "TextFonts", kTextFonts, ".*" }, - { "Portrait", kPortrait, ".*" }, - { "PalVary", kPalVary, "ii*" }, - { "AssertPalette", kAssertPalette, "i" }, - { "Empty", kEmpty, ".*" }, +#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE +#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1 +#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 +#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE + +#define SIGFOR_ALL 0x4f +#define SIGFOR_PC 1 << 0 +#define SIGFOR_PC98 1 << 1 +#define SIGFOR_WIN 1 << 2 +#define SIGFOR_MAC 1 << 3 +#define SIGFOR_AMIGA 1 << 4 +#define SIGFOR_ATARI 1 << 5 + +#define SIG_EVERYWHERE SIG_SCI32, SIGFOR_ALL + +#define MAP_CALL(_name_) #_name_, k##_name_ + +// name, version, platf., function, signature, subfunction-signatures +static SciKernelMapEntry s_kernelMap[] = { + { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i.*", NULL }, + // ^^ FIXME - Work around SQ1 bug, when exiting the Ulence flats bar + { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "Oii*", NULL }, + // ^^ FIXME - Work around QfG1 bug + { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL }, + { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL }, + { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(Animate), SIG_EVERYWHERE, "LI*", NULL }, + // ^^ FIXME - More like (li?)? + { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "oi*", NULL }, + // ^^ FIXME - The second parameter is ignored + { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL }, + { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL }, + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*r*", NULL }, + { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL }, + { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL }, + { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL }, + { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(SetPort), SIG_EVERYWHERE, "ii*", NULL }, + { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "ii*", NULL }, + { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL }, + { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL }, + { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(GetEvent), SIG_EVERYWHERE, "ioi*", NULL }, + // ^^ FIXME Mac versions pass an extra 3rd parameter (ignored - always 0?) + { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL }, + { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL }, + { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "oi*", NULL }, + { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL }, + { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "Zri*", NULL }, + { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL }, + { MAP_CALL(Said), SIG_EVERYWHERE, "Zr", NULL }, + { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL }, + { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL }, + { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL }, + { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rirr*", NULL }, + { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir*", NULL }, + { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(DoSound), SIG_EVERYWHERE, "iIo*", NULL }, + { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL }, + { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL }, + { MAP_CALL(FirstNode), SIG_EVERYWHERE, "Zl", NULL }, + { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL }, + { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL }, + { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL }, + { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL }, + { MAP_CALL(NodeValue), SIG_EVERYWHERE, "Zn", NULL }, + { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL }, + { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL }, + { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL }, + { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL }, + { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(Abs), SIG_EVERYWHERE, "Oi", NULL }, + { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiiii*", NULL }, + // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake + { MAP_CALL(GetDistance), SIG_EVERYWHERE, "iiiii*", NULL }, + { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(GetTime), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL }, + { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL }, + { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rri*", NULL }, + { MAP_CALL(StrLen), SIG_EVERYWHERE, "Zr", NULL }, + { MAP_CALL(StrCpy), SIG_EVERYWHERE, "rZri*", NULL }, + { MAP_CALL(Format), SIG_EVERYWHERE, "r.*", NULL }, + { MAP_CALL(GetFarText), SIG_EVERYWHERE, "iiZr", NULL }, + { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL }, + { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL }, + { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "ol*", NULL }, + { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "ol*", NULL }, + { MAP_CALL(OnControl), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(InitBresen), SIG_EVERYWHERE, "oi*", NULL }, + { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL }, + { MAP_CALL(SetDebug), SIG_EVERYWHERE, "i*", NULL }, + { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL }, + { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL }, + { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL }, + { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r.*", NULL }, + { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL }, + { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL }, + { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL }, + { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, ".*", NULL }, + // ^^ FIXME accepts a parameter in SCI2+ games + { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL }, + { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(Joystick), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(FileIO), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(Memory), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL }, + { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii.*", NULL }, + { MAP_CALL(Lock), SIG_EVERYWHERE, "iii*", NULL }, + { MAP_CALL(Palette), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL }, + { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rrZr", NULL }, + { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL }, + { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL }, + { MAP_CALL(Message), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL }, + { MAP_CALL(DoAudio), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(DoSync), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "iri*", NULL }, + { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL }, + { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL }, + { MAP_CALL(ResCheck), SIG_EVERYWHERE, "iii*", NULL }, + { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL }, + { MAP_CALL(ShowMovie), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(Platform), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(TextColors), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(TextFonts), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(Portrait), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(PalVary), SIG_EVERYWHERE, "ii*", NULL }, + { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL }, + { MAP_CALL(Empty), SIG_EVERYWHERE, ".*", NULL }, #ifdef ENABLE_SCI32 - // SCI2 Kernel Functions - { "IsHiRes", kIsHiRes, "" }, - { "Array", kArray, ".*" }, - { "ListAt", kListAt, "li" }, - { "String", kString, ".*" }, - { "AddScreenItem", kAddScreenItem, "o" }, - { "UpdateScreenItem", kUpdateScreenItem, "o" }, - { "DeleteScreenItem", kDeleteScreenItem, "o" }, - { "AddPlane", kAddPlane, "o" }, - { "DeletePlane", kDeletePlane, "o" }, - { "UpdatePlane", kUpdatePlane, "o" }, - { "RepaintPlane", kRepaintPlane, "o" }, - { "GetHighPlanePri", kGetHighPlanePri, "" }, - { "FrameOut", kFrameOut, "" }, - { "ListEachElementDo", kListEachElementDo, "li.*" }, - { "ListFirstTrue", kListFirstTrue, "li.*" }, - { "ListAllTrue", kListAllTrue, "li.*" }, - { "ListIndexOf", kListIndexOf, "lZo" }, - { "OnMe", kOnMe, "iio.*" }, - { "InPolygon", kInPolygon, "iio" }, - { "CreateTextBitmap", kCreateTextBitmap, "i.*" }, - - // SCI2.1 Kernel Functions - { "Save", kSave, ".*" }, - { "List", kList, ".*" }, - { "Robot", kRobot, ".*" }, - { "PlayVMD", kPlayVMD, ".*" }, - { "IsOnMe", kIsOnMe, "iio.*" }, - { "MulDiv", kMulDiv, "iii" }, - { "Text", kText, ".*" }, - + // SCI2 Kernel Functions + { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(Array), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL }, + { MAP_CALL(String), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL }, + { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL }, + { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li.*", NULL }, + { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li.*", NULL }, + { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li.*", NULL }, + { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "lZo", NULL }, + { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio.*", NULL }, + { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL }, + { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i.*", NULL }, + + // SCI2.1 Kernel Functions + { MAP_CALL(Save), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(List), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(PlayVMD), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL }, + { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL }, + { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL }, + { NULL, NULL, SIG_EVERYWHERE, NULL, NULL } #endif +}; #if 0 // Stub functions @@ -406,9 +432,6 @@ static SciKernelFunction s_kernelFuncMap[] = { { "DbugStr", kDbugStr, ".*" }, #endif - {NULL, NULL, NULL} // Terminator -}; - Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan), _invalid("") { loadSelectorNames(); @@ -569,55 +592,83 @@ static char *compileKernelSignature(const char *s) { void Kernel::mapFunctions() { int mapped = 0; int ignored = 0; - uint functions_nr = _kernelNames.size(); + uint functionCount = _kernelNames.size(); + byte platformMask = 0; - _kernelFuncs.resize(functions_nr); + switch (g_sci->getPlatform()) { + case Common::kPlatformPC: + platformMask = SIGFOR_PC; + break; + case Common::kPlatformPC98: + platformMask = SIGFOR_PC98; + break; + case Common::kPlatformWindows: + platformMask = SIGFOR_WIN; + break; + case Common::kPlatformMacintosh: + platformMask = SIGFOR_MAC; + break; + case Common::kPlatformAmiga: + platformMask = SIGFOR_AMIGA; + break; + case Common::kPlatformAtariST: + platformMask = SIGFOR_ATARI; + break; + default: + break; + } - for (uint functnr = 0; functnr < functions_nr; functnr++) { - int found = -1; + _kernelFuncs.resize(functionCount); + for (uint functNr = 0; functNr < functionCount; functNr++) { // First, get the name, if known, of the kernel function with number functnr - Common::String sought_name = _kernelNames[functnr]; + Common::String sought_name = _kernelNames[functNr]; // Reset the table entry - _kernelFuncs[functnr].func = NULL; - _kernelFuncs[functnr].signature = NULL; - _kernelFuncs[functnr].origName = sought_name; + _kernelFuncs[functNr].func = NULL; + _kernelFuncs[functNr].signature = NULL; + _kernelFuncs[functNr].origName = sought_name; + _kernelFuncs[functNr].isDummy = true; if (sought_name.empty()) { // No name was given -> must be an unknown opcode - warning("Kernel function %x unknown", functnr); - _kernelFuncs[functnr].isDummy = true; + warning("Kernel function %x unknown", functNr); continue; } // Don't map dummy functions - they will never be called - if (sought_name == "Dummy") { - _kernelFuncs[functnr].isDummy = true; + if (sought_name == "Dummy") continue; - } - // If the name is known, look it up in s_kernelFuncMap. This table + // If the name is known, look it up in s_kernelMap. This table // maps kernel func names to actual function (pointers). - for (uint seeker = 0; (found == -1) && s_kernelFuncMap[seeker].name; seeker++) - if (sought_name == s_kernelFuncMap[seeker].name) - found = seeker; // Found a kernel function with the correct name! + SciKernelMapEntry *kernelMap = s_kernelMap; + bool nameMatch = false; + while (kernelMap->name) { + if (sought_name == kernelMap->name) { + if (platformMask & kernelMap->forPlatform) + break; + nameMatch = true; + } + kernelMap++; + } - if (found == -1) { - // No match but a name was given -> stub - warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functnr); - _kernelFuncs[functnr].isDummy = true; - } else { - // A match in s_kernelFuncMap was found - if (s_kernelFuncMap[found].func) { - _kernelFuncs[functnr].func = s_kernelFuncMap[found].func; - _kernelFuncs[functnr].signature = compileKernelSignature(s_kernelFuncMap[found].signature); - _kernelFuncs[functnr].isDummy = false; + if (kernelMap->name) { + // A match was found + if (kernelMap->function) { + _kernelFuncs[functNr].func = kernelMap->function; + _kernelFuncs[functNr].signature = compileKernelSignature(kernelMap->signature); + _kernelFuncs[functNr].isDummy = false; ++mapped; } else { //warning("Ignoring function %s\n", s_kernelFuncMap[found].name); ++ignored; } + } else { + if (nameMatch) + error("kernel function %s[%x] not found for this version/platform", sought_name.c_str(), functNr); + // No match but a name was given -> stub + warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functNr); } } // for all functions requesting to be mapped -- cgit v1.2.3 From b09996cb5cea63482c16faafb55d83bd50c04c90 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 29 Jun 2010 20:50:52 +0000 Subject: SCI: Rewrap yet more comments svn-id: r50505 --- engines/sci/sound/audio.cpp | 16 ++++++----- engines/sci/sound/music.cpp | 43 ++++++++++++++++++------------ engines/sci/sound/soundcmd.cpp | 60 ++++++++++++++++++++++++------------------ 3 files changed, 69 insertions(+), 50 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index 336218eaec..ed9061ab81 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -77,9 +77,10 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { } int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { - // Get the audio sample length and set the wPlay flag so we return 0 on position. - // SSCI pre-loads the audio here, but it's much easier for us to just get the - // sample length and return that. wPlayAudio should *not* actually start the sample. + // Get the audio sample length and set the wPlay flag so we return 0 on + // position. SSCI pre-loads the audio here, but it's much easier for us to + // just get the sample length and return that. wPlayAudio should *not* + // actually start the sample. int sampleLen = 0; Audio::AudioStream *audioStream = getAudioStream(tuple, module, &sampleLen); @@ -272,8 +273,8 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 byte *compressedData = (byte *)malloc(audioRes->size); assert(compressedData); // We copy over the compressed data in our own buffer. We have to do - // this, because ResourceManager may free the original data late. - // All other compression types already decompress completely into an + // this, because ResourceManager may free the original data late. All + // other compression types already decompress completely into an // additional buffer here. MP3/OGG/FLAC decompression works on-the-fly // instead. memcpy(compressedData, audioRes->data, audioRes->size); @@ -367,8 +368,9 @@ Audio::RewindableAudioStream *AudioPlayer::getAudioStream(uint32 number, uint32 *sampleLen = (audioSeekStream->getLength().msecs() * 60) / 1000; // we translate msecs to ticks audioStream = audioSeekStream; } - // We have to make sure that we don't depend on resource manager pointers after this point, because the actual - // audio resource may get unloaded by resource manager at any time + // We have to make sure that we don't depend on resource manager pointers + // after this point, because the actual audio resource may get unloaded by + // resource manager at any time. if (audioStream) return audioStream; diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index ba103ee746..874f0a381e 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -64,11 +64,16 @@ void SciMusic::init() { _dwTempo = 0; // Default to MIDI in SCI32 games, as many don't have AdLib support. - // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support those patches yet. - // We also don't yet support the 7.pat file of SCI1+ Mac games or SCI0 Mac patches, so we - // default to MIDI in those games to let them run. + // WORKAROUND: Default to MIDI in Amiga SCI1_EGA+ games as we don't support + // those patches yet. We also don't yet support the 7.pat file of SCI1+ Mac + // games or SCI0 Mac patches, so we default to MIDI in those games to let + // them run. Common::Platform platform = g_sci->getPlatform(); - uint32 dev = MidiDriver::detectDevice((getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); + uint32 dev = MidiDriver::detectDevice( + (getSciVersion() >= SCI_VERSION_2 || platform == Common::kPlatformMacintosh || + (platform == Common::kPlatformAmiga && getSciVersion() >= SCI_VERSION_1_EGA)) + ? (MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_GM) + : (MDT_PCSPK | MDT_ADLIB | MDT_MIDI)); switch (MidiDriver::getMusicType(dev)) { case MT_ADLIB: @@ -100,7 +105,8 @@ void SciMusic::init() { _bMultiMidi = ConfMan.getBool("multi_midi"); - // Find out what the first possible channel is (used, when doing channel remapping) + // Find out what the first possible channel is (used, when doing channel + // remapping). _driverFirstChannel = _pMidiDrv->getFirstChannel(); } @@ -128,9 +134,10 @@ void SciMusic::putMidiCommandInQueue(uint32 midi) { _queuedCommands.push_back(midi); } -// This sends the stored commands from queue to driver (is supposed to get called only during onTimer()) -// at least mt32 emulation doesn't like getting note-on commands from main thread (if we directly send, we would get -// a crash during piano scene in lsl5) +// This sends the stored commands from queue to driver (is supposed to get +// called only during onTimer()). At least mt32 emulation doesn't like getting +// note-on commands from main thread (if we directly send, we would get a crash +// during piano scene in lsl5). void SciMusic::sendMidiCommandsFromQueue() { uint curCommand = 0; uint commandCount = _queuedCommands.size(); @@ -210,10 +217,10 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { int channelFilterMask = 0; SoundResource::Track *track = pSnd->soundRes->getTrackByType(_pMidiDrv->getPlayId()); - // If MIDI device is selected but there is no digital track in sound resource - // try to use adlib's digital sample if possible - // Also, if the track couldn't be found, load the digital track, as some games - // depend on this (e.g. the Longbow demo) + // If MIDI device is selected but there is no digital track in sound + // resource try to use adlib's digital sample if possible. Also, if the + // track couldn't be found, load the digital track, as some games depend on + // this (e.g. the Longbow demo). if (!track || (_bMultiMidi && track->digitalChannelNr == -1)) { SoundResource::Track *digital = pSnd->soundRes->getDigitalTrack(); if (digital) @@ -260,8 +267,8 @@ void SciMusic::soundInitSnd(MusicEntry *pSnd) { } } -// This one checks, if requested channel is available -> in that case give caller that channel -// Otherwise look for an unused one +// This one checks, if requested channel is available -> in that case give +// caller that channel. Otherwise look for an unused one int16 SciMusic::tryToOwnChannel(MusicEntry *caller, int16 bestChannel) { // Don't even try this for SCI0 if (_soundVersion <= SCI_VERSION_0_LATE) @@ -316,7 +323,7 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { if ((_soundVersion <= SCI_VERSION_0_LATE) && (alreadyPlaying)) { // Music already playing in SCI0? if (pSnd->priority > alreadyPlaying->priority) { - // And new priority higher? pause previous music and play new one immediately + // And new priority higher? pause previous music and play new one immediately. // Example of such case: lsl3, when getting points (jingle is played then) soundPause(alreadyPlaying); alreadyPlaying->isQueued = true; @@ -339,7 +346,8 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { pSnd->pLoopStream, -1, pSnd->volume, 0, DisposeAfterUse::NO); } else { - // Rewind in case we play the same sample multiple times (non-looped) like in pharkas right at the start + // Rewind in case we play the same sample multiple times + // (non-looped) like in pharkas right at the start pSnd->pStreamAud->rewind(); _pMixer->playStream(pSnd->soundType, &pSnd->hCurrentAud, pSnd->pStreamAud, -1, pSnd->volume, 0, @@ -377,7 +385,8 @@ void SciMusic::soundStop(MusicEntry *pSnd) { if (pSnd->pMidiParser) { _mutex.lock(); pSnd->pMidiParser->mainThreadBegin(); - // We shouldn't call stop in case it's paused, otherwise we would send allNotesOff() again + // We shouldn't call stop in case it's paused, otherwise we would send + // allNotesOff() again if (previousStatus == kSoundPlaying) pSnd->pMidiParser->stop(); freeChannels(pSnd); diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 5e0f45e166..7cdb3e08bf 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -134,7 +134,8 @@ SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segM _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { #ifdef USE_OLD_MUSIC_FUNCTIONS - // The following hack is needed to ease the change from old to new sound code (because the new sound code does not use SfxState) + // The following hack is needed to ease the change from old to new sound + // code (because the new sound code does not use SfxState) _state = &g_sci->getEngineState()->_sound; // HACK #endif @@ -378,22 +379,24 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { } if (!readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && obj.segment) { - // In SCI1.1 games, sound effects are started from here. If we can find - // a relevant audio resource, play it, otherwise switch to synthesized - // effects. If the resource exists, play it using map 65535 (sound - // effects map) + // In SCI1.1 games, sound effects are started from here. If we can + // find a relevant audio resource, play it, otherwise switch to + // synthesized effects. If the resource exists, play it using map + // 65535 (sound effects map). if (_resMan->testResource(ResourceId(kResourceTypeAudio, songNumber)) && getSciVersion() >= SCI_VERSION_1_1) { // Found a relevant audio resource, play it _audio->stopAudio(); warning("Initializing audio resource instead of requested sound resource %d", songNumber); sampleLen = _audio->startAudio(65535, songNumber); - // Also create iterator, that will fire SI_FINISHED event, when the sound is done playing + // Also create iterator, that will fire SI_FINISHED event, when + // the sound is done playing. _state->sfx_add_song(new_timer_iterator(sampleLen), 0, handle, songNumber); } else { if (!_resMan->testResource(ResourceId(kResourceTypeSound, songNumber))) { warning("Could not open song number %d", songNumber); - // Send a "stop handle" event so that the engine won't wait forever here + // Send a "stop handle" event so that the engine won't wait + // forever here. _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); return; @@ -533,12 +536,13 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); } - // Set signal selector in sound SCI0 games only, when the sample has finished playing - // If we don't set it at all, we get a problem when using vaporizer on the 2 guys - // If we set it all the time, we get no music in sq3new and kq1 - // FIXME: this *may* be wrong, it's impossible to find out in sierra DOS sci, because SCI0 under DOS didn't have - // sfx drivers included - // We need to set signal in sound SCI1+ games all the time + // Set signal selector in sound SCI0 games only, when the sample has + // finished playing. If we don't set it at all, we get a problem when using + // vaporizer on the 2 guys. If we set it all the time, we get no music in + // sq3new and kq1. + // FIXME: This *may* be wrong, it's impossible to find out in Sierra DOS + // SCI, because SCI0 under DOS didn't have sfx drivers included. + // We need to set signal in sound SCI1+ games all the time. if ((_soundVersion > SCI_VERSION_0_LATE) || sampleFinishedPlaying) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); @@ -560,8 +564,8 @@ void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { #else if (!obj.segment) { // pause the whole playlist - // Pausing/Resuming the whole playlist was introduced - // in the SCI1 late sound scheme + // Pausing/Resuming the whole playlist was introduced in the SCI1 late + // sound scheme. if (_soundVersion <= SCI_VERSION_1_EARLY) return; @@ -685,7 +689,8 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { switch (_argc) { case 2: // SCI0 - // SCI0 fades out all the time and when fadeout is done it will also stop the music from playing + // SCI0 fades out all the time and when fadeout is done it will also + // stop the music from playing musicSlot->fadeTo = 0; musicSlot->fadeStep = -5; musicSlot->fadeTickerStep = 10 * 16667 / _music->soundGetTempo(); @@ -864,10 +869,12 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { cmdStopSound(obj, 0); } } else { - // Slot actually has no data (which would mean that a sound-resource w/ unsupported data is used + // Slot actually has no data (which would mean that a sound-resource w/ + // unsupported data is used. // (example lsl5 - sound resource 744 - it's roland exclusive writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - // If we don't set signal here, at least the switch to the mud wrestling room in lsl5 will not work + // If we don't set signal here, at least the switch to the mud wrestling + // room in lsl5 will not work. } if (musicSlot->fadeCompleted) { @@ -968,9 +975,9 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Do not throw a warning if the sound can't be found, as in some games - // this is called before the actual sound is loaded (e.g. SQ4CD, with the - // drum sounds of the energizer bunny at the beginning), so this is normal - // behavior + // this is called before the actual sound is loaded (e.g. SQ4CD, with + // the drum sounds of the energizer bunny at the beginning), so this is + // normal behavior. //warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -1036,7 +1043,7 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { // before actually initializing the sound and adding it to the playlist // with cmdInitSound. Usually, it doesn't matter if the game doesn't // request to loop the sound, so in this case, don't throw any warning, - // otherwise do, because the sound won't be looped + // otherwise do, because the sound won't be looped. if (value == -1) { warning("cmdSetSoundLoop: Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); } else { @@ -1070,12 +1077,13 @@ void SoundCommandParser::updateSci0Cues() { const MusicList::iterator end = _music->getPlayListEnd(); for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { // Is the sound stopped, and the sound object updated too? If yes, skip - // this sound, as SCI0 only allows one active song + // this sound, as SCI0 only allows one active song. if ((*i)->isQueued) { pWaitingForPlay = (*i); - // FIXME (?) - in iceman 2 songs are queued when playing the door sound - if we use the first song for resuming - // then it's the wrong one. Both songs have same priority. Maybe the new sound function in sci0 - // is somehow responsible + // FIXME(?): In iceman 2 songs are queued when playing the door + // sound - if we use the first song for resuming then it's the wrong + // one. Both songs have same priority. Maybe the new sound function + // in sci0 is somehow responsible. continue; } if ((*i)->signal == 0 && (*i)->status != kSoundPlaying) -- cgit v1.2.3 From c536630648ea7232508a477c3e503a0d867e25d9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 21:13:19 +0000 Subject: SCI: adding space in kernelmap for workaround table svn-id: r50506 --- engines/sci/engine/kernel.cpp | 343 +++++++++++++++++++++--------------------- 1 file changed, 172 insertions(+), 171 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index f804ce0426..40ee003cde 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -215,7 +215,8 @@ struct SciKernelMapEntry { byte forPlatform; const char *signature; - const char *subSignature; // placeholder + const char *subSignatures; // placeholder + const char *workarounds; // placeholder }; #define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE @@ -235,189 +236,189 @@ struct SciKernelMapEntry { #define MAP_CALL(_name_) #_name_, k##_name_ -// name, version, platf., function, signature, subfunction-signatures +// name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { - { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i.*", NULL, NULL }, // ^^ FIXME - Work around SQ1 bug, when exiting the Ulence flats bar - { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL }, - { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "Oii*", NULL }, + { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "Oii*", NULL, NULL }, // ^^ FIXME - Work around QfG1 bug - { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL }, - { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL }, - { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(Animate), SIG_EVERYWHERE, "LI*", NULL }, + { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, + { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, + { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(Animate), SIG_EVERYWHERE, "LI*", NULL, NULL }, // ^^ FIXME - More like (li?)? - { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "oi*", NULL }, + { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "oi*", NULL, NULL }, // ^^ FIXME - The second parameter is ignored - { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL }, - { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL }, - { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*r*", NULL }, - { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL }, - { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL }, - { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL }, - { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(SetPort), SIG_EVERYWHERE, "ii*", NULL }, - { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "ii*", NULL }, - { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL }, - { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL }, - { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(GetEvent), SIG_EVERYWHERE, "ioi*", NULL }, + { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL, NULL }, + { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*r*", NULL, NULL }, + { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL, NULL }, + { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(SetPort), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL, NULL }, + { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL, NULL }, + { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_EVERYWHERE, "ioi*", NULL, NULL }, // ^^ FIXME Mac versions pass an extra 3rd parameter (ignored - always 0?) - { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL }, - { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL }, - { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "oi*", NULL }, - { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL }, - { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "Zri*", NULL }, - { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL }, - { MAP_CALL(Said), SIG_EVERYWHERE, "Zr", NULL }, - { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL }, - { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL }, - { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL }, - { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rirr*", NULL }, - { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir*", NULL }, - { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(DoSound), SIG_EVERYWHERE, "iIo*", NULL }, - { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL }, - { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL }, - { MAP_CALL(FirstNode), SIG_EVERYWHERE, "Zl", NULL }, - { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL }, - { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL }, - { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL }, - { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL }, - { MAP_CALL(NodeValue), SIG_EVERYWHERE, "Zn", NULL }, - { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL }, - { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL }, - { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL }, - { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL }, - { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL }, - { MAP_CALL(Random), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(Abs), SIG_EVERYWHERE, "Oi", NULL }, - { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiiii*", NULL }, + { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL, NULL }, + { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "oi*", NULL, NULL }, + { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "Zri*", NULL, NULL }, + { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, + { MAP_CALL(Said), SIG_EVERYWHERE, "Zr", NULL, NULL }, + { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, + { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, + { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, + { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rirr*", NULL, NULL }, + { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir*", NULL, NULL }, + { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(DoSound), SIG_EVERYWHERE, "iIo*", NULL, NULL }, + { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, + { MAP_CALL(FirstNode), SIG_EVERYWHERE, "Zl", NULL, NULL }, + { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(NodeValue), SIG_EVERYWHERE, "Zn", NULL, NULL }, + { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, + { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(Abs), SIG_EVERYWHERE, "Oi", NULL, NULL }, + { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiiii*", NULL, NULL }, // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake - { MAP_CALL(GetDistance), SIG_EVERYWHERE, "iiiii*", NULL }, - { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(GetTime), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL }, - { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL }, - { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rri*", NULL }, - { MAP_CALL(StrLen), SIG_EVERYWHERE, "Zr", NULL }, - { MAP_CALL(StrCpy), SIG_EVERYWHERE, "rZri*", NULL }, - { MAP_CALL(Format), SIG_EVERYWHERE, "r.*", NULL }, - { MAP_CALL(GetFarText), SIG_EVERYWHERE, "iiZr", NULL }, - { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL }, - { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL }, - { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "ol*", NULL }, - { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "ol*", NULL }, - { MAP_CALL(OnControl), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(InitBresen), SIG_EVERYWHERE, "oi*", NULL }, - { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL }, - { MAP_CALL(SetDebug), SIG_EVERYWHERE, "i*", NULL }, - { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL }, - { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i.*", NULL }, - { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL }, - { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL }, - { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r.*", NULL }, - { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL }, - { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL }, - { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL }, - { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL }, - { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(GetDistance), SIG_EVERYWHERE, "iiiii*", NULL, NULL }, + { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(GetTime), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rri*", NULL, NULL }, + { MAP_CALL(StrLen), SIG_EVERYWHERE, "Zr", NULL, NULL }, + { MAP_CALL(StrCpy), SIG_EVERYWHERE, "rZri*", NULL, NULL }, + { MAP_CALL(Format), SIG_EVERYWHERE, "r.*", NULL, NULL }, + { MAP_CALL(GetFarText), SIG_EVERYWHERE, "iiZr", NULL, NULL }, + { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, + { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL }, + { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL }, + { MAP_CALL(OnControl), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(InitBresen), SIG_EVERYWHERE, "oi*", NULL, NULL }, + { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, + { MAP_CALL(SetDebug), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL }, + { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, + { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r.*", NULL, NULL }, + { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL, NULL }, + { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, ".*", NULL, NULL }, // ^^ FIXME accepts a parameter in SCI2+ games - { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL }, - { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(Joystick), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(FileIO), SIG_EVERYWHERE, "i.*", NULL }, - { MAP_CALL(Memory), SIG_EVERYWHERE, "i.*", NULL }, - { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL }, - { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii.*", NULL }, - { MAP_CALL(Lock), SIG_EVERYWHERE, "iii*", NULL }, - { MAP_CALL(Palette), SIG_EVERYWHERE, "i.*", NULL }, - { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL }, - { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rrZr", NULL }, - { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL }, - { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL }, - { MAP_CALL(Message), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL }, - { MAP_CALL(DoAudio), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(DoSync), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "iri*", NULL }, - { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL }, - { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL }, - { MAP_CALL(ResCheck), SIG_EVERYWHERE, "iii*", NULL }, - { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL }, - { MAP_CALL(ShowMovie), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(Platform), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(TextColors), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(TextFonts), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(Portrait), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(PalVary), SIG_EVERYWHERE, "ii*", NULL }, - { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL }, - { MAP_CALL(Empty), SIG_EVERYWHERE, ".*", NULL }, + { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Joystick), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(FileIO), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(Memory), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, + { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii.*", NULL, NULL }, + { MAP_CALL(Lock), SIG_EVERYWHERE, "iii*", NULL, NULL }, + { MAP_CALL(Palette), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL }, + { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rrZr", NULL, NULL }, + { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL }, + { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(Message), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL }, + { MAP_CALL(DoAudio), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(DoSync), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "iri*", NULL, NULL }, + { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL }, + { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL }, + { MAP_CALL(ResCheck), SIG_EVERYWHERE, "iii*", NULL, NULL }, + { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(ShowMovie), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Platform), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(TextColors), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(TextFonts), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Portrait), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(PalVary), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Empty), SIG_EVERYWHERE, ".*", NULL, NULL }, #ifdef ENABLE_SCI32 // SCI2 Kernel Functions - { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(Array), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL }, - { MAP_CALL(String), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL }, - { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL }, - { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li.*", NULL }, - { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li.*", NULL }, - { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li.*", NULL }, - { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "lZo", NULL }, - { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio.*", NULL }, - { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL }, - { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i.*", NULL }, + { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(Array), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL }, + { MAP_CALL(String), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li.*", NULL, NULL }, + { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li.*", NULL, NULL }, + { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li.*", NULL, NULL }, + { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "lZo", NULL, NULL }, + { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL }, + { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, + { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i.*", NULL, NULL }, // SCI2.1 Kernel Functions - { MAP_CALL(Save), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(List), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(Robot), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(PlayVMD), SIG_EVERYWHERE, ".*", NULL }, - { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL }, - { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL }, - { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL }, - { NULL, NULL, SIG_EVERYWHERE, NULL, NULL } + { MAP_CALL(Save), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(List), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(PlayVMD), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL }, + { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, + { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL, NULL }, + { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } #endif }; -- cgit v1.2.3 From 2e58bdc20237ce328ded894d19f3c27dfa475035 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 21:41:36 +0000 Subject: SCI: implemented version specific signatures, added special kDrawCel signature for SCI1.1 (PC)/kq6 svn-id: r50507 --- engines/sci/engine/kernel.cpp | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 40ee003cde..f251613991 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -225,14 +225,15 @@ struct SciKernelMapEntry { #define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE #define SIGFOR_ALL 0x4f -#define SIGFOR_PC 1 << 0 +#define SIGFOR_DOS 1 << 0 #define SIGFOR_PC98 1 << 1 #define SIGFOR_WIN 1 << 2 #define SIGFOR_MAC 1 << 3 #define SIGFOR_AMIGA 1 << 4 #define SIGFOR_ATARI 1 << 5 +#define SIGFOR_PC SIGFOR_DOS|SIGFOR_WIN -#define SIG_EVERYWHERE SIG_SCI32, SIGFOR_ALL +#define SIG_EVERYWHERE SIG_SCIALL, SIGFOR_ALL #define MAP_CALL(_name_) #_name_, k##_name_ @@ -258,7 +259,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL, NULL }, { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL, NULL }, - { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*r*", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiiii*i*r*", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*", NULL, NULL }, { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL, NULL }, { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL, NULL }, { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL, NULL }, @@ -595,10 +597,11 @@ void Kernel::mapFunctions() { int ignored = 0; uint functionCount = _kernelNames.size(); byte platformMask = 0; + SciVersion myVersion = getSciVersion(); switch (g_sci->getPlatform()) { case Common::kPlatformPC: - platformMask = SIGFOR_PC; + platformMask = SIGFOR_DOS; break; case Common::kPlatformPC98: platformMask = SIGFOR_PC98; @@ -647,8 +650,10 @@ void Kernel::mapFunctions() { bool nameMatch = false; while (kernelMap->name) { if (sought_name == kernelMap->name) { - if (platformMask & kernelMap->forPlatform) - break; + if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion >= myVersion)) + if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion <= myVersion)) + if (platformMask & kernelMap->forPlatform) + break; nameMatch = true; } kernelMap++; -- cgit v1.2.3 From 0f28c799f013372c88dd420d084645b5275edb62 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 21:47:34 +0000 Subject: SCI: added mac-specific signature for kGetEvent svn-id: r50508 --- engines/sci/engine/kernel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index f251613991..9b492535d2 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -272,8 +272,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL, NULL }, { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL, NULL }, { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(GetEvent), SIG_EVERYWHERE, "ioi*", NULL, NULL }, - // ^^ FIXME Mac versions pass an extra 3rd parameter (ignored - always 0?) + { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "ioi*", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL }, { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL, NULL }, { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL, NULL }, { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, -- cgit v1.2.3 From 97186bd5b03e012776bd3894e417a25118444ca9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 29 Jun 2010 21:53:27 +0000 Subject: SCI: added sci32-specific signature for kGetSaveDir svn-id: r50509 --- engines/sci/engine/kernel.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 9b492535d2..7a2e34a207 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -346,8 +346,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL, NULL }, { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL, NULL }, { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL, NULL }, - { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, ".*", NULL, NULL }, - // ^^ FIXME accepts a parameter in SCI2+ games + { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "r*", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL, NULL }, { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, -- cgit v1.2.3 From 9f1413b338da98139efb68434f7f875e2abbd745 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 07:18:43 +0000 Subject: When deleting a list node, erase its references to predecessor and successor nodes. Fixes cases where game scripts could reference a list node after it was deleted (e.g. QFG1 intro, Longbow when exiting the cave). Some slight cleanup svn-id: r50515 --- engines/sci/engine/klists.cpp | 4 +++- engines/sci/engine/savegame.cpp | 2 -- 2 files changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index eff0e725b8..ef2f40e235 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -346,7 +346,9 @@ reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { if (!n->succ.isNull()) s->_segMan->lookupNode(n->succ)->pred = n->pred; - //s->_segMan->free_Node(node_pos); // TODO + // Erase references to the predecessor and successor nodes + n->pred = NULL_REG; + n->succ = NULL_REG; return make_reg(0, 1); // Signal success } diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index bf7b88b699..b2528fe210 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -74,9 +74,7 @@ SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorT #ifdef USE_OLD_MUSIC_FUNCTIONS static void sync_songlib(Common::Serializer &s, SongLibrary &obj); -#endif -#ifdef USE_OLD_MUSIC_FUNCTIONS static void syncSong(Common::Serializer &s, Song &obj) { s.syncAsSint32LE(obj._handle); s.syncAsSint32LE(obj._resourceNum); -- cgit v1.2.3 From 7c5b31eb6d6e53a91efb9e0575f07055ea626ed0 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 07:28:30 +0000 Subject: Also erase the value of the list node itself when deleting it inside kDeleteKey, as it might be referenced again before the GC is invoked svn-id: r50516 --- engines/sci/engine/klists.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index ef2f40e235..6e01768958 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -346,9 +346,11 @@ reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { if (!n->succ.isNull()) s->_segMan->lookupNode(n->succ)->pred = n->pred; - // Erase references to the predecessor and successor nodes + // Erase the node itself, as the game might reference it + // again before the GC is invoked n->pred = NULL_REG; n->succ = NULL_REG; + n->value = NULL_REG; return make_reg(0, 1); // Signal success } -- cgit v1.2.3 From 1e8b74f9de0e3a6cf265376a1c4d2c9859f68c61 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 07:34:37 +0000 Subject: Updated incorrect comment svn-id: r50517 --- engines/sci/engine/klists.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 6e01768958..25df4bb563 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -346,8 +346,9 @@ reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { if (!n->succ.isNull()) s->_segMan->lookupNode(n->succ)->pred = n->pred; - // Erase the node itself, as the game might reference it - // again before the GC is invoked + // Erase the node itself, as the game might reference it again. + // Happens in the intro of QFG1 and in Longbow, when exiting the + // cave. n->pred = NULL_REG; n->succ = NULL_REG; n->value = NULL_REG; -- cgit v1.2.3 From 764aa1a125e913fb6d9800f97136adcd13fff9ae Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 08:01:19 +0000 Subject: SCI: adding inheritancelevel to uninit workarounds to make them safer svn-id: r50518 --- engines/sci/engine/vm.cpp | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fe37f09f31..a16e048713 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -266,6 +266,7 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in struct UninitializedReadWorkaround { SciGameId gameId; int scriptNr; + int16 inheritanceLevel; const char *objectName; const char *methodName; int localCallOffset; @@ -273,24 +274,24 @@ struct UninitializedReadWorkaround { uint16 newValue; }; -// gameID, scriptNr, object-name, method-name, call,index,replace +// gameID, scriptNr,lvl, object-name, method-name, call,index,replace static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_LSL1, 720, "rm720", "init", -1, 0, 0 }, // age check room - { GID_LSL3, 997, "TheMenuBar", "handleEvent", -1, 1, 0xf }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 928, "Narrator", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions, that's why we use the base-class - { GID_ISLANDBRAIN, 140, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 - { GID_ISLANDBRAIN, 268, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon - { GID_KQ5, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio - { GID_KQ5, 25, "rm025", "doit", -1, 0, 0 }, // inside witch forest, where the walking rock is - { GID_SQ1, 703, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, 703, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) - { GID_SQ4, 928, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller - { GID_SQ6, 0, "Game", "init", -1, 2, 0 }, - { GID_SQ6, 64950, "View", "handleEvent", -1, 0, 0 }, - { (SciGameId)0, -1, NULL, NULL, -1, 0, 0 } + { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu + { GID_LSL1, 720, 0, "rm720", "init", -1, 0, 0 }, // age check room + { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, 0xf }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 0, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio + { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, 0 }, // inside witch forest, where the walking rock is + { GID_SQ1, 703, 0, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller + { GID_SQ6, 0, 0, "Game", "init", -1, 2, 0 }, + { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, 0 }, + { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, 0 } }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -332,12 +333,13 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i // Search if this is a known uninitialized read const UninitializedReadWorkaround *workaround; + int16 inheritanceLevel = 0; Common::String searchObjectName = curObjectName; reg_t searchObject = lastCall->sendp; do { workaround = uninitializedReadWorkarounds; while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->objectName == searchObjectName) + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->inheritanceLevel == inheritanceLevel) && (workaround->objectName == searchObjectName) && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { // Workaround found r[index] = make_reg(0, workaround->newValue); @@ -346,6 +348,7 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i workaround++; } // Go back to the parent + inheritanceLevel++; searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); if (!searchObject.isNull()) searchObjectName = state->_segMan->getObjectName(searchObject); -- cgit v1.2.3 From c7f6a5b286bad600c987922396b7328079890342 Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Wed, 30 Jun 2010 08:27:09 +0000 Subject: Generalize the sound archive framework to be able to open new formats svn-id: r50519 --- engines/draci/draci.cpp | 4 ++-- engines/draci/game.cpp | 2 +- engines/draci/game.h | 2 +- engines/draci/sound.cpp | 10 ++++----- engines/draci/sound.h | 55 +++++++++++++++++++++++++++++++++++++++---------- 5 files changed, 53 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index ee883f9881..202bf6d187 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -123,8 +123,8 @@ int DraciEngine::init() { _itemImagesArchive = new BArchive(itemImagesPath); _stringsArchive = new BArchive(stringsPath); - _soundsArchive = new SoundArchive(soundsPath, kSoundsFrequency); - _dubbingArchive = new SoundArchive(dubbingPath, kDubbingFrequency); + _soundsArchive = new LegacySoundArchive(soundsPath, kSoundsFrequency); + _dubbingArchive = new LegacySoundArchive(dubbingPath, kDubbingFrequency); _sound = new Sound(_mixer); MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); diff --git a/engines/draci/game.cpp b/engines/draci/game.cpp index 23c50b8f63..8f3ad12cfd 100644 --- a/engines/draci/game.cpp +++ b/engines/draci/game.cpp @@ -332,7 +332,7 @@ void Game::handleOrdinaryLoop(int x, int y) { } } -int Game::inventoryPositionFromMouse() { +int Game::inventoryPositionFromMouse() const { const int column = CLIP(scummvm_lround( (_vm->_mouse->getPosX() - kInventoryX + kInventoryItemWidth / 2.) / kInventoryItemWidth) - 1, 0L, (long) kInventoryColumns - 1); diff --git a/engines/draci/game.h b/engines/draci/game.h index 275293074e..21baaed5cc 100644 --- a/engines/draci/game.h +++ b/engines/draci/game.h @@ -335,7 +335,7 @@ public: private: void updateOrdinaryCursor(); void updateInventoryCursor(); - int inventoryPositionFromMouse(); + int inventoryPositionFromMouse() const; void handleOrdinaryLoop(int x, int y); void handleInventoryLoop(); void handleDialogueLoop(); diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index 4fb2fd6309..65e7e41ac4 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -39,7 +39,7 @@ namespace Draci { -void SoundArchive::openArchive(const Common::String &path) { +void LegacySoundArchive::openArchive(const Common::String &path) { // Close previously opened archive (if any) closeArchive(); @@ -103,12 +103,12 @@ void SoundArchive::openArchive(const Common::String &path) { } /** - * @brief SoundArchive close method + * @brief LegacySoundArchive close method * * Closes the currently opened archive. It can be called explicitly to * free up memory. */ -void SoundArchive::closeArchive() { +void LegacySoundArchive::closeArchive() { clearCache(); delete _f; _f = NULL; @@ -123,7 +123,7 @@ void SoundArchive::closeArchive() { * Clears the cache of the open files inside the archive without closing it. * If the files are subsequently accessed, they are read from the disk. */ -void SoundArchive::clearCache() { +void LegacySoundArchive::clearCache() { // Delete all cached data for (uint i = 0; i < _sampleCount; ++i) { _samples[i].close(); @@ -137,7 +137,7 @@ void SoundArchive::clearCache() { * * Loads individual samples from an archive to memory on demand. */ -SoundSample *SoundArchive::getSample(int i, uint freq) { +SoundSample *LegacySoundArchive::getSample(int i, uint freq) { // Check whether requested file exists if (i < 0 || i >= (int) _sampleCount) { return NULL; diff --git a/engines/draci/sound.h b/engines/draci/sound.h index 28379b5429..e4cf7efdec 100644 --- a/engines/draci/sound.h +++ b/engines/draci/sound.h @@ -47,28 +47,61 @@ struct SoundSample { } }; +/** + * An abstract wrapper around archives of sound samples or dubbing. + */ class SoundArchive { public: - SoundArchive(const Common::String &path, uint defaultFreq) : + SoundArchive() { } + virtual ~SoundArchive() { } + + /** + * Returns the number of sound samples in the archive. Zero means that + * a fake empty archive has been opened and the caller may consider + * opening a different one, for example with compressed music. + */ + virtual uint size() const = 0; + + /** + * Checks whether there is an archive opened. Should be called before reading + * from the archive to check whether opening of the archive has succeeded. + */ + virtual bool isOpen() const = 0; + + /** + * Removes cached samples from memory. + */ + virtual void clearCache() = 0; + + /** + * Caches a given sample into memory and returns a pointer into it. We + * own the pointer. If freq is nonzero, then the sample is played at a + * different frequency (only used for uncompressed samples). + */ + virtual SoundSample *getSample(int i, uint freq) = 0; +}; + +/** + * Reads CD.SAM (with dubbing) and CD2.SAM (with sound samples) from the + * original game. + */ +class LegacySoundArchive : public SoundArchive { +public: + LegacySoundArchive(const Common::String &path, uint defaultFreq) : _path(), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) { openArchive(path); } - ~SoundArchive() { closeArchive(); } + virtual ~LegacySoundArchive() { closeArchive(); } void closeArchive(); void openArchive(const Common::String &path); - uint size() const { return _sampleCount; } - - /** - * Checks whether there is an archive opened. Should be called before reading - * from the archive to check whether openArchive() succeeded. - */ - bool isOpen() const { return _opened; } - void clearCache(); + virtual uint size() const { return _sampleCount; } + virtual bool isOpen() const { return _opened; } - SoundSample *getSample(int i, uint freq); + virtual void clearCache(); + virtual SoundSample *getSample(int i, uint freq); private: Common::String _path; ///< Path to file -- cgit v1.2.3 From 7595e7c1bec5e56e9ddaabea4b6af43423e8e002 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 09:47:04 +0000 Subject: SCI: implementing workarounds for kernel calls, removing original code workaround for kDisposeScript / qfg1 room 64 and adding it to workaround table svn-id: r50520 --- engines/sci/engine/kernel.cpp | 11 ++- engines/sci/engine/kernel.h | 16 +++- engines/sci/engine/kscripts.cpp | 4 - engines/sci/engine/vm.cpp | 186 +++++++++++++++++++++++----------------- 4 files changed, 129 insertions(+), 88 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 7a2e34a207..586c552770 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -206,6 +206,12 @@ static const char *s_defaultKernelNames[] = { // i* -> optional multiple integers // .* -> any parameters afterwards (or none) +// gameID, scriptNr,lvl, object-name, method-name, call,index,replace +static const SciWorkaroundEntry kDisposeScript_workarounds[] = { + { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard + SCI_WORKAROUNDENTRY_TERMINATOR +}; + struct SciKernelMapEntry { const char *name; KernelFunc *function; @@ -216,7 +222,7 @@ struct SciKernelMapEntry { const char *signature; const char *subSignatures; // placeholder - const char *workarounds; // placeholder + const SciWorkaroundEntry *workarounds; }; #define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE @@ -243,7 +249,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i.*", NULL, NULL }, // ^^ FIXME - Work around SQ1 bug, when exiting the Ulence flats bar { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, - { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "Oii*", NULL, NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds }, // ^^ FIXME - Work around QfG1 bug { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, @@ -664,6 +670,7 @@ void Kernel::mapFunctions() { if (kernelMap->function) { _kernelFuncs[functNr].func = kernelMap->function; _kernelFuncs[functNr].signature = compileKernelSignature(kernelMap->signature); + _kernelFuncs[functNr].workarounds = kernelMap->workarounds; _kernelFuncs[functNr].isDummy = false; ++mapped; } else { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 6f7b0d569d..b7cd9058e5 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -115,11 +115,25 @@ enum { /* Generic description: */ typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv); +struct SciWorkaroundEntry { + SciGameId gameId; + int scriptNr; + int16 inheritanceLevel; + const char *objectName; + const char *methodName; + int localCallOffset; + int index; + reg_t newValue; +}; + +#define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, { 0, 0 } } + struct KernelFuncWithSignature { KernelFunc *func; /**< The actual function */ - char *signature; /**< KernelFunc signature */ Common::String origName; /**< Original name, in case we couldn't map it */ bool isDummy; + char *signature; + const SciWorkaroundEntry *workarounds; }; enum AutoDetectedFeatures { diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 8f41fbad2e..4f4df7d875 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -228,10 +228,6 @@ reg_t kScriptID(EngineState *s, int argc, reg_t *argv) { reg_t kDisposeScript(EngineState *s, int argc, reg_t *argv) { int script = argv[0].offset; - // Work around QfG1 graveyard bug - if (argv[0].segment) - return s->r_acc; - SegmentId id = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(id); if (scr) { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a16e048713..46fc46da63 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -263,35 +263,100 @@ static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, in return true; } -struct UninitializedReadWorkaround { - SciGameId gameId; +struct SciTrackOriginReply { int scriptNr; - int16 inheritanceLevel; - const char *objectName; - const char *methodName; + Common::String objectName; + Common::String methodName; int localCallOffset; - int index; - uint16 newValue; }; -// gameID, scriptNr,lvl, object-name, method-name, call,index,replace -static const UninitializedReadWorkaround uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, 0xf }, // is used as priority for game menu - { GID_LSL1, 720, 0, "rm720", "init", -1, 0, 0 }, // age check room - { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, 0xf }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, 0 }, // used by various objects that are even translated in foreign versions, that's why we use the base-class - { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, 1 }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 - { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, 0 }, // elements puzzle, gets used before super TextIcon - { GID_KQ5, 0, 0, "", "export 29", -1, 3, 0 }, // called when playing harp for the harpies, is used for kDoAudio - { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, 0 }, // inside witch forest, where the walking rock is - { GID_SQ1, 703, 0, "", "export 1", -1, 0, 0 }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, 0 }, // export 1, but called locally (when shooting at aliens) - { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, 1 }, // sq4cd: method returns this to the caller - { GID_SQ6, 0, 0, "Game", "init", -1, 2, 0 }, - { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, 0 }, - { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, 0 } +static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, bool &workaroundFound, SciTrackOriginReply *trackOrigin) { + EngineState *state = g_sci->getEngineState(); + ExecStack *lastCall = state->xs; + Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); + int curScriptNr = local_script->getScriptNumber(); + + if (lastCall->debugLocalCallOffset != -1) { + // if lastcall was actually a local call search back for a real call + Common::List::iterator callIterator = state->_executionStack.end(); + while (callIterator != state->_executionStack.begin()) { + callIterator--; + ExecStack loopCall = *callIterator; + if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) { + lastCall->debugSelector = loopCall.debugSelector; + lastCall->debugExportId = loopCall.debugExportId; + break; + } + } + } + + Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp); + Common::String curMethodName; + const SciGameId gameId = g_sci->getGameId(); + + if (lastCall->type == EXEC_STACK_TYPE_CALL) { + if (lastCall->debugSelector != -1) { + curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector); + } else if (lastCall->debugExportId != -1) { + curObjectName = ""; + curMethodName = curMethodName.printf("export %d", lastCall->debugExportId); + } + } + + if (workaroundList) { + // Search if there is a workaround for this one + const SciWorkaroundEntry *workaround; + int16 inheritanceLevel = 0; + Common::String searchObjectName = curObjectName; + reg_t searchObject = lastCall->sendp; + do { + workaround = workaroundList; + while (workaround->objectName) { + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->inheritanceLevel == inheritanceLevel) && (workaround->objectName == searchObjectName) + && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { + // Workaround found + workaroundFound = true; + return workaround->newValue; + } + workaround++; + } + + // Go back to the parent + inheritanceLevel++; + searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); + if (!searchObject.isNull()) + searchObjectName = state->_segMan->getObjectName(searchObject); + } while (!searchObject.isNull()); // no parent left? + } + + // give caller origin data + trackOrigin->objectName = curObjectName; + trackOrigin->methodName = curMethodName; + trackOrigin->scriptNr = curScriptNr; + trackOrigin->localCallOffset = lastCall->debugLocalCallOffset; + + workaroundFound = false; + return make_reg(0xFFFF, 0xFFFF); +} + +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { + { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room + { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio + { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is + { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller + { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, + { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, + SCI_WORKAROUNDENTRY_TERMINATOR }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { @@ -299,61 +364,11 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually - EngineState *state = g_sci->getEngineState(); - ExecStack *lastCall = state->xs; - Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); - int curScriptNr = local_script->getScriptNumber(); - - if (lastCall->debugLocalCallOffset != -1) { - // if lastcall was actually a local call search back for a real call - Common::List::iterator callIterator = state->_executionStack.end(); - while (callIterator != state->_executionStack.begin()) { - callIterator--; - ExecStack loopCall = *callIterator; - if ((loopCall.debugSelector != -1) || (loopCall.debugExportId != -1)) { - lastCall->debugSelector = loopCall.debugSelector; - lastCall->debugExportId = loopCall.debugExportId; - break; - } - } - } - - Common::String curObjectName = state->_segMan->getObjectName(lastCall->sendp); - Common::String curMethodName; - const SciGameId gameId = g_sci->getGameId(); - - if (lastCall->type == EXEC_STACK_TYPE_CALL) { - if (lastCall->debugSelector != -1) { - curMethodName = g_sci->getKernel()->getSelectorName(lastCall->debugSelector); - } else if (lastCall->debugExportId != -1) { - curObjectName = ""; - curMethodName = curMethodName.printf("export %d", lastCall->debugExportId); - } - } - - // Search if this is a known uninitialized read - const UninitializedReadWorkaround *workaround; - int16 inheritanceLevel = 0; - Common::String searchObjectName = curObjectName; - reg_t searchObject = lastCall->sendp; - do { - workaround = uninitializedReadWorkarounds; - while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->inheritanceLevel == inheritanceLevel) && (workaround->objectName == searchObjectName) - && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { - // Workaround found - r[index] = make_reg(0, workaround->newValue); - return r[index]; - } - workaround++; - } - // Go back to the parent - inheritanceLevel++; - searchObject = state->_segMan->getObject(searchObject)->getSuperClassSelector(); - if (!searchObject.isNull()) - searchObjectName = state->_segMan->getObjectName(searchObject); - } while (!searchObject.isNull()); // no parent left? - error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, curObjectName.c_str(), curMethodName.c_str(), curScriptNr, lastCall->debugLocalCallOffset); + bool workaroundFound; + SciTrackOriginReply originReply; + r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, workaroundFound, &originReply); + if (!workaroundFound) + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } return r[index]; } else @@ -770,7 +785,16 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { if (kernelFunc.signature && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, s->xs->sp + 1)) { - error("[VM] Invalid arguments to kernel call k%s (funcNr %x)", g_sci->getKernel()->getKernelName(kernelFuncNr).c_str(), kernelFuncNr); + // signature mismatch, check if a workaround is available + bool workaroundFound; + SciTrackOriginReply originReply; + reg_t workaround; + workaround = trackOriginAndFindWorkaround(0, kernelFunc.workarounds, workaroundFound, &originReply); + if (!workaroundFound) + error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", g_sci->getKernel()->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (!workaround.segment) + return; } reg_t *argv = s->xs->sp + 1; -- cgit v1.2.3 From 8752eed8f241ae2c405a2818b3e30ef735019662 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 09:51:21 +0000 Subject: SCI: Reverting r50516, SSCI didn't reset the node value when deleting the node. Also, a slight fix in VM debug code. svn-id: r50521 --- engines/sci/engine/klists.cpp | 7 +++---- engines/sci/engine/vm.cpp | 2 +- 2 files changed, 4 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 25df4bb563..6842c9b1d8 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -346,12 +346,11 @@ reg_t kDeleteKey(EngineState *s, int argc, reg_t *argv) { if (!n->succ.isNull()) s->_segMan->lookupNode(n->succ)->pred = n->pred; - // Erase the node itself, as the game might reference it again. - // Happens in the intro of QFG1 and in Longbow, when exiting the - // cave. + // Erase references to the predecessor and successor nodes, as the game + // scripts could reference the node itself again. + // Happens in the intro of QFG1 and in Longbow, when exiting the cave. n->pred = NULL_REG; n->succ = NULL_REG; - n->value = NULL_REG; return make_reg(0, 1); // Signal success } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 46fc46da63..4e0c2710c1 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -815,7 +815,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { #if 0 // Used for debugging Common::String debugMsg = kernelFunc.origName + - Common::String::printf("[0x%x]", kernelFuncNum) + + Common::String::printf("[0x%x]", kernelFuncNr) + Common::String::printf(", %d params: ", argc) + " ("; -- cgit v1.2.3 From 915b9fa318435df1dc8a9865f5784cb8a9e8e12f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 10:09:07 +0000 Subject: SCI: removing full debug output when signature fails to the point where we didnt find a workaround for a signature mismatch svn-id: r50522 --- engines/sci/engine/kernel.cpp | 27 ++++++++++----------------- engines/sci/engine/vm.cpp | 23 +++++++++++++---------- 2 files changed, 23 insertions(+), 27 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 586c552770..c7a7b4e843 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -795,46 +795,39 @@ void Kernel::signatureDebug(const char *sig, int argc, const reg_t *argv) { } bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { - const char *checkSig = sig; - const reg_t *checkParam = argv; - int checkCount = argc; // Always "match" if no signature is given if (!sig) return true; - while (*checkSig && checkCount) { - if ((*checkSig & KSIG_ANY) != KSIG_ANY) { - int type = findRegType(*checkParam); + while (*sig && argc) { + if ((*sig & KSIG_ANY) != KSIG_ANY) { + int type = findRegType(*argv); if (!type) { warning("[KERNEL] call signature: couldn't determine type of ref %04x:%04x", PRINT_REG(*argv)); - signatureDebug(sig, argc, argv); return false; } - if (!(type & *checkSig)) { + if (!(type & *sig)) { warning("[KERNEL] call signature: %d args left, is %d, should be %d", argc, type, *sig); - signatureDebug(sig, argc, argv); return false; } } - if (!(*checkSig & KSIG_ELLIPSIS)) - ++checkSig; - ++checkParam; - --checkCount; + if (!(*sig & KSIG_ELLIPSIS)) + ++sig; + ++argv; + --argc; } - if (checkCount) { + if (argc) { warning("[KERNEL] call signature: too many arguments"); - signatureDebug(sig, argc, argv); return false; // Too many arguments } - if (*checkSig == 0 || (*checkSig & KSIG_ELLIPSIS)) + if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) return true; warning("[KERNEL] call signature: too few arguments"); - signatureDebug(sig, argc, argv); return false; } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 4e0c2710c1..a7db23b5ec 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -777,21 +777,24 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { } static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { + Kernel *kernel = g_sci->getKernel(); - if (kernelFuncNr >= (int)g_sci->getKernel()->_kernelFuncs.size()) + if (kernelFuncNr >= (int)kernel->_kernelFuncs.size()) error("Invalid kernel function 0x%x requested", kernelFuncNr); - const KernelFuncWithSignature &kernelFunc = g_sci->getKernel()->_kernelFuncs[kernelFuncNr]; + const KernelFuncWithSignature &kernelCall = kernel->_kernelFuncs[kernelFuncNr]; - if (kernelFunc.signature - && !g_sci->getKernel()->signatureMatch(kernelFunc.signature, argc, s->xs->sp + 1)) { + if (kernelCall.signature + && !kernel->signatureMatch(kernelCall.signature, argc, s->xs->sp + 1)) { // signature mismatch, check if a workaround is available bool workaroundFound; SciTrackOriginReply originReply; reg_t workaround; - workaround = trackOriginAndFindWorkaround(0, kernelFunc.workarounds, workaroundFound, &originReply); - if (!workaroundFound) - error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", g_sci->getKernel()->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, workaroundFound, &originReply); + if (!workaroundFound) { + kernel->signatureDebug(kernelCall.signature, argc, s->xs->sp + 1); + error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernel->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + } // FIXME: implement some real workaround type logic - ignore call, still do call etc. if (!workaround.segment) return; @@ -799,7 +802,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { reg_t *argv = s->xs->sp + 1; - if (!kernelFunc.isDummy) { + if (!kernelCall.isDummy) { // Add stack frame to indicate we're executing a callk. // This is useful in debugger backtraces if this // kernel function calls a script itself. @@ -810,7 +813,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function - s->r_acc = kernelFunc.func(s, argc, argv); + s->r_acc = kernelCall.func(s, argc, argv); #if 0 // Used for debugging @@ -832,7 +835,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { if (s->_executionStack.begin() != s->_executionStack.end()) s->_executionStack.pop_back(); } else { - Common::String warningMsg = "Dummy function " + kernelFunc.origName + + Common::String warningMsg = "Dummy function " + kernelCall.origName + Common::String::printf("[0x%x]", kernelFuncNr) + " invoked - ignoring. Params: " + Common::String::printf("%d", argc) + " ("; -- cgit v1.2.3 From 0c283ed197d839cb81e5957424833700ada1c4ae Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 30 Jun 2010 10:13:20 +0000 Subject: Replaced Y offset from various drawing routines in favour of a viewport sub-surface - this will make it easier to clip sprites to within the drawable area svn-id: r50523 --- engines/m4/graphics.cpp | 3 ++- engines/m4/graphics.h | 14 ++++++++++++++ engines/m4/mads_anim.cpp | 2 +- engines/m4/mads_views.cpp | 38 ++++++++++++++++++++++++-------------- engines/m4/mads_views.h | 11 ++++++----- 5 files changed, 47 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 43df6e1b5f..56c40a7402 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -74,7 +74,8 @@ M4Surface::~M4Surface() { _madsVm->_palette->deleteRange(_rgbList); delete _rgbList; } - free(); + if (_ownsData) + free(); } void M4Surface::loadCodesM4(Common::SeekableReadStream *source) { diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 96cd039e27..5e97d4f09b 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -97,6 +97,7 @@ private: byte _color; bool _isScreen; RGBList *_rgbList; + bool _ownsData; void rexLoadBackground(Common::SeekableReadStream *source, RGBList **palData = NULL); void madsLoadBackground(int roomNumber, RGBList **palData = NULL); @@ -106,12 +107,24 @@ public: create(g_system->getWidth(), isScreen ? g_system->getHeight() : MADS_SURFACE_HEIGHT, 1); _isScreen = isScreen; _rgbList = NULL; + _ownsData = true; } M4Surface(int width_, int height_) { create(width_, height_, 1); _isScreen = false; _rgbList = NULL; + _ownsData = true; } + M4Surface(int width_, int height_, byte *srcPixels, int pitch_) { + bytesPerPixel = 1; + w = width_; + h = height_; + pitch = pitch_; + pixels = srcPixels; + _rgbList = NULL; + _ownsData = false; + } + virtual ~M4Surface(); // loads a .COD file into the M4Surface @@ -143,6 +156,7 @@ public: inline Common::Rect bounds() const { return Common::Rect(0, 0, width(), height()); } inline int width() const { return w; } inline int height() const { return h; } + inline int getPitch() const { return pitch; } void setSize(int sizeX, int sizeY) { create(sizeX, sizeY, 1); } inline byte *getBasePtr() { return (byte *)pixels; diff --git a/engines/m4/mads_anim.cpp b/engines/m4/mads_anim.cpp index ebc684bec4..ca53bdca75 100644 --- a/engines/m4/mads_anim.cpp +++ b/engines/m4/mads_anim.cpp @@ -446,7 +446,7 @@ AnimviewView::AnimviewView(MadsM4Engine *vm): MadsView::_bgSurface = &_backgroundSurface; MadsView::_depthSurface = &_codeSurface; - MadsView::_yOffset = MADS_Y_OFFSET; + MadsView::setViewport(Common::Rect(0, MADS_Y_OFFSET, MADS_SURFACE_WIDTH, MADS_Y_OFFSET + MADS_SURFACE_HEIGHT)); _screenType = VIEWID_ANIMVIEW; _screenFlags.layer = LAYER_BACKGROUND; diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 1766603dc8..c9aacbad4e 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -133,7 +133,7 @@ bool sortHelper(const DepthEntry &entry1, const DepthEntry &entry2) { typedef Common::List DepthList; -void MadsSpriteSlots::drawBackground(int yOffset) { +void MadsSpriteSlots::drawBackground() { // Draw all active sprites onto the background surface for (int i = 0; i < startIndex; ++i) { MadsSpriteSlot &slot = _entries[i]; @@ -173,7 +173,7 @@ void MadsSpriteSlots::drawBackground(int yOffset) { _owner._dirtyAreas[i].active = false; } -void MadsSpriteSlots::drawForeground(View *view, int yOffset) { +void MadsSpriteSlots::drawForeground(M4Surface *viewport) { DepthList depthList; // Get a list of sprite object depths for active objects @@ -199,7 +199,7 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { // Minimalised drawing assert(slot.spriteListIndex < (int)_sprites.size()); M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - view->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, + viewport->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, 0), slot.depth, _owner._depthSurface, slot.scale, spr->getTransparencyIndex()); } else { int xp, yp; @@ -215,11 +215,11 @@ void MadsSpriteSlots::drawForeground(View *view, int yOffset) { if (slot.depth > 1) { // Draw the frame with depth processing - view->copyFrom(spr, xp, yp, Common::Point(0, yOffset), slot.depth, _owner._depthSurface, 100, + viewport->copyFrom(spr, xp, yp, Common::Point(0, 0), slot.depth, _owner._depthSurface, 100, spr->getTransparencyIndex()); } else { // No depth, so simply draw the image - spr->copyTo(view, xp, yp + yOffset, spr->getTransparencyIndex()); + spr->copyTo(viewport, xp, yp, spr->getTransparencyIndex()); } } } @@ -332,12 +332,12 @@ void MadsTextDisplay::setDirtyAreas2() { } } -void MadsTextDisplay::draw(View *view, int yOffset) { +void MadsTextDisplay::draw(M4Surface *view) { for (uint idx = 0; idx < _entries.size(); ++idx) { if (_entries[idx].active && (_entries[idx].expire >= 0)) { _entries[idx].font->setColours(_entries[idx].colour1, _entries[idx].colour2, 0); _entries[idx].font->writeString(view, _entries[idx].msg, - _entries[idx].bounds.left, _entries[idx].bounds.top + yOffset, _entries[idx].bounds.width(), + _entries[idx].bounds.left, _entries[idx].bounds.top, _entries[idx].bounds.width(), _entries[idx].spacing); } } @@ -859,7 +859,7 @@ void MadsDirtyAreas::mergeAreas(int idx1, int idx2) { da1.textActive = true; } -void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset, const Common::Point &posAdjust) { +void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust) { for (uint i = 0; i < _entries.size(); ++i) { const Common::Rect &srcBounds = _entries[i].bounds; @@ -867,7 +867,7 @@ void MadsDirtyAreas::copy(M4Surface *dest, M4Surface *src, int yOffset, const Co srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y); if (_entries[i].active && _entries[i].bounds.isValidRect()) - src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top + yOffset); + src->copyTo(dest, bounds, _entries[i].bounds.left, _entries[i].bounds.top); } } @@ -1195,20 +1195,24 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL _abortTimersMode = ABORTMODE_0; _abortTimersMode2 = ABORTMODE_0; - _yOffset = 0; _depthSurface = NULL; _bgSurface = NULL; + _viewport = NULL; _sceneAnimation = new MadsAnimation(_vm, this); } MadsView::~MadsView() { delete _sceneAnimation; + delete _viewport; } void MadsView::refresh() { + if (!_viewport) + setViewport(_view->bounds()); + // Draw any sprites _dirtyAreas.clear(); - _spriteSlots.drawBackground(_yOffset); + _spriteSlots.drawBackground(); // Process dirty areas _textDisplay.setDirtyAreas(); @@ -1217,7 +1221,7 @@ void MadsView::refresh() { _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); // Copy dirty areas to the main display surface - _dirtyAreas.copy(_view, _bgSurface, _yOffset, _posAdjust); + _dirtyAreas.copy(_viewport, _bgSurface, _posAdjust); // Handle dirty areas for foreground objects _spriteSlots.setDirtyAreas(); @@ -1225,10 +1229,10 @@ void MadsView::refresh() { _dirtyAreas.merge(1, DIRTY_AREAS_SIZE); // Draw foreground sprites - _spriteSlots.drawForeground(_view, _yOffset); + _spriteSlots.drawForeground(_viewport); // Draw text elements onto the view - _textDisplay.draw(_view, _yOffset); + _textDisplay.draw(_viewport); // Remove any sprite slots that are no longer needed _spriteSlots.cleanUp(); @@ -1248,4 +1252,10 @@ void MadsView::clearLists() { _spriteSlots.clear(); } +void MadsView::setViewport(const Common::Rect &bounds) { + delete _viewport; + _viewport = new M4Surface(bounds.width(), bounds.height(), _view->getBasePtr(bounds.left, bounds.top), + _view->getPitch()); +} + } // End of namespace M4 diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 8bc507f20b..2fbe6a6dc7 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -97,8 +97,8 @@ public: void clear(); void deleteTimer(int seqIndex); - void drawBackground(int yOffset); - void drawForeground(View *view, int yOffset); + void drawBackground(); + void drawForeground(M4Surface *viewport); void setDirtyAreas(); void fullRefresh(); void cleanUp(); @@ -139,7 +139,7 @@ public: int add(int xp, int yp, uint fontColour, int charSpacing, const char *msg, Font *font); void clear(); - void draw(View *view, int yOffset); + void draw(M4Surface *view); void setDirtyAreas(); void setDirtyAreas2(); void cleanUp(); @@ -293,7 +293,7 @@ public: void merge(int startIndex, int count); bool intersects(int idx1, int idx2); void mergeAreas(int idx1, int idx2); - void copy(M4Surface *dest, M4Surface *src, int yOffset, const Common::Point &posAdjust); + void copy(M4Surface *dest, M4Surface *src, const Common::Point &posAdjust); void clear(); }; @@ -403,7 +403,7 @@ public: M4Surface *_depthSurface; M4Surface *_bgSurface; - int _yOffset; + M4Surface *_viewport; public: MadsView(View *view); ~MadsView(); @@ -411,6 +411,7 @@ public: void refresh(); void update(); void clearLists(); + void setViewport(const Common::Rect &bounds); }; } -- cgit v1.2.3 From 8de571556012eae3cff13b3b86f8554b5ba070b4 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 30 Jun 2010 10:17:54 +0000 Subject: Removed deprecated destAdjust parameters from the frame drawing code svn-id: r50524 --- engines/m4/graphics.cpp | 8 ++++---- engines/m4/graphics.h | 4 ++-- engines/m4/mads_views.cpp | 11 +++++------ 3 files changed, 11 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 56c40a7402..107bcbc6f9 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -401,8 +401,8 @@ void M4Surface::copyFrom(M4Surface *src, const Common::Rect &srcBounds, int dest * Copies a given image onto a destination surface with scaling, transferring only pixels that meet * the specified depth requirement on a secondary surface contain depth information */ -void M4Surface::copyFrom(M4Surface *src, int destX, int destY, Common::Point destAdjust, - int depth, M4Surface *depthsSurface, int scale, int transparentColour) { +void M4Surface::copyFrom(M4Surface *src, int destX, int destY, int depth, + M4Surface *depthsSurface, int scale, int transparentColour) { if (scale == 100) { // Copy the specified area @@ -428,7 +428,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, Common::Point des byte *srcPtr = data + (src->width() * copyRect.top + copyRect.left); byte *depthsData = depthsSurface->getBasePtr(); byte *depthsPtr = depthsData + (depthsSurface->pitch * destY) + destX; - byte *destPtr = (byte *)pixels + ((destY + destAdjust.y) * pitch) + destX + destAdjust.x; + byte *destPtr = (byte *)pixels + (destY * pitch) + destX; // 100% scaling variation for (int rowCtr = 0; rowCtr < copyRect.height(); ++rowCtr) { @@ -521,7 +521,7 @@ void M4Surface::copyFrom(M4Surface *src, int destX, int destY, Common::Point des if (spriteHeight <= 0) return; - byte *destPixelsP = this->getBasePtr(destX + spriteLeft + destAdjust.x, destY + spriteTop + destAdjust.y); + byte *destPixelsP = this->getBasePtr(destX + spriteLeft, destY + spriteTop); const byte *depthPixelsP = depthsSurface->getBasePtr(destX + spriteLeft, destY + spriteTop); spriteLeft = (spriteLeft * (normalFrame ? 1 : -1)); diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index 5e97d4f09b..c2eb11c575 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -173,7 +173,7 @@ public: void frameRect(const Common::Rect &r, uint8 color); void fillRect(const Common::Rect &r, uint8 color); void copyFrom(M4Surface *src, const Common::Rect &srcBounds, int destX, int destY, int transparentColour = -1); - void copyFrom(M4Surface *src, int destX, int destY, Common::Point destAdjust, int depth, M4Surface *depthSurface, + void copyFrom(M4Surface *src, int destX, int destY, int depth, M4Surface *depthSurface, int scale, int transparentColour = -1); void update() { @@ -196,7 +196,7 @@ public: } inline void copyTo(M4Surface *dest, int destX, int destY, int depth, M4Surface *depthsSurface, int scale, int transparentColour = -1) { - dest->copyFrom(this, destX, destY, Common::Point(0, 0), depth, depthsSurface, scale, transparentColour); + dest->copyFrom(this, destX, destY, depth, depthsSurface, scale, transparentColour); } void scrollX(int xAmount); diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index c9aacbad4e..21ea3a75cb 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -158,8 +158,8 @@ void MadsSpriteSlots::drawBackground() { if (slot.depth > 1) { // Draw the frame with depth processing - _owner._bgSurface->copyFrom(frame, xp, yp, Common::Point(), slot.depth, - _owner._depthSurface, 100, frame->getTransparencyIndex()); + _owner._bgSurface->copyFrom(frame, xp, yp, slot.depth, _owner._depthSurface, 100, + frame->getTransparencyIndex()); } else { // No depth, so simply draw the image frame->copyTo(_owner._bgSurface, xp, yp, frame->getTransparencyIndex()); @@ -199,8 +199,8 @@ void MadsSpriteSlots::drawForeground(M4Surface *viewport) { // Minimalised drawing assert(slot.spriteListIndex < (int)_sprites.size()); M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); - viewport->copyFrom(spr, slot.xp, slot.yp, Common::Point(0, 0), slot.depth, _owner._depthSurface, - slot.scale, spr->getTransparencyIndex()); + viewport->copyFrom(spr, slot.xp, slot.yp, slot.depth, _owner._depthSurface, slot.scale, + spr->getTransparencyIndex()); } else { int xp, yp; M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1); @@ -215,8 +215,7 @@ void MadsSpriteSlots::drawForeground(M4Surface *viewport) { if (slot.depth > 1) { // Draw the frame with depth processing - viewport->copyFrom(spr, xp, yp, Common::Point(0, 0), slot.depth, _owner._depthSurface, 100, - spr->getTransparencyIndex()); + viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, spr->getTransparencyIndex()); } else { // No depth, so simply draw the image spr->copyTo(viewport, xp, yp, spr->getTransparencyIndex()); -- cgit v1.2.3 From c6695b1d6aa778575f4cefc1942253cbb8a65fbf Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 10:31:23 +0000 Subject: SCI: removing all the remaining debug output from signature matching svn-id: r50525 --- engines/sci/engine/kernel.cpp | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c7a7b4e843..2eeefe83d9 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -771,7 +771,11 @@ void Kernel::signatureDebug(const char *sig, int argc, const reg_t *argv) { if (argc) { reg_t parameter = *argv; printf("%04x:%04x (", PRINT_REG(parameter)); - kernelSignatureDebugType(findRegType(parameter)); + int regType = findRegType(parameter); + if (regType) + kernelSignatureDebugType(regType); + else + printf("unknown type of %04x:%04x", PRINT_REG(parameter)); printf(")"); argv++; argc--; @@ -803,15 +807,11 @@ bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { if ((*sig & KSIG_ANY) != KSIG_ANY) { int type = findRegType(*argv); - if (!type) { - warning("[KERNEL] call signature: couldn't determine type of ref %04x:%04x", PRINT_REG(*argv)); - return false; - } + if (!type) + return false; // couldn't determine type - if (!(type & *sig)) { - warning("[KERNEL] call signature: %d args left, is %d, should be %d", argc, type, *sig); - return false; - } + if (!(type & *sig)) + return false; // type mismatch } if (!(*sig & KSIG_ELLIPSIS)) @@ -820,15 +820,12 @@ bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { --argc; } - if (argc) { - warning("[KERNEL] call signature: too many arguments"); + if (argc) return false; // Too many arguments - } if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) return true; - warning("[KERNEL] call signature: too few arguments"); - return false; + return false; // Too few arguments } void Kernel::setDefaultKernelNames() { -- cgit v1.2.3 From dcba035912fb876f1db8da998405a659b9c87d04 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 30 Jun 2010 10:42:34 +0000 Subject: Corrected font display to properly use both colour indexes svn-id: r50526 --- engines/m4/animation.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index 51d3970e12..f9dd8287ae 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -444,7 +444,7 @@ void MadsAnimation::update() { _vm->_palette->setEntry(colIndex + 1, me.rgb2.r, me.rgb2.g, me.rgb2.b); // Add a kernel message to display the given text - me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101, 0, 0, INDEFINITE_TIMEOUT, me.msg); + me.kernelMsgIndex = _view->_kernelMessages.add(me.pos, colIndex * 0x101 + 0x100, 0, 0, INDEFINITE_TIMEOUT, me.msg); assert(me.kernelMsgIndex >= 0); // Play the associated sound, if it exists -- cgit v1.2.3 From cf5c60ed4f0628496ad97db3c274b7f0325e2440 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 11:05:29 +0000 Subject: SCI: changing signature of kUnLoad, adding workaround for sq1 ulence flats bug svn-id: r50527 --- engines/sci/engine/kernel.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2eeefe83d9..29b6a9bf9e 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -206,6 +206,12 @@ static const char *s_defaultKernelNames[] = { // i* -> optional multiple integers // .* -> any parameters afterwards (or none) +// gameID, scriptNr,lvl, object-name, method-name, call,index,replace +static const SciWorkaroundEntry kUnLoad_workarounds[] = { + { GID_SQ1, 998, 0, "View", "delete", -1, 0, { 1, 0 } }, // exiting ulence flats bar - slotGuyBody::dispose calls view::delete resulting in parameter 1 to be a reference + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call,index,replace static const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard @@ -246,11 +252,9 @@ struct SciKernelMapEntry { // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i.*", NULL, NULL }, - // ^^ FIXME - Work around SQ1 bug, when exiting the Ulence flats bar + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "ii*", NULL, kUnLoad_workarounds }, { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds }, - // ^^ FIXME - Work around QfG1 bug { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, -- cgit v1.2.3 From cb897a1a15bb178f1fdb55378852fb6da707e444 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 11:08:23 +0000 Subject: Changed an error back to a warning - Torin's Passage calls kAddAfter with 4 parameters, and we don't know what the 4th parameter is yet svn-id: r50528 --- engines/sci/engine/klists.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 6842c9b1d8..4f8087539b 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -272,7 +272,8 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { } if (argc == 4) // Torin's Passage - error("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); + // TODO: Find out what the 4th parameter is + warning("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); if (firstnode) { // We're really appending after reg_t oldnext = firstnode->succ; -- cgit v1.2.3 From bf6acef9a9accb1753f87d34c3d5dddd56e36642 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 11:09:49 +0000 Subject: SCI: fixed a typo, so that workarounds really trigger an ignore kernel call for now svn-id: r50529 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a7db23b5ec..48f17d34de 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -796,7 +796,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernel->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. - if (!workaround.segment) + if (workaround.segment) return; } -- cgit v1.2.3 From a14c6d7815e27e76846a2a0feedcbf90785e07c9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 13:31:47 +0000 Subject: Fixed the signature for kUnload (thanks m_kiewitz) svn-id: r50530 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 29b6a9bf9e..ec3cdc5106 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -252,7 +252,7 @@ struct SciKernelMapEntry { // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "ii*", NULL, kUnLoad_workarounds }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "iRi*", NULL, kUnLoad_workarounds }, { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds }, { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, -- cgit v1.2.3 From bff3e89e48a6f819d5b23ba4cc848cbcf35aa965 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 13:49:05 +0000 Subject: SCI: Removed the FreeSCI music code svn-id: r50532 --- engines/sci/console.cpp | 78 -- engines/sci/engine/kernel.h | 12 - engines/sci/engine/kevent.cpp | 2 - engines/sci/engine/kgraphics.cpp | 4 - engines/sci/engine/savegame.cpp | 130 -- engines/sci/engine/state.cpp | 4 - engines/sci/engine/state.h | 8 - engines/sci/module.mk | 3 - engines/sci/sci.cpp | 35 - engines/sci/sci.h | 15 - engines/sci/sound/iterator/core.cpp | 969 -------------- engines/sci/sound/iterator/core.h | 209 --- engines/sci/sound/iterator/iterator.cpp | 1641 ------------------------ engines/sci/sound/iterator/iterator.h | 326 ----- engines/sci/sound/iterator/iterator_internal.h | 276 ---- engines/sci/sound/iterator/songlib.cpp | 189 --- engines/sci/sound/iterator/songlib.h | 171 --- engines/sci/sound/iterator/test-iterator.cpp | 423 ------ engines/sci/sound/music.h | 23 +- engines/sci/sound/soundcmd.cpp | 435 +------ engines/sci/sound/soundcmd.h | 17 - 21 files changed, 4 insertions(+), 4966 deletions(-) delete mode 100644 engines/sci/sound/iterator/core.cpp delete mode 100644 engines/sci/sound/iterator/core.h delete mode 100644 engines/sci/sound/iterator/iterator.cpp delete mode 100644 engines/sci/sound/iterator/iterator.h delete mode 100644 engines/sci/sound/iterator/iterator_internal.h delete mode 100644 engines/sci/sound/iterator/songlib.cpp delete mode 100644 engines/sci/sound/iterator/songlib.h delete mode 100644 engines/sci/sound/iterator/test-iterator.cpp (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index f9d2ac5090..b5fc903108 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -36,13 +36,8 @@ #include "sci/engine/savegame.h" #include "sci/engine/gc.h" #include "sci/engine/features.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/songlib.h" // for SongLibrary -#include "sci/sound/iterator/iterator.h" // for SCI_SONG_ITERATOR_TYPE_SCI0 -#else #include "sci/sound/midiparser_sci.h" #include "sci/sound/music.h" -#endif #include "sci/sound/drivers/mididriver.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" @@ -215,19 +210,11 @@ Console::~Console() { } void Console::preEnter() { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (_engine->_gamestate) - _engine->_gamestate->_sound.sfx_suspend(true); -#endif if (g_sci && g_sci->_soundCmd) g_sci->_soundCmd->pauseAll(true); } void Console::postEnter() { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (_engine->_gamestate) - _engine->_gamestate->_sound.sfx_suspend(false); -#endif if (g_sci && g_sci->_soundCmd) g_sci->_soundCmd->pauseAll(false); @@ -846,7 +833,6 @@ bool Console::cmdVerifyScripts(int argc, const char **argv) { } bool Console::cmdShowInstruments(int argc, const char **argv) { -#ifndef USE_OLD_MUSIC_FUNCTIONS int songNumber = -1; if (argc == 2) @@ -1004,7 +990,6 @@ bool Console::cmdShowInstruments(int argc, const char **argv) { DebugPrintf("\n\n"); } -#endif return true; } @@ -1647,23 +1632,7 @@ bool Console::cmdShowMap(int argc, const char **argv) { bool Console::cmdSongLib(int argc, const char **argv) { DebugPrintf("Song library:\n"); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - Song *seeker = _engine->_gamestate->_sound._songlib._lib; - - do { - DebugPrintf(" %p", (void *)seeker); - - if (seeker) { - DebugPrintf("[%04lx,p=%d,s=%d]->", seeker->_handle, seeker->_priority, seeker->_status); - seeker = seeker->_next; - } - DebugPrintf("\n"); - } while (seeker); - DebugPrintf("\n"); -#else g_sci->_soundCmd->printPlayList(this); -#endif return true; } @@ -1726,19 +1695,6 @@ bool Console::cmdToggleSound(int argc, const char **argv) { return true; } -#ifdef USE_OLD_MUSIC_FUNCTIONS - int handle = id.segment << 16 | id.offset; // frobnicate handle - - if (id.segment) { - SegManager *segMan = _engine->_gamestate->_segMan; // for writeSelectorValue - _engine->_gamestate->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _engine->_gamestate->_sound.sfx_remove_song(handle); - writeSelectorValue(segMan, id, SELECTOR(signal), SIGNAL_OFFSET); - writeSelectorValue(segMan, id, SELECTOR(nodePtr), 0); - writeSelectorValue(segMan, id, SELECTOR(handle), 0); - } -#else - Common::String newState = argv[2]; newState.toLowercase(); @@ -1748,15 +1704,12 @@ bool Console::cmdToggleSound(int argc, const char **argv) { g_sci->_soundCmd->stopSound(id); else DebugPrintf("New state can either be 'play' or 'stop'"); -#endif return true; } bool Console::cmdStopAllSounds(int argc, const char **argv) { -#ifndef USE_OLD_MUSIC_FUNCTIONS g_sci->_soundCmd->stopAllSounds(); -#endif DebugPrintf("All sounds have been stopped\n"); return true; @@ -1770,36 +1723,6 @@ bool Console::cmdIsSample(int argc, const char **argv) { return true; } -#ifdef USE_OLD_MUSIC_FUNCTIONS - Resource *song = _engine->getResMan()->findResource(ResourceId(kResourceTypeSound, atoi(argv[1])), 0); - SongIterator *songit; - Audio::AudioStream *data; - - if (!song) { - DebugPrintf("Not a sound resource!\n"); - return true; - } - - songit = songit_new(song->data, song->size, SCI_SONG_ITERATOR_TYPE_SCI0, 0xcaffe /* What do I care about the ID? */); - - if (!songit) { - DebugPrintf("Could not convert to song iterator!\n"); - return true; - } - - data = songit->getAudioStream(); - if (data) { - // TODO -/* - DebugPrintf("\nIs sample (encoding %dHz/%s/%04x)", data->conf.rate, (data->conf.stereo) ? - ((data->conf.stereo == SFX_PCM_STEREO_LR) ? "stereo-LR" : "stereo-RL") : "mono", data->conf.format); -*/ - delete data; - } else - DebugPrintf("Valid song, but not a sample.\n"); - - delete songit; -#else int16 number = atoi(argv[1]); if (!_engine->getResMan()->testResource(ResourceId(kResourceTypeSound, number))) { @@ -1823,7 +1746,6 @@ bool Console::cmdIsSample(int argc, const char **argv) { DebugPrintf("Sample size: %d, sample rate: %d, channels: %d, digital channel number: %d\n", track->digitalSampleSize, track->digitalSampleRate, track->channelCount, track->digitalChannelNr); -#endif return true; } diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b7cd9058e5..a3cf7b5f91 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -32,7 +32,6 @@ #include "common/str-array.h" #include "sci/engine/selector.h" -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS #include "sci/engine/vm_types.h" // for reg_t #include "sci/engine/vm.h" @@ -268,17 +267,6 @@ private: const Common::String _invalid; }; -#ifdef USE_OLD_MUSIC_FUNCTIONS -/******************** Misc functions ********************/ - -/** - * Get all sound events, apply their changes to the heap. - */ -void process_sound_events(EngineState *s); - -/******************** Constants ********************/ -#endif - /* Maximum length of a savegame name (including terminator character). */ #define SCI_MAX_SAVENAME_LENGTH 0x24 diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index bc8ddc34fc..4086d14a25 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -149,7 +149,6 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { con->onFrame(); } -#ifndef USE_OLD_MUSIC_FUNCTIONS if (g_sci->_features->detectDoSoundType() <= SCI_VERSION_0_LATE) { // If we're running a SCI0 game, update the sound cues, to compensate // for the fact that SCI0 does not poll to update the sound cues itself, @@ -158,7 +157,6 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { // this call g_sci->_soundCmd->updateSci0Cues(); } -#endif return s->r_acc; } diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index c9d3c92603..bacba674d7 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1080,10 +1080,6 @@ reg_t kAnimate(EngineState *s, int argc, reg_t *argv) { reg_t castListReference = (argc > 0) ? argv[0] : NULL_REG; bool cycle = (argc > 1) ? ((argv[1].toUint16()) ? true : false) : false; -#ifdef USE_OLD_MUSIC_FUNCTIONS - // Take care of incoming events (kAnimate is called semi-regularly) - process_sound_events(s); -#endif g_sci->_gfxAnimate->kernelAnimate(castListReference, cycle, argc, argv); return s->r_acc; diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index b2528fe210..7a6496fe63 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -42,12 +42,7 @@ #include "sci/engine/script.h" // for SCI_OBJ_EXPORTS and SCI_OBJ_SYNONYMS #include "sci/graphics/ports.h" #include "sci/sound/audio.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" -#else #include "sci/sound/music.h" -#endif #include "gui/message.h" @@ -61,40 +56,11 @@ namespace Sci { const uint32 INTMAPPER_MAGIC_KEY = 0xDEADBEEF; -#ifdef USE_OLD_MUSIC_FUNCTIONS -// from ksound.cpp: -SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id); -#endif - - #pragma mark - // TODO: Many of the following sync_*() methods should be turned into member funcs // of the classes they are syncing. -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void sync_songlib(Common::Serializer &s, SongLibrary &obj); - -static void syncSong(Common::Serializer &s, Song &obj) { - s.syncAsSint32LE(obj._handle); - s.syncAsSint32LE(obj._resourceNum); - s.syncAsSint32LE(obj._priority); - s.syncAsSint32LE(obj._status); - s.syncAsSint32LE(obj._restoreBehavior); - s.syncAsSint32LE(obj._restoreTime); - s.syncAsSint32LE(obj._loops); - s.syncAsSint32LE(obj._hold); - - if (s.isLoading()) { - obj._it = 0; - obj._delay = 0; - obj._next = 0; - obj._nextPlaying = 0; - obj._nextStopping = 0; - } -} -#else - #define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff)) void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { @@ -148,7 +114,6 @@ void MusicEntry::saveLoadWithSerializer(Common::Serializer &s) { pStreamAud = 0; } } -#endif // Experimental hack: Use syncWithSerializer to sync. By default, this assume // the object to be synced is a subclass of Serializable and thus tries to invoke @@ -380,11 +345,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { syncArray(s, _segMan->_classTable); -#ifdef USE_OLD_MUSIC_FUNCTIONS - sync_songlib(s, _sound._songlib); -#else g_sci->_soundCmd->syncPlayList(s); -#endif } void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { @@ -620,30 +581,6 @@ void DataStack::saveLoadWithSerializer(Common::Serializer &s) { #pragma mark - -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void sync_songlib(Common::Serializer &s, SongLibrary &obj) { - int songcount = 0; - if (s.isSaving()) - songcount = obj.countSongs(); - s.syncAsUint32LE(songcount); - - if (s.isLoading()) { - obj._lib = 0; - while (songcount--) { - Song *newsong = new Song; - syncSong(s, *newsong); - obj.addSong(newsong); - } - } else { - Song *seeker = obj._lib; - while (seeker) { - seeker->_restoreTime = seeker->_it->getTimepos(); - syncSong(s, *seeker); - seeker = seeker->_next; - } - } -} -#else void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { // Sync song lib data. When loading, the actual song lib will be initialized // afterwards in gamestate_restore() @@ -692,16 +629,12 @@ void SciMusic::saveLoadWithSerializer(Common::Serializer &s) { } } } -#endif void SoundCommandParser::syncPlayList(Common::Serializer &s) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->saveLoadWithSerializer(s); -#endif } void SoundCommandParser::reconstructPlayList(int savegame_version) { -#ifndef USE_OLD_MUSIC_FUNCTIONS Common::StackLock lock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); @@ -724,8 +657,6 @@ void SoundCommandParser::reconstructPlayList(int savegame_version) { cmdPlaySound((*i)->soundObj, 0); } } - -#endif } #ifdef ENABLE_SCI32 @@ -819,42 +750,6 @@ void SegManager::reconstructClones() { } // end for } -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void reconstruct_sounds(EngineState *s) { - Song *seeker; - SongIteratorType it_type; - - if (getSciVersion() > SCI_VERSION_01) - it_type = SCI_SONG_ITERATOR_TYPE_SCI1; - else - it_type = SCI_SONG_ITERATOR_TYPE_SCI0; - - seeker = s->_sound._songlib._lib; - - while (seeker) { - SongIterator *base, *ff = 0; - int oldstatus; - SongIterator::Message msg; - - base = ff = build_iterator(g_sci->getResMan(), seeker->_resourceNum, it_type, seeker->_handle); - if (seeker->_restoreBehavior == RESTORE_BEHAVIOR_CONTINUE) - ff = new_fast_forward_iterator(base, seeker->_restoreTime); - ff->init(); - - msg = SongIterator::Message(seeker->_handle, SIMSG_SET_LOOPS(seeker->_loops)); - songit_handle_message(&ff, msg); - msg = SongIterator::Message(seeker->_handle, SIMSG_SET_HOLD(seeker->_hold)); - songit_handle_message(&ff, msg); - - oldstatus = seeker->_status; - seeker->_status = SOUND_STATUS_STOPPED; - seeker->_it = ff; - s->_sound.sfx_song_set_status(seeker->_handle, oldstatus); - seeker = seeker->_next; - } -} -#endif - #pragma mark - @@ -888,10 +783,6 @@ bool gamestate_save(EngineState *s, Common::WriteStream *fh, const char* savenam } void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongLibrary temp; -#endif - SavegameMetadata meta; Common::Serializer ser(fh, 0); @@ -943,21 +834,8 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->reset(true); s->saveLoadWithSerializer(ser); // FIXME: Error handling? -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound.sfx_exit(); -#endif - // Now copy all current state information -#ifdef USE_OLD_MUSIC_FUNCTIONS - temp = s->_sound._songlib; - s->_sound.sfx_init(g_sci->getResMan(), s->sfx_init_flags, g_sci->_features->detectDoSoundType()); - s->sfx_init_flags = s->sfx_init_flags; - s->_sound._songlib.freeSounds(); - s->_sound._songlib = temp; - s->_soundCmd->updateSfxState(&s->_sound); -#endif - s->_segMan->reconstructStack(s); s->_segMan->reconstructScripts(s); s->_segMan->reconstructClones(); @@ -969,15 +847,7 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { s->gameStartTime = g_system->getMillis(); s->_screenUpdateTime = g_system->getMillis(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - s->_sound._it = NULL; - s->_sound._flags = s->_sound._flags; - s->_sound._song = NULL; - s->_sound._suspended = s->_sound._suspended; - reconstruct_sounds(s); -#else g_sci->_soundCmd->reconstructPlayList(meta.savegame_version); -#endif // Message state: s->_msgState = new MessageState(s->_segMan); diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index f13a44e704..6f54a3c199 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -81,10 +81,6 @@ EngineState::~EngineState() { } void EngineState::reset(bool isRestoring) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - sfx_init_flags = 0; -#endif - if (!isRestoring) { _memorySegmentSize = 0; diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 07843a68e3..885c8a871c 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -41,9 +41,6 @@ namespace Common { #include "sci/parser/vocabulary.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#endif #include "sci/sound/soundcmd.h" namespace Sci { @@ -105,11 +102,6 @@ public: /* Non-VM information */ -#ifdef USE_OLD_MUSIC_FUNCTIONS - SfxState _sound; /**< sound subsystem */ - int sfx_init_flags; /**< flags the sfx subsystem was initialised with */ -#endif - uint32 gameStartTime; /**< The time at which the interpreter was started */ uint32 lastWaitTime; /**< The last time the game invoked Wait() */ uint32 _screenUpdateTime; /**< The last time the game updated the screen */ diff --git a/engines/sci/module.mk b/engines/sci/module.mk index 792522f153..85988b8f1b 100644 --- a/engines/sci/module.mk +++ b/engines/sci/module.mk @@ -67,9 +67,6 @@ MODULE_OBJS := \ sound/drivers/fb01.o \ sound/drivers/midi.o \ sound/drivers/pcjr.o \ - sound/iterator/core.o \ - sound/iterator/iterator.o \ - sound/iterator/songlib.o \ video/seq_decoder.o diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index e90ca9de5d..e9e16c8262 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -222,10 +222,6 @@ Common::Error SciEngine::run() { _kernel->loadKernelNames(_features); _soundCmd = new SoundCommandParser(_resMan, segMan, _kernel, _audio, _features->detectDoSoundType()); -#ifdef USE_OLD_MUSIC_FUNCTIONS - initGameSound(0, _features->detectDoSoundType()); -#endif - syncSoundSettings(); // Initialize all graphics related subsystems @@ -313,11 +309,6 @@ bool SciEngine::initGame() { srand(g_system->getMillis()); // Initialize random number generator -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (_gamestate->sfx_init_flags & SFX_STATE_FLAG_NOSOUND) - initGameSound(0, _features->detectDoSoundType()); -#endif - // Load game language into printLang property of game object setSciLanguage(); @@ -399,18 +390,6 @@ void SciEngine::initGraphics() { _gfxPalette->setDefault(); } -#ifdef USE_OLD_MUSIC_FUNCTIONS - -void SciEngine::initGameSound(int sound_flags, SciVersion soundVersion) { - if (getSciVersion() > SCI_VERSION_0_LATE) - sound_flags |= SFX_STATE_FLAG_MULTIPLAY; - - _gamestate->sfx_init_flags = sound_flags; - _gamestate->_sound.sfx_init(_resMan, sound_flags, soundVersion); -} - -#endif - void SciEngine::initStackBaseWithSelector(Selector selector) { _gamestate->stack_base[0] = make_reg(0, (uint16)selector); _gamestate->stack_base[1] = NULL_REG; @@ -438,9 +417,6 @@ void SciEngine::runGame() { if (_gamestate->abortScriptProcessing == kAbortRestartGame) { _gamestate->_segMan->resetSegMan(); initGame(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - _gamestate->_sound.sfx_reset_player(); -#endif initStackBaseWithSelector(SELECTOR(play)); _gamestate->gameWasRestarted = true; } else if (_gamestate->abortScriptProcessing == kAbortLoadGame) { @@ -455,14 +431,8 @@ void SciEngine::runGame() { void SciEngine::exitGame() { if (_gamestate->abortScriptProcessing != kAbortLoadGame) { _gamestate->_executionStack.clear(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - _gamestate->_sound.sfx_exit(); - // Reinit because some other code depends on having a valid state - initGameSound(SFX_STATE_FLAG_NOSOUND, _features->detectDoSoundType()); -#else _audio->stopAllAudio(); g_sci->_soundCmd->clearPlayList(); -#endif } // TODO Free parser segment here @@ -544,16 +514,12 @@ Common::String SciEngine::unwrapFilename(const Common::String &name) const { } void SciEngine::pauseEngineIntern(bool pause) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _gamestate->_sound.sfx_suspend(pause); -#endif _mixer->pauseAll(pause); } void SciEngine::syncSoundSettings() { Engine::syncSoundSettings(); -#ifndef USE_OLD_MUSIC_FUNCTIONS bool mute = false; if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); @@ -564,7 +530,6 @@ void SciEngine::syncSoundSettings() { int vol = (soundVolumeMusic + 1) * SoundCommandParser::kMaxSciVolume / Audio::Mixer::kMaxMixerVolume; g_sci->_soundCmd->setMasterVolume(vol); } -#endif } } // End of namespace Sci diff --git a/engines/sci/sci.h b/engines/sci/sci.h index d7ca1345bf..c09342f749 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -42,9 +42,6 @@ struct ADGameDescription; */ namespace Sci { -// Uncomment this to use old music functions -//#define USE_OLD_MUSIC_FUNCTIONS - struct EngineState; class Vocabulary; class ResourceManager; @@ -321,18 +318,6 @@ private: */ void exitGame(); -#ifdef USE_OLD_MUSIC_FUNCTIONS - /** - * Initializes the sound part of a SCI game - * This function may only be called if game_init() did not initialize - * the sound data. - * @param[in] s The state to initialize the sound in - * @param[in] sound_flags Flags to pass to the sound subsystem - * @param[in] soundVersion sound-version that got detected during game init - */ - void initGameSound(int sound_flags, SciVersion soundVersion); -#endif - void initStackBaseWithSelector(Selector selector); const ADGameDescription *_gameDescription; diff --git a/engines/sci/sound/iterator/core.cpp b/engines/sci/sound/iterator/core.cpp deleted file mode 100644 index 9ecd00f54c..0000000000 --- a/engines/sci/sound/iterator/core.cpp +++ /dev/null @@ -1,969 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Sound subsystem core: Event handler, sound player dispatching */ - -#include "sci/sci.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS - -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" -#include "sci/sound/drivers/mididriver.h" - -#include "common/system.h" -#include "common/timer.h" - -#include "sound/mixer.h" - -namespace Sci { - -/* Plays a song iterator that found a PCM through a PCM device, if possible -** Parameters: (SongIterator *) it: The iterator to play -** (SongHandle) handle: Debug handle -** Returns : (int) 0 if the effect will not be played, nonzero if it will -** This assumes that the last call to 'it->next()' returned SI_PCM. -*/ -static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle); - - -#pragma mark - - - -class SfxPlayer { -public: - /** Number of voices that can play simultaneously */ - int _polyphony; - -protected: - SciVersion _soundVersion; - MidiPlayer *_mididrv; - - SongIterator *_iterator; - Audio::Timestamp _wakeupTime; - Audio::Timestamp _currentTime; - uint32 _pauseTimeDiff; - - bool _paused; - bool _iteratorIsDone; - uint32 _tempo; - - Common::Mutex _mutex; - int _volume; - - void play_song(SongIterator *it); - static void player_timer_callback(void *refCon); - -public: - SfxPlayer(SciVersion soundVersion); - ~SfxPlayer(); - - /** - * Initializes the player. - * @param resMan a resource manager for driver initialization - * @param expected_latency expected delay in between calls to 'maintenance' (in microseconds) - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error init(ResourceManager *resMan, int expected_latency); - - /** - * Adds an iterator to the song player - * @param it The iterator to play - * @param start_time The time to assume as the time the first MIDI command executes at - * @return Common::kNoError on success, Common::kUnknownError on failure - * - * The iterator should not be cloned (to avoid memory leaks) and - * may be modified according to the needs of the player. - * Implementors may use the 'sfx_iterator_combine()' function - * to add iterators onto their already existing iterators. - */ - Common::Error add_iterator(SongIterator *it, uint32 start_time); - - /** - * Stops the currently playing song and deletes the associated iterator. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error stop(); - - /** - * Transmits a song iterator message to the active song. - * @param msg the message to transmit - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error iterator_message(const SongIterator::Message &msg); - - /** - * Pauses song playing. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error pause(); - - /** - * Resumes song playing after a pause. - * @return Common::kNoError on success, Common::kUnknownError on failure - */ - Common::Error resume(); - - /** - * Pass a raw MIDI event to the synth. - * @param argc length of buffer holding the midi event - * @param argv the buffer itself - */ - void tell_synth(int buf_nr, byte *buf); - - void setVolume(int vol); - - int getVolume(); -}; - -SfxPlayer::SfxPlayer(SciVersion soundVersion) - : _soundVersion(soundVersion), _wakeupTime(0, SFX_TICKS_PER_SEC), _currentTime(0, 1) { - _polyphony = 0; - - _mididrv = 0; - - _iterator = NULL; - _pauseTimeDiff = 0; - - _paused = false; - _iteratorIsDone = false; - _tempo = 0; - - _volume = 15; -} - -SfxPlayer::~SfxPlayer() { - if (_mididrv) { - _mididrv->close(); - delete _mididrv; - } - delete _iterator; - _iterator = NULL; -} - -void SfxPlayer::play_song(SongIterator *it) { - while (_iterator && _wakeupTime.msecsDiff(_currentTime) <= 0) { - int delay; - byte buf[8]; - int result; - - switch ((delay = songit_next(&(_iterator), - buf, &result, - IT_READER_MASK_ALL - | IT_READER_MAY_FREE - | IT_READER_MAY_CLEAN))) { - - case SI_FINISHED: - delete _iterator; - _iterator = NULL; - _iteratorIsDone = true; - return; - - case SI_IGNORE: - case SI_LOOP: - case SI_RELATIVE_CUE: - case SI_ABSOLUTE_CUE: - break; - - case SI_PCM: - sfx_play_iterator_pcm(_iterator, 0); - break; - - case 0: - static_cast(_mididrv)->send(buf[0], buf[1], buf[2]); - - break; - - default: - _wakeupTime = _wakeupTime.addFrames(delay); - } - } -} - -void SfxPlayer::tell_synth(int buf_nr, byte *buf) { - byte op1 = (buf_nr < 2 ? 0 : buf[1]); - byte op2 = (buf_nr < 3 ? 0 : buf[2]); - - static_cast(_mididrv)->send(buf[0], op1, op2); -} - -void SfxPlayer::player_timer_callback(void *refCon) { - SfxPlayer *thePlayer = (SfxPlayer *)refCon; - assert(refCon); - Common::StackLock lock(thePlayer->_mutex); - - if (thePlayer->_iterator && !thePlayer->_iteratorIsDone && !thePlayer->_paused) { - thePlayer->play_song(thePlayer->_iterator); - } - - thePlayer->_currentTime = thePlayer->_currentTime.addFrames(1); -} - -/* API implementation */ - -Common::Error SfxPlayer::init(ResourceManager *resMan, int expected_latency) { - MidiDriverType musicDriver = MidiDriver::detectDevice(MDT_PCSPK | MDT_ADLIB); - - switch (musicDriver) { - case MD_ADLIB: - // FIXME: There's no Amiga sound option, so we hook it up to AdLib - if (g_sci->getPlatform() == Common::kPlatformAmiga) - _mididrv = MidiPlayer_Amiga_create(_soundVersion); - else - _mididrv = MidiPlayer_AdLib_create(_soundVersion); - break; - case MD_PCJR: - _mididrv = MidiPlayer_PCJr_create(_soundVersion); - break; - case MD_PCSPK: - _mididrv = MidiPlayer_PCSpeaker_create(_soundVersion); - break; - default: - break; - } - - assert(_mididrv); - - _polyphony = _mididrv->getPolyphony(); - - _tempo = _mididrv->getBaseTempo(); - uint32 time = g_system->getMillis(); - _currentTime = Audio::Timestamp(time, 1000000 / _tempo); - _wakeupTime = Audio::Timestamp(time, SFX_TICKS_PER_SEC); - - _mididrv->setTimerCallback(this, player_timer_callback); - _mididrv->open(resMan); - _mididrv->setVolume(_volume); - - return Common::kNoError; -} - -Common::Error SfxPlayer::add_iterator(SongIterator *it, uint32 start_time) { - Common::StackLock lock(_mutex); - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(_mididrv->getPlayId())); - SIMSG_SEND(it, SIMSG_SET_RHYTHM(_mididrv->hasRhythmChannel())); - - if (_iterator == NULL) { - // Resync with clock - _currentTime = Audio::Timestamp(g_system->getMillis(), 1000000 / _tempo); - _wakeupTime = Audio::Timestamp(start_time, SFX_TICKS_PER_SEC); - } - - _iterator = sfx_iterator_combine(_iterator, it); - _iteratorIsDone = false; - - return Common::kNoError; -} - -Common::Error SfxPlayer::stop() { - debug(3, "Player: Stopping song iterator %p", (void *)_iterator); - Common::StackLock lock(_mutex); - delete _iterator; - _iterator = NULL; - for (int i = 0; i < MIDI_CHANNELS; i++) - static_cast(_mididrv)->send(0xb0 + i, SCI_MIDI_CHANNEL_NOTES_OFF, 0); - - return Common::kNoError; -} - -Common::Error SfxPlayer::iterator_message(const SongIterator::Message &msg) { - Common::StackLock lock(_mutex); - if (!_iterator) { - return Common::kUnknownError; - } - - songit_handle_message(&_iterator, msg); - - return Common::kNoError; -} - -Common::Error SfxPlayer::pause() { - Common::StackLock lock(_mutex); - - _paused = true; - _pauseTimeDiff = _wakeupTime.msecsDiff(_currentTime); - - _mididrv->playSwitch(false); - - return Common::kNoError; -} - -Common::Error SfxPlayer::resume() { - Common::StackLock lock(_mutex); - - _wakeupTime = Audio::Timestamp(_currentTime.msecs() + _pauseTimeDiff, SFX_TICKS_PER_SEC); - _mididrv->playSwitch(true); - _paused = false; - - return Common::kNoError; -} - -void SfxPlayer::setVolume(int vol) { - _mididrv->setVolume(vol); -} - -int SfxPlayer::getVolume() { - return _mididrv->getVolume(); -} - -#pragma mark - - -void SfxState::sfx_reset_player() { - if (_player) - _player->stop(); -} - -void SfxState::sfx_player_tell_synth(int buf_nr, byte *buf) { - if (_player) - _player->tell_synth(buf_nr, buf); -} - -int SfxState::sfx_get_player_polyphony() { - if (_player) - return _player->_polyphony; - else - return 0; -} - -SfxState::SfxState() { - _player = NULL; - _it = NULL; - _flags = 0; - _song = NULL; - _suspended = 0; -} - -SfxState::~SfxState() { -} - - -void SfxState::freezeTime() { - /* Freezes the top song delay time */ - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song) { - song->_delay = song->_wakeupTime.frameDiff(ctime); - if (song->_delay < 0) - song->_delay = 0; - - song = song->_nextPlaying; - } -} - -void SfxState::thawTime() { - /* inverse of freezeTime() */ - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song) { - song->_wakeupTime = ctime.addFrames(song->_delay); - - song = song->_nextPlaying; - } -} - -bool SfxState::isPlaying(Song *song) { - Song *playing_song = _song; - - /* _dump_playing_list(this, "is-playing");*/ - - while (playing_song) { - if (playing_song == song) - return true; - playing_song = playing_song->_nextPlaying; - } - return false; -} - -void SfxState::setSongStatus(Song *song, int status) { - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - - switch (status) { - - case SOUND_STATUS_STOPPED: - // Reset - song->_it->init(); - break; - - case SOUND_STATUS_SUSPENDED: - case SOUND_STATUS_WAITING: - if (song->_status == SOUND_STATUS_PLAYING) { - // Update delay, set wakeup_time - song->_delay += song->_wakeupTime.frameDiff(ctime); - song->_wakeupTime = ctime; - } - if (status == SOUND_STATUS_SUSPENDED) - break; - - /* otherwise... */ - - case SOUND_STATUS_PLAYING: - if (song->_status == SOUND_STATUS_STOPPED) { - // Starting anew - song->_wakeupTime = ctime; - } - - if (isPlaying(song)) - status = SOUND_STATUS_PLAYING; - else - status = SOUND_STATUS_WAITING; - break; - - default: - fprintf(stderr, "%s L%d: Attempt to set invalid song" - " state %d!\n", __FILE__, __LINE__, status); - return; - - } - song->_status = status; -} - -/* Update internal state iff only one song may be played */ -void SfxState::updateSingleSong() { - Song *newsong = _songlib.findFirstActive(); - - if (newsong != _song) { - freezeTime(); /* Store song delay time */ - - if (_player) - _player->stop(); - - if (newsong) { - if (!newsong->_it) - return; /* Restore in progress and not ready for this yet */ - - /* Change song */ - if (newsong->_status == SOUND_STATUS_WAITING) - setSongStatus(newsong, SOUND_STATUS_PLAYING); - - /* Change instrument mappings */ - } else { - /* Turn off sound */ - } - if (_song) { - if (_song->_status == SOUND_STATUS_PLAYING) - setSongStatus(newsong, SOUND_STATUS_WAITING); - } - - Common::String debugMessage = "[SFX] Changing active song:"; - if (!_song) { - debugMessage += " New song:"; - } else { - char tmp[50]; - sprintf(tmp, " pausing %08lx, now playing ", _song->_handle); - debugMessage += tmp; - } - - if (newsong) { - char tmp[20]; - sprintf(tmp, "%08lx\n", newsong->_handle); - debugMessage += tmp; - } else { - debugMessage += " none\n"; - } - - debugC(2, kDebugLevelSound, "%s", debugMessage.c_str()); - - _song = newsong; - thawTime(); /* Recover song delay time */ - - if (newsong && _player) { - SongIterator *clonesong = newsong->_it->clone(newsong->_delay); - - _player->add_iterator(clonesong, newsong->_wakeupTime.msecs()); - } - } -} - - -void SfxState::updateMultiSong() { - Song *oldfirst = _song; - Song *oldseeker; - Song *newsong = _songlib.findFirstActive(); - Song *newseeker; - Song not_playing_anymore; /* Dummy object, referenced by - ** songs which are no longer - ** active. */ - - /* _dump_playing_list(this, "before");*/ - freezeTime(); /* Store song delay time */ - - // WORKAROUND: sometimes, newsong can be NULL (e.g. in SQ4). - // Handle this here, so that we avoid a crash - if (!newsong) { - // Iterators should get freed when there's only one song left playing - if(oldfirst && oldfirst->_status == SOUND_STATUS_STOPPED) { - debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldfirst->_handle); - if (_player && oldfirst->_it) - _player->iterator_message(SongIterator::Message(oldfirst->_it->ID, SIMSG_STOP)); - } - return; - } - - for (newseeker = newsong; newseeker; - newseeker = newseeker->_nextPlaying) { - if (!newseeker || !newseeker->_it) - return; /* Restore in progress and not ready for this yet */ - } - - /* First, put all old songs into the 'stopping' list and - ** mark their 'next-playing' as not_playing_anymore. */ - for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->_nextStopping) { - oldseeker->_nextStopping = oldseeker->_nextPlaying; - oldseeker->_nextPlaying = ¬_playing_anymore; - - if (oldseeker == oldseeker->_nextPlaying) { - error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } - } - - /* Second, re-generate the new song queue. */ - for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { - newseeker->_nextPlaying = _songlib.findNextActive(newseeker); - - if (newseeker == newseeker->_nextPlaying) { - error("updateMultiSong() failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } - } - /* We now need to update the currently playing song list, because we're - ** going to use some functions that require this list to be in a sane - ** state (particularly isPlaying(), indirectly */ - _song = newsong; - - /* Third, stop all old songs */ - for (oldseeker = oldfirst; oldseeker; - oldseeker = oldseeker->_nextStopping) - if (oldseeker->_nextPlaying == ¬_playing_anymore) { - setSongStatus(oldseeker, SOUND_STATUS_SUSPENDED); - debugC(2, kDebugLevelSound, "[SFX] Stopping song %lx", oldseeker->_handle); - - if (_player && oldseeker->_it) - _player->iterator_message(SongIterator::Message(oldseeker->_it->ID, SIMSG_STOP)); - oldseeker->_nextPlaying = NULL; /* Clear this pointer; we don't need the tag anymore */ - } - - for (newseeker = newsong; newseeker; newseeker = newseeker->_nextPlaying) { - if (newseeker->_status != SOUND_STATUS_PLAYING && _player) { - debugC(2, kDebugLevelSound, "[SFX] Adding song %lx", newseeker->_it->ID); - - SongIterator *clonesong = newseeker->_it->clone(newseeker->_delay); - _player->add_iterator(clonesong, g_system->getMillis()); - } - setSongStatus(newseeker, SOUND_STATUS_PLAYING); - } - - _song = newsong; - thawTime(); - /* _dump_playing_list(this, "after");*/ -} - -/* Update internal state */ -void SfxState::update() { - if (_flags & SFX_STATE_FLAG_MULTIPLAY) - updateMultiSong(); - else - updateSingleSong(); -} - -static int sfx_play_iterator_pcm(SongIterator *it, SongHandle handle) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Playing PCM: %08lx\n", handle); -#endif - if (g_system->getMixer()->isReady()) { - Audio::AudioStream *newfeed = it->getAudioStream(); - if (newfeed) { - g_system->getMixer()->playStream(Audio::Mixer::kSFXSoundType, 0, newfeed); - return 1; - } - } - return 0; -} - -#define DELAY (1000000 / SFX_TICKS_PER_SEC) - -void SfxState::sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion) { - _songlib._lib = 0; - _song = NULL; - _flags = flags; - - _player = NULL; - - if (flags & SFX_STATE_FLAG_NOSOUND) { - warning("[SFX] Sound disabled"); - return; - } - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Initialising: flags=%x\n", flags); -#endif - - /*-------------------*/ - /* Initialise player */ - /*-------------------*/ - - if (!resMan) { - warning("[SFX] Warning: No resource manager present, cannot initialise player"); - return; - } - - _player = new SfxPlayer(soundVersion); - - if (!_player) { - warning("[SFX] No song player found"); - return; - } - - if (_player->init(resMan, DELAY / 1000)) { - warning("[SFX] Song player reported error, disabled"); - delete _player; - _player = NULL; - } - - _resMan = resMan; -} - -void SfxState::sfx_exit() { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Uninitialising\n"); -#endif - - delete _player; - _player = 0; - - g_system->getMixer()->stopAll(); - - _songlib.freeSounds(); -} - -void SfxState::sfx_suspend(bool suspend) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Suspending? = %d\n", suspend); -#endif - if (suspend && (!_suspended)) { - /* suspend */ - - freezeTime(); - if (_player) - _player->pause(); - /* Suspend song player */ - - } else if (!suspend && (_suspended)) { - /* unsuspend */ - - thawTime(); - if (_player) - _player->resume(); - - /* Unsuspend song player */ - } - - _suspended = suspend; -} - -int SfxState::sfx_poll(SongHandle *handle, int *cue) { - if (!_song) - return 0; /* No milk today */ - - *handle = _song->_handle; - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Polling any (%08lx)\n", *handle); -#endif - return sfx_poll_specific(*handle, cue); -} - -int SfxState::sfx_poll_specific(SongHandle handle, int *cue) { - const Audio::Timestamp ctime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - Song *song = _song; - - while (song && song->_handle != handle) - song = song->_nextPlaying; - - if (!song) - return 0; /* Song not playing */ - - debugC(2, kDebugLevelSound, "[SFX:CUE] Polled song %08lx ", handle); - - while (1) { - if (song->_wakeupTime.frameDiff(ctime) > 0) - return 0; /* Patience, young hacker! */ - - byte buf[8]; - int result = songit_next(&(song->_it), buf, cue, IT_READER_MASK_ALL); - - switch (result) { - - case SI_FINISHED: - setSongStatus(song, SOUND_STATUS_STOPPED); - update(); - /* ...fall through... */ - case SI_LOOP: - case SI_RELATIVE_CUE: - case SI_ABSOLUTE_CUE: - if (result == SI_FINISHED) - debugC(2, kDebugLevelSound, " => finished"); - else { - if (result == SI_LOOP) - debugC(2, kDebugLevelSound, " => Loop: %d (0x%x)", *cue, *cue); - else - debugC(2, kDebugLevelSound, " => Cue: %d (0x%x)", *cue, *cue); - - } - return result; - - default: - if (result > 0) - song->_wakeupTime = song->_wakeupTime.addFrames(result); - - /* Delay */ - break; - } - } - -} - - -/*****************/ -/* Song basics */ -/*****************/ - -void SfxState::sfx_add_song(SongIterator *it, int priority, SongHandle handle, int number) { - Song *song = _songlib.findSong(handle); - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Adding song: %08lx at %d, it=%p\n", handle, priority, it); -#endif - if (!it) { - error("[SFX] Attempt to add empty song with handle %08lx", handle); - return; - } - - it->init(); - - /* If we're already playing this, stop it */ - /* Tell player to shut up */ -// _dump_songs(this); - - if (_player) - _player->iterator_message(SongIterator::Message(handle, SIMSG_STOP)); - - if (song) { - setSongStatus( song, SOUND_STATUS_STOPPED); - - fprintf(stderr, "Overwriting old song (%08lx) ...\n", handle); - if (song->_status == SOUND_STATUS_PLAYING || song->_status == SOUND_STATUS_SUSPENDED) { - delete it; - error("Unexpected (error): Song %ld still playing/suspended (%d)", - handle, song->_status); - return; - } else { - _songlib.removeSong(handle); /* No duplicates */ - } - - } - - song = new Song(handle, it, priority); - song->_resourceNum = number; - song->_hold = 0; - song->_loops = 0; - song->_wakeupTime = Audio::Timestamp(g_system->getMillis(), SFX_TICKS_PER_SEC); - _songlib.addSong(song); - _song = NULL; /* As above */ - update(); - - return; -} - -void SfxState::sfx_remove_song(SongHandle handle) { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Removing song: %08lx\n", handle); -#endif - if (_song && _song->_handle == handle) - _song = NULL; - - _songlib.removeSong(handle); - update(); -} - - - -/**********************/ -/* Song modifications */ -/**********************/ - -#define ASSERT_SONG(s) if (!(s)) { warning("Looking up song handle %08lx failed in %s, L%d", handle, __FILE__, __LINE__); return; } - -void SfxState::sfx_song_set_status(SongHandle handle, int status) { - Song *song = _songlib.findSong(handle); - ASSERT_SONG(song); -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting song status to %d" - " (0:stop, 1:play, 2:susp, 3:wait): %08lx\n", status, handle); -#endif - - setSongStatus(song, status); - - update(); -} - -void SfxState::sfx_song_set_fade(SongHandle handle, fade_params_t *params) { -#ifdef DEBUG_SONG_API - static const char *stopmsg[] = {"??? Should not happen", "Do not stop afterwards", "Stop afterwards"}; -#endif - Song *song = _songlib.findSong(handle); - - ASSERT_SONG(song); - -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting fade params of %08lx to " - "final volume %d in steps of %d per %d ticks. %s.", - handle, fade->final_volume, fade->step_size, fade->ticks_per_step, - stopmsg[fade->action]); -#endif - - SIMSG_SEND_FADE(song->_it, params); - - update(); -} - -void SfxState::sfx_song_renice(SongHandle handle, int priority) { - Song *song = _songlib.findSong(handle); - ASSERT_SONG(song); -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Renicing song %08lx to %d\n", - handle, priority); -#endif - - song->_priority = priority; - - update(); -} - -void SfxState::sfx_song_set_loops(SongHandle handle, int loops) { - Song *song = _songlib.findSong(handle); - SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_LOOPS(loops)); - ASSERT_SONG(song); - - song->_loops = loops; -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting loops on %08lx to %d\n", - handle, loops); -#endif - songit_handle_message(&(song->_it), msg); - - if (_player/* && _player->send_iterator_message*/) - /* FIXME: The above should be optional! */ - _player->iterator_message(msg); -} - -void SfxState::sfx_song_set_hold(SongHandle handle, int hold) { - Song *song = _songlib.findSong(handle); - SongIterator::Message msg = SongIterator::Message(handle, SIMSG_SET_HOLD(hold)); - ASSERT_SONG(song); - - song->_hold = hold; -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] Setting hold on %08lx to %d\n", - handle, hold); -#endif - songit_handle_message(&(song->_it), msg); - - if (_player/* && _player->send_iterator_message*/) - /* FIXME: The above should be optional! */ - _player->iterator_message(msg); -} - -/* Different from the one in iterator.c */ -static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0, - 3, 3, 0, 3, 2, 0, 3, 0 - }; - -static const SongHandle midi_send_base = 0xffff0000; - -Common::Error SfxState::sfx_send_midi(SongHandle handle, int channel, - int command, int arg1, int arg2) { - byte buffer[5]; - - /* Yes, in that order. SCI channel mutes are actually done via - a counting semaphore. 0 means to decrement the counter, 1 - to increment it. */ - static const char *channel_state[] = {"ON", "OFF"}; - - if (command == 0xb0 && - arg1 == SCI_MIDI_CHANNEL_MUTE) { - warning("TODO: channel mute (channel %d %s)", channel, channel_state[arg2]); - /* We need to have a GET_PLAYMASK interface to use - here. SET_PLAYMASK we've got. - */ - return Common::kNoError; - } - - buffer[0] = channel | command; /* No channel remapping yet */ - - switch (command) { - case 0x80 : - case 0x90 : - case 0xb0 : - buffer[1] = arg1 & 0xff; - buffer[2] = arg2 & 0xff; - break; - case 0xc0 : - buffer[1] = arg1 & 0xff; - break; - case 0xe0 : - buffer[1] = (arg1 & 0x7f) | 0x80; - buffer[2] = (arg1 & 0xff00) >> 7; - break; - default: - warning("Unexpected explicit MIDI command %02x", command); - return Common::kUnknownError; - } - - if (_player) - _player->tell_synth(MIDI_cmdlen[command >> 4], buffer); - return Common::kNoError; -} - -int SfxState::sfx_getVolume() { - return _player->getVolume(); -} - -void SfxState::sfx_setVolume(int volume) { - _player->setVolume(volume); -} - -void SfxState::sfx_all_stop() { -#ifdef DEBUG_SONG_API - fprintf(stderr, "[sfx-core] All stop\n"); -#endif - - _songlib.freeSounds(); - update(); -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/core.h b/engines/sci/sound/iterator/core.h deleted file mode 100644 index a44fe2ecae..0000000000 --- a/engines/sci/sound/iterator/core.h +++ /dev/null @@ -1,209 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Sound engine */ -#ifndef SCI_SFX_CORE_H -#define SCI_SFX_CORE_H - -#include "common/error.h" - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/songlib.h" -#include "sci/resource.h" - -namespace Sci { - -class SfxPlayer; -class SongIterator; -struct fade_params_t; - -#define SFX_TICKS_PER_SEC 60 /* MIDI ticks per second */ - - -#define SFX_STATE_FLAG_MULTIPLAY (1 << 0) /* More than one song playable -** simultaneously ? */ -#define SFX_STATE_FLAG_NOSOUND (1 << 1) /* Completely disable sound playing */ - -class SfxState { -private: - SfxPlayer *_player; - -public: // FIXME, make private - SongIterator *_it; /**< The song iterator at the heart of things */ - uint _flags; /**< SFX_STATE_FLAG_* */ - SongLibrary _songlib; /**< Song library */ - Song *_song; /**< Active song, or start of active song chain */ - bool _suspended; /**< Whether we are suspended */ - ResourceManager *_resMan; - -public: - SfxState(); - ~SfxState(); - - /***********/ - /* General */ - /***********/ - - /* Initializes the sound engine - ** Parameters: (ResourceManager *) resMan: Resource manager for initialization - ** (int) flags: SFX_STATE_FLAG_* - */ - void sfx_init(ResourceManager *resMan, int flags, SciVersion soundVersion); - - /** Deinitializes the sound subsystem. */ - void sfx_exit(); - - /* Suspends/unsuspends the sound sybsystem - ** Parameters: (int) suspend: Whether to suspend (non-null) or to unsuspend - */ - void sfx_suspend(bool suspend); - - /* Polls the sound server for cues etc. - ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise - ** (SongHandle) *handle: The affected handle - ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) - */ - int sfx_poll(SongHandle *handle, int *cue); - - /* Polls the sound server for cues etc. - ** Parameters: (SongHandle) handle: The handle to poll - ** Returns : (int) 0 if the cue queue is empty, SI_LOOP, SI_CUE, or SI_FINISHED otherwise - ** (int) *cue: The sound cue number (if SI_CUE), or the loop number (if SI_LOOP) - */ - int sfx_poll_specific(SongHandle handle, int *cue); - - /* Determines the current global volume settings - ** Returns : (int) The global volume, between 0 (silent) and 127 (max. volume) - */ - int sfx_getVolume(); - - /* Determines the current global volume settings - ** Parameters: (int) volume: The new global volume, between 0 and 127 (see above) - */ - void sfx_setVolume(int volume); - - /* Stops all songs currently playing, purges song library - */ - void sfx_all_stop(); - - - /*****************/ - /* Song basics */ - /*****************/ - - /* Adds a song to the internal sound library - ** Parameters: (SongIterator *) it: The iterator describing the song - ** (int) priority: Initial song priority (higher <-> more important) - ** (SongHandle) handle: The handle to associate with the song - */ - void sfx_add_song(SongIterator *it, int priority, SongHandle handle, int resnum); - - - /* Deletes a song and its associated song iterator from the song queue - ** Parameters: (SongHandle) handle: The song to remove - */ - void sfx_remove_song(SongHandle handle); - - - /**********************/ - /* Song modifications */ - /**********************/ - - - /* Sets the song status, i.e. whether it is playing, suspended, or stopped. - ** Parameters: (SongHandle) handle: Handle of the song to modify - ** (int) status: The song status the song should assume - ** WAITING and PLAYING are set implicitly and essentially describe the same state - ** as far as this function is concerned. - */ - void sfx_song_set_status(SongHandle handle, int status); - - /* Sets the new song priority - ** Parameters: (SongHandle) handle: The handle to modify - ** (int) priority: The priority to set - */ - void sfx_song_renice(SongHandle handle, int priority); - - /* Sets the number of loops for the specified song - ** Parameters: (SongHandle) handle: The song handle to reference - ** (int) loops: Number of loops to set - */ - void sfx_song_set_loops(SongHandle handle, int loops); - - /* Sets the number of loops for the specified song - ** Parameters: (SongHandle) handle: The song handle to reference - ** (int) hold: Number of loops to setn - */ - void sfx_song_set_hold(SongHandle handle, int hold); - - /* Instructs a song to be faded out - ** Parameters: (SongHandle) handle: The song handle to reference - ** (fade_params_t *) fade_setup: The precise fade-out configuration to use - */ - void sfx_song_set_fade(SongHandle handle, fade_params_t *fade_setup); - - - // Previously undocumented: - Common::Error sfx_send_midi(SongHandle handle, int channel, - int command, int arg1, int arg2); - - // misc - - /** - * Determines the polyphony of the player in use. - * @return Number of voices the active player can emit - */ - int sfx_get_player_polyphony(); - - /** - * Tells the player to stop its internal iterator. - */ - void sfx_reset_player(); - - /** - * Pass a raw MIDI event to the synth of the player. - * @param argc Length of buffer holding the midi event - * @param argv The buffer itself - */ - void sfx_player_tell_synth(int buf_nr, byte *buf); - -protected: - void freezeTime(); - void thawTime(); - - bool isPlaying(Song *song); - void setSongStatus(Song *song, int status); - void updateSingleSong(); - void updateMultiSong(); - void update(); -}; - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_CORE_H diff --git a/engines/sci/sound/iterator/iterator.cpp b/engines/sci/sound/iterator/iterator.cpp deleted file mode 100644 index 62560b631f..0000000000 --- a/engines/sci/sound/iterator/iterator.cpp +++ /dev/null @@ -1,1641 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song iterators */ - -#include "common/util.h" - -#include "sci/sci.h" -#ifdef USE_OLD_MUSIC_FUNCTIONS - -#include "sci/sound/iterator/iterator_internal.h" -#include "sci/engine/state.h" // for sfx_player_tell_synth :/ -#include "sci/sound/iterator/core.h" // for sfx_player_tell_synth - -#include "sound/audiostream.h" -#include "sound/mixer.h" -#include "sound/decoders/raw.h" - -namespace Sci { - - -static const int MIDI_cmdlen[16] = {0, 0, 0, 0, 0, 0, 0, 0, - 2, 2, 2, 2, 1, 1, 2, 0 - }; - -/*#define DEBUG_DECODING*/ -/*#define DEBUG_VERBOSE*/ - -/** Find first set bit in bits and return its index. Returns 0 if bits is 0. */ -static int sci_ffs(int bits) { - if (!bits) - return 0; - - int retval = 1; - - while (!(bits & 1)) { - retval++; - bits >>= 1; - } - - return retval; -} - -static void print_tabs_id(int nr, songit_id_t id) { - while (nr-- > 0) - fprintf(stderr, "\t"); - - fprintf(stderr, "[%08lx] ", id); -} - -BaseSongIterator::BaseSongIterator(byte *data, uint size, songit_id_t id) - : _data(data, size) { - ID = id; -} - -/************************************/ -/*-- SCI0 iterator implementation --*/ -/************************************/ - -#define SCI0_MIDI_OFFSET 33 -#define SCI0_END_OF_SONG 0xfc /* proprietary MIDI command */ - -#define SCI0_PCM_SAMPLE_RATE_OFFSET 0x0e -#define SCI0_PCM_SIZE_OFFSET 0x20 -#define SCI0_PCM_DATA_OFFSET 0x2c - -#define CHECK_FOR_END_ABSOLUTE(offset) \ - if (offset > _data.size()) { \ - warning("Reached end of song without terminator (%x/%x) at %d", offset, _data.size(), __LINE__); \ - return SI_FINISHED; \ - } - -#define CHECK_FOR_END(offset_augment) \ - if ((channel->offset + (offset_augment)) > channel->end) { \ - channel->state = SI_STATE_FINISHED; \ - warning("Reached end of track %d without terminator (%x+%x/%x) at %d", channel->id, channel->offset, offset_augment, channel->end, __LINE__); \ - return SI_FINISHED; \ - } - - -static int _parse_ticks(byte *data, int *offset_p, int size) { - int ticks = 0; - int tempticks; - int offset = 0; - - do { - tempticks = data[offset++]; - ticks += (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX) ? - SCI_MIDI_TIME_EXPANSION_LENGTH : tempticks; - } while (tempticks == SCI_MIDI_TIME_EXPANSION_PREFIX - && offset < size); - - if (offset_p) - *offset_p = offset; - - return ticks; -} - - -static int _sci0_get_pcm_data(Sci0SongIterator *self, int *rate, int *xoffset, uint *xsize); - - -#define PARSE_FLAG_LOOPS_UNLIMITED (1 << 0) /* Unlimited # of loops? */ -#define PARSE_FLAG_PARAMETRIC_CUE (1 << 1) /* Assume that cues take an additional "cue value" argument */ -/* This implements a difference between SCI0 and SCI1 cues. */ - -void SongIteratorChannel::init(int id_, int offset_, int end_) { - playmask = PLAYMASK_NONE; /* Disable all channels */ - id = id_; - state = SI_STATE_DELTA_TIME; - loop_timepos = 0; - total_timepos = 0; - timepos_increment = 0; - delay = 0; /* Only used for more than one channel */ - last_cmd = 0xfe; - - offset = loop_offset = initial_offset = offset_; - end = end_; -} - -void SongIteratorChannel::resetSynthChannels() { - byte buf[5]; - - // FIXME: Evil hack - SfxState &sound = g_sci->getEngineState()->_sound; - - for (int i = 0; i < MIDI_CHANNELS; i++) { - if (playmask & (1 << i)) { - buf[0] = 0xe0 | i; /* Pitch bend */ - buf[1] = 0x80; /* Wheel center */ - buf[2] = 0x40; - sound.sfx_player_tell_synth(3, buf); - - buf[0] = 0xb0 | i; // Set control - buf[1] = 0x40; // Hold pedal - buf[2] = 0x00; // Off - sound.sfx_player_tell_synth(3, buf); - /* TODO: Reset other controls? */ - } - } -} - -int BaseSongIterator::parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags) { - byte cmd; - int paramsleft; - int midi_op; - int midi_channel; - - channel->state = SI_STATE_DELTA_TIME; - - cmd = _data[channel->offset++]; - - if (!(cmd & 0x80)) { - /* 'Running status' mode */ - channel->offset--; - cmd = channel->last_cmd; - } - - if (cmd == 0xfe) { - warning("song iterator subsystem: Corrupted sound resource detected."); - return SI_FINISHED; - } - - midi_op = cmd >> 4; - midi_channel = cmd & 0xf; - paramsleft = MIDI_cmdlen[midi_op]; - - buf[0] = cmd; - - - CHECK_FOR_END(paramsleft); - memcpy(buf + 1, _data.begin() + channel->offset, paramsleft); - *result = 1 + paramsleft; - - channel->offset += paramsleft; - - channel->last_cmd = cmd; - - /* Are we supposed to play this channel? */ - if ( - /* First, exclude "global" properties-- such as cues-- from consideration */ - (midi_op < 0xf - && !(cmd == SCI_MIDI_SET_SIGNAL) - && !(SCI_MIDI_CONTROLLER(cmd) - && buf[1] == SCI_MIDI_CUMULATIVE_CUE)) - - /* Next, check if the channel is allowed */ - && (!((1 << midi_channel) & channel->playmask))) - return /* Execute next command */ - nextCommand(buf, result); - - - if (cmd == SCI_MIDI_EOT) { - /* End of track? */ - channel->resetSynthChannels(); - if (_loops > 1) { - /* If allowed, decrement the number of loops */ - if (!(flags & PARSE_FLAG_LOOPS_UNLIMITED)) - *result = --_loops; - -#ifdef DEBUG_DECODING - fprintf(stderr, "%s L%d: (%p):%d Looping ", __FILE__, __LINE__, this, channel->id); - if (flags & PARSE_FLAG_LOOPS_UNLIMITED) - fprintf(stderr, "(indef.)"); - else - fprintf(stderr, "(%d)", _loops); - fprintf(stderr, " %x -> %x\n", - channel->offset, channel->loop_offset); -#endif - channel->offset = channel->loop_offset; - channel->state = SI_STATE_DELTA_TIME; - channel->total_timepos = channel->loop_timepos; - channel->last_cmd = 0xfe; - debugC(2, kDebugLevelSound, "Looping song iterator %08lx.", ID); - return SI_LOOP; - } else { - channel->state = SI_STATE_FINISHED; - return SI_FINISHED; - } - - } else if (cmd == SCI_MIDI_SET_SIGNAL) { - if (buf[1] == SCI_MIDI_SET_SIGNAL_LOOP) { - channel->loop_offset = channel->offset; - channel->loop_timepos = channel->total_timepos; - - return /* Execute next command */ - nextCommand(buf, result); - } else { - /* Used to be conditional <= 127 */ - *result = buf[1]; /* Absolute cue */ - return SI_ABSOLUTE_CUE; - } - } else if (SCI_MIDI_CONTROLLER(cmd)) { - switch (buf[1]) { - - case SCI_MIDI_CUMULATIVE_CUE: - if (flags & PARSE_FLAG_PARAMETRIC_CUE) - _ccc += buf[2]; - else { /* No parameter to CC */ - _ccc++; - /* channel->offset--; */ - } - *result = _ccc; - return SI_RELATIVE_CUE; - - case SCI_MIDI_RESET_ON_SUSPEND: - _resetflag = buf[2]; - break; - - case SCI_MIDI_SET_POLYPHONY: - _polyphony[midi_channel] = buf[2]; - break; - - case SCI_MIDI_SET_REVERB: - break; - - case SCI_MIDI_CHANNEL_MUTE: - warning("CHANNEL_MUTE(%d, %d)", midi_channel, buf[2]); - break; - - case SCI_MIDI_HOLD: { - // Safe cast: This controller is only used in SCI1 - Sci1SongIterator *self1 = (Sci1SongIterator *)this; - - if (buf[2] == self1->_hold) { - channel->offset = channel->initial_offset; - channel->state = SI_STATE_COMMAND; - channel->total_timepos = 0; - - self1->_numLoopedChannels = self1->_numActiveChannels - 1; - - // FIXME: - // This implementation of hold breaks getting out of the - // limo when visiting the airport near the start of LSL5. - // It seems like all channels should be reset here somehow, - // but not sure how. - // Forcing all channel offsets to 0 seems to fix the hang, - // but somehow slows the exit sequence down to take 20 seconds - // instead of about 3. - - return SI_LOOP; - } - - break; - } - case 0x04: /* UNKNOWN NYI (happens in LSL2 gameshow) */ - case 0x46: /* UNKNOWN NYI (happens in LSL3 binoculars) */ - case 0x61: /* UNKNOWN NYI (special for AdLib? Iceman) */ - case 0x73: /* UNKNOWN NYI (happens in Hoyle) */ - case 0xd1: /* UNKNOWN NYI (happens in KQ4 when riding the unicorn) */ - return /* Execute next command */ - nextCommand(buf, result); - - case 0x01: /* modulation */ - case 0x07: /* volume */ - case 0x0a: /* panpot */ - case 0x0b: /* expression */ - case 0x40: /* hold */ - case 0x79: /* reset all */ - /* No special treatment neccessary */ - break; - - } - return 0; - - } else { - /* Process as normal MIDI operation */ - return 0; - } -} - -int BaseSongIterator::processMidi(byte *buf, int *result, - SongIteratorChannel *channel, int flags) { - CHECK_FOR_END(0); - - switch (channel->state) { - - case SI_STATE_PCM: { - if (_data[channel->offset] == 0 - && _data[channel->offset + 1] == SCI_MIDI_EOT) - /* Fake one extra tick to trick the interpreter into not killing the song iterator right away */ - channel->state = SI_STATE_PCM_MAGIC_DELTA; - else - channel->state = SI_STATE_DELTA_TIME; - return SI_PCM; - } - - case SI_STATE_PCM_MAGIC_DELTA: { - int rate; - int offset; - uint size; - int delay; - if (_sci0_get_pcm_data((Sci0SongIterator *)this, &rate, &offset, &size)) - return SI_FINISHED; /* 'tis broken */ - channel->state = SI_STATE_FINISHED; - delay = (size * 50 + rate - 1) / rate; /* number of ticks to completion*/ - - debugC(2, kDebugLevelSound, "delaying %d ticks", delay); - return delay; - } - - case SI_STATE_UNINITIALISED: - warning("Attempt to read command from uninitialized iterator"); - init(); - return nextCommand(buf, result); - - case SI_STATE_FINISHED: - return SI_FINISHED; - - case SI_STATE_DELTA_TIME: { - int offset; - int ticks = _parse_ticks(_data.begin() + channel->offset, - &offset, - _data.size() - channel->offset); - - channel->offset += offset; - channel->delay += ticks; - channel->timepos_increment = ticks; - - CHECK_FOR_END(0); - - channel->state = SI_STATE_COMMAND; - - if (ticks) - return ticks; - } - - /* continute otherwise... */ - - case SI_STATE_COMMAND: { - int retval; - channel->total_timepos += channel->timepos_increment; - channel->timepos_increment = 0; - - retval = parseMidiCommand(buf, result, channel, flags); - - if (retval == SI_FINISHED) { - if (_numActiveChannels) - --(_numActiveChannels); -#ifdef DEBUG_DECODING - fprintf(stderr, "%s L%d: (%p):%d Finished channel, %d channels left\n", - __FILE__, __LINE__, this, channel->id, - _numActiveChannels); -#endif - /* If we still have channels left... */ - if (_numActiveChannels) { - return nextCommand(buf, result); - } - - /* Otherwise, we have reached the end */ - _loops = 0; - } - - return retval; - } - - default: - error("Invalid iterator state %d", channel->state); - return SI_FINISHED; - } -} - -int Sci0SongIterator::nextCommand(byte *buf, int *result) { - return processMidi(buf, result, &_channel, PARSE_FLAG_PARAMETRIC_CUE); -} - -static int _sci0_header_magic_p(byte *data, int offset, int size) { - if (offset + 0x10 > size) - return 0; - return (data[offset] == 0x1a) - && (data[offset + 1] == 0x00) - && (data[offset + 2] == 0x01) - && (data[offset + 3] == 0x00); -} - - -static int _sci0_get_pcm_data(Sci0SongIterator *self, - int *rate, int *xoffset, uint *xsize) { - int tries = 2; - bool found_it = false; - byte *pcm_data; - int size; - uint offset = SCI0_MIDI_OFFSET; - - if (self->_data[0] != 2) - return 1; - /* No such luck */ - - while ((tries--) && (offset < self->_data.size()) && (!found_it)) { - // Search through the garbage manually - // FIXME: Replace offset by an iterator - Common::Array::iterator iter = Common::find(self->_data.begin() + offset, self->_data.end(), SCI0_END_OF_SONG); - - if (iter == self->_data.end()) { - warning("Playing unterminated song"); - return 1; - } - - // add one to move it past the END_OF_SONG marker - iter++; - offset = iter - self->_data.begin(); // FIXME - - - if (_sci0_header_magic_p(self->_data.begin(), offset, self->_data.size())) - found_it = true; - } - - if (!found_it) { - warning("Song indicates presence of PCM, but" - " none found (finally at offset %04x)", offset); - - return 1; - } - - pcm_data = self->_data.begin() + offset; - - size = READ_LE_UINT16(pcm_data + SCI0_PCM_SIZE_OFFSET); - - /* Two of the format parameters are fixed by design: */ - *rate = READ_LE_UINT16(pcm_data + SCI0_PCM_SAMPLE_RATE_OFFSET); - - if (offset + SCI0_PCM_DATA_OFFSET + size != self->_data.size()) { - int d = offset + SCI0_PCM_DATA_OFFSET + size - self->_data.size(); - - warning("PCM advertizes %d bytes of data, but %d" - " bytes are trailing in the resource", - size, self->_data.size() - (offset + SCI0_PCM_DATA_OFFSET)); - - if (d > 0) - size -= d; /* Fix this */ - } - - *xoffset = offset; - *xsize = size; - - return 0; -} - -static Audio::AudioStream *makeStream(byte *data, int size, int rate) { - debugC(2, kDebugLevelSound, "Playing PCM data of size %d, rate %d", size, rate); - - // Duplicate the data - byte *sound = (byte *)malloc(size); - memcpy(sound, data, size); - - // Convert stream format flags - int flags = Audio::FLAG_UNSIGNED; - return Audio::makeRawStream(sound, size, rate, flags); -} - -Audio::AudioStream *Sci0SongIterator::getAudioStream() { - int rate; - int offset; - uint size; - if (_sci0_get_pcm_data(this, &rate, &offset, &size)) - return NULL; - - _channel.state = SI_STATE_FINISHED; /* Don't play both PCM and music */ - - return makeStream(_data.begin() + offset + SCI0_PCM_DATA_OFFSET, size, rate); -} - -SongIterator *Sci0SongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASE) { - switch (msg._type) { - - case _SIMSG_BASEMSG_PRINT: - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "SCI0: dev=%d, active-chan=%d, size=%d, loops=%d", - _deviceId, _numActiveChannels, _data.size(), _loops); - break; - - case _SIMSG_BASEMSG_SET_LOOPS: - _loops = msg._arg.i; - break; - - case _SIMSG_BASEMSG_STOP: { - songit_id_t sought_id = msg.ID; - - if (sought_id == ID) - _channel.state = SI_STATE_FINISHED; - break; - } - - case _SIMSG_BASEMSG_SET_PLAYMASK: { - int i; - _deviceId = msg._arg.i; - - /* Set all but the rhytm channel mask bits */ - _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); - - for (i = 0; i < MIDI_CHANNELS; i++) - if (_data[2 + (i << 1)] & _deviceId - && i != MIDI_RHYTHM_CHANNEL) - _channel.playmask |= (1 << i); - } - break; - - case _SIMSG_BASEMSG_SET_RHYTHM: - _channel.playmask &= ~(1 << MIDI_RHYTHM_CHANNEL); - if (msg._arg.i) - _channel.playmask |= (1 << MIDI_RHYTHM_CHANNEL); - break; - - case _SIMSG_BASEMSG_SET_FADE: { - fade_params_t *fp = (fade_params_t *) msg._arg.p; - fade.action = fp->action; - fade.final_volume = fp->final_volume; - fade.ticks_per_step = fp->ticks_per_step; - fade.step_size = fp->step_size; - break; - } - - default: - return NULL; - } - - return this; - } - return NULL; -} - -int Sci0SongIterator::getTimepos() { - return _channel.total_timepos; -} - -Sci0SongIterator::Sci0SongIterator(byte *data, uint size, songit_id_t id) - : BaseSongIterator(data, size, id) { - channel_mask = 0xffff; // Allocate all channels by default - _channel.state = SI_STATE_UNINITIALISED; - - for (int i = 0; i < MIDI_CHANNELS; i++) - _polyphony[i] = data[1 + (i << 1)]; - - init(); -} - -void Sci0SongIterator::init() { - fade.action = FADE_ACTION_NONE; - _resetflag = 0; - _loops = 0; - priority = 0; - - _ccc = 0; /* Reset cumulative cue counter */ - _numActiveChannels = 1; - _channel.init(0, SCI0_MIDI_OFFSET, _data.size()); - _channel.resetSynthChannels(); - - if (_data[0] == 2) /* Do we have an embedded PCM? */ - _channel.state = SI_STATE_PCM; -} - -SongIterator *Sci0SongIterator::clone(int delta) { - Sci0SongIterator *newit = new Sci0SongIterator(*this); - return newit; -} - - -/***************************/ -/*-- SCI1 song iterators --*/ -/***************************/ - -int Sci1SongIterator::initSample(const int offset) { - Sci1Sample sample; - int rate; - int length; - int begin; - int end; - - CHECK_FOR_END_ABSOLUTE((uint)offset + 10); - if (_data[offset + 1] != 0) - warning("[iterator-1] In sample at offset 0x04x: Byte #1 is %02x instead of zero", - _data[offset + 1]); - - rate = (int16)READ_LE_UINT16(_data.begin() + offset + 2); - length = READ_LE_UINT16(_data.begin() + offset + 4); - begin = (int16)READ_LE_UINT16(_data.begin() + offset + 6); - end = (int16)READ_LE_UINT16(_data.begin() + offset + 8); - - CHECK_FOR_END_ABSOLUTE((uint)(offset + 10 + length)); - - sample.delta = begin; - sample.size = length; - sample._data = _data.begin() + offset + 10; - -#ifdef DEBUG_VERBOSE - fprintf(stderr, "[SAMPLE] %x/%x/%x/%x l=%x\n", - offset + 10, begin, end, _data.size(), length); -#endif - - sample.rate = rate; - - sample.announced = false; - - /* Insert into the sample list at the right spot, keeping it sorted by delta */ - Common::List::iterator seeker = _samples.begin(); - while (seeker != _samples.end() && seeker->delta < begin) - ++seeker; - _samples.insert(seeker, sample); - - return 0; /* Everything's fine */ -} - -int Sci1SongIterator::initSong() { - int last_time; - uint offset = 0; - _numChannels = 0; - _samples.clear(); -// _deviceId = 0x0c; - - if (_data[offset] == 0xf0) { - priority = _data[offset + 1]; - - offset += 8; - } - - while (_data[offset] != 0xff - && _data[offset] != _deviceId) { - offset++; - CHECK_FOR_END_ABSOLUTE(offset + 1); - while (_data[offset] != 0xff) { - CHECK_FOR_END_ABSOLUTE(offset + 7); - offset += 6; - } - offset++; - } - - if (_data[offset] == 0xff) { - warning("[iterator] Song does not support hardware 0x%02x", _deviceId); - return 1; - } - - offset++; - - while (_data[offset] != 0xff) { /* End of list? */ - uint track_offset; - int end; - offset += 2; - - CHECK_FOR_END_ABSOLUTE(offset + 4); - - track_offset = READ_LE_UINT16(_data.begin() + offset); - end = READ_LE_UINT16(_data.begin() + offset + 2); - - CHECK_FOR_END_ABSOLUTE(track_offset - 1); - - if (_data[track_offset] == 0xfe) { - if (initSample(track_offset)) - return 1; /* Error */ - } else { - /* Regular MIDI channel */ - if (_numChannels >= MIDI_CHANNELS) { - warning("[iterator] Song has more than %d channels, cutting them off", - MIDI_CHANNELS); - break; /* Scan for remaining samples */ - } else { - int channel_nr = _data[track_offset] & 0xf; - SongIteratorChannel &channel = _channels[_numChannels++]; - - /* - if (_data[track_offset] & 0xf0) - printf("Channel %d has mapping bits %02x\n", - channel_nr, _data[track_offset] & 0xf0); - */ - - // Add 2 to skip over header bytes */ - channel.init(channel_nr, track_offset + 2, track_offset + end); - channel.resetSynthChannels(); - - _polyphony[_numChannels - 1] = _data[channel.offset - 1] & 15; - - channel.playmask = ~0; /* Enable all */ - channel_mask |= (1 << channel_nr); - - CHECK_FOR_END_ABSOLUTE(offset + end); - } - } - offset += 4; - CHECK_FOR_END_ABSOLUTE(offset); - } - - /* Now ensure that sample deltas are relative to the previous sample */ - last_time = 0; - _numActiveChannels = _numChannels; - _numLoopedChannels = 0; - - for (Common::List::iterator seeker = _samples.begin(); - seeker != _samples.end(); ++seeker) { - int prev_last_time = last_time; - //printf("[iterator] Detected sample: %d Hz, %d bytes at time %d\n", - // seeker->format.rate, seeker->size, seeker->delta); - last_time = seeker->delta; - seeker->delta -= prev_last_time; - } - - return 0; /* Success */ -} - -int Sci1SongIterator::getSmallestDelta() const { - int d = -1; - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_COMMAND - && (d == -1 || _channels[i].delay < d)) - d = _channels[i].delay; - - if (!_samples.empty() && _samples.begin()->delta < d) - return _samples.begin()->delta; - else - return d; -} - -void Sci1SongIterator::updateDelta(int delta) { - if (!_samples.empty()) - _samples.begin()->delta -= delta; - - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_COMMAND) - _channels[i].delay -= delta; -} - -bool Sci1SongIterator::noDeltaTime() const { - for (int i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_DELTA_TIME) - return false; - return true; -} - -#define COMMAND_INDEX_NONE -1 -#define COMMAND_INDEX_PCM -2 - -int Sci1SongIterator::getCommandIndex() const { - /* Determine the channel # of the next active event, or -1 */ - int i; - int base_delay = 0x7ffffff; - int best_chan = COMMAND_INDEX_NONE; - - for (i = 0; i < _numChannels; i++) - if ((_channels[i].state != SI_STATE_PENDING) - && (_channels[i].state != SI_STATE_FINISHED)) { - - if ((_channels[i].state == SI_STATE_DELTA_TIME) - && (_channels[i].delay == 0)) - return i; - /* First, read all unknown delta times */ - - if (_channels[i].delay < base_delay) { - best_chan = i; - base_delay = _channels[i].delay; - } - } - - if (!_samples.empty() && base_delay >= _samples.begin()->delta) - return COMMAND_INDEX_PCM; - - return best_chan; -} - - -Audio::AudioStream *Sci1SongIterator::getAudioStream() { - Common::List::iterator sample = _samples.begin(); - if (sample != _samples.end() && sample->delta <= 0) { - Audio::AudioStream *feed = makeStream(sample->_data, sample->size, sample->rate); - _samples.erase(sample); - - return feed; - } else - return NULL; -} - -int Sci1SongIterator::nextCommand(byte *buf, int *result) { - - if (!_initialised) { - //printf("[iterator] DEBUG: Initialising for %d\n", _deviceId); - _initialised = true; - if (initSong()) - return SI_FINISHED; - } - - - if (_delayRemaining) { - int delay = _delayRemaining; - _delayRemaining = 0; - return delay; - } - - int retval = 0; - do { /* All delays must be processed separately */ - int chan = getCommandIndex(); - - if (chan == COMMAND_INDEX_NONE) { - return SI_FINISHED; - } - - if (chan == COMMAND_INDEX_PCM) { - - if (_samples.begin()->announced) { - /* Already announced; let's discard it */ - Audio::AudioStream *feed = getAudioStream(); - delete feed; - } else { - int delay = _samples.begin()->delta; - - if (delay) { - updateDelta(delay); - return delay; - } - /* otherwise we're touching a PCM */ - _samples.begin()->announced = true; - return SI_PCM; - } - } else { /* Not a PCM */ - - retval = processMidi(buf, result, - &(_channels[chan]), - PARSE_FLAG_LOOPS_UNLIMITED); - - if (retval == SI_LOOP) { - _numLoopedChannels++; - _channels[chan].state = SI_STATE_PENDING; - _channels[chan].delay = 0; - - if (_numLoopedChannels == _numActiveChannels) { - int i; - - /* Everyone's ready: Let's loop */ - for (i = 0; i < _numChannels; i++) - if (_channels[i].state == SI_STATE_PENDING) - _channels[i].state = SI_STATE_DELTA_TIME; - - _numLoopedChannels = 0; - return SI_LOOP; - } - } else if (retval == SI_FINISHED) { -#ifdef DEBUG - fprintf(stderr, "FINISHED some channel\n"); -#endif - } else if (retval > 0) { - int sd ; - sd = getSmallestDelta(); - - if (noDeltaTime() && sd) { - /* No other channel is ready */ - updateDelta(sd); - - /* Only from here do we return delta times */ - return sd; - } - } - - } /* Not a PCM */ - - } while (retval > 0); - - return retval; -} - -SongIterator *Sci1SongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASE) { /* May extend this in the future */ - switch (msg._type) { - - case _SIMSG_BASEMSG_PRINT: { - int playmask = 0; - int i; - - for (i = 0; i < _numChannels; i++) - playmask |= _channels[i].playmask; - - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "SCI1: chan-nr=%d, playmask=%04x", - _numChannels, playmask); - } - break; - - case _SIMSG_BASEMSG_STOP: { - songit_id_t sought_id = msg.ID; - int i; - - if (sought_id == ID) { - ID = 0; - - for (i = 0; i < _numChannels; i++) - _channels[i].state = SI_STATE_FINISHED; - } - break; - } - - case _SIMSG_BASEMSG_SET_PLAYMASK: - if (msg.ID == ID) { - channel_mask = 0; - - _deviceId = msg._arg.i; - - if (_initialised) { - int i; - int toffset = -1; - - for (i = 0; i < _numChannels; i++) - if (_channels[i].state != SI_STATE_FINISHED - && _channels[i].total_timepos > toffset) { - toffset = _channels[i].total_timepos - + _channels[i].timepos_increment - - _channels[i].delay; - } - - /* Find an active channel so that we can - ** get the correct time offset */ - - initSong(); - - toffset -= _delayRemaining; - _delayRemaining = 0; - - if (toffset > 0) - return new_fast_forward_iterator(this, toffset); - } else { - initSong(); - _initialised = true; - } - - break; - - } - - case _SIMSG_BASEMSG_SET_LOOPS: - if (msg.ID == ID) - _loops = (msg._arg.i > 32767) ? 99 : 0; - /* 99 is arbitrary, but we can't use '1' because of - ** the way we're testing in the decoding section. */ - break; - - case _SIMSG_BASEMSG_SET_HOLD: - _hold = msg._arg.i; - break; - case _SIMSG_BASEMSG_SET_RHYTHM: - /* Ignore */ - break; - - case _SIMSG_BASEMSG_SET_FADE: { - fade_params_t *fp = (fade_params_t *) msg._arg.p; - fade.action = fp->action; - fade.final_volume = fp->final_volume; - fade.ticks_per_step = fp->ticks_per_step; - fade.step_size = fp->step_size; - break; - } - - default: - warning("Unsupported command %d to SCI1 iterator", msg._type); - } - return this; - } - return NULL; -} - -Sci1SongIterator::Sci1SongIterator(byte *data, uint size, songit_id_t id) - : BaseSongIterator(data, size, id) { - channel_mask = 0; // Defer channel allocation - - for (int i = 0; i < MIDI_CHANNELS; i++) - _polyphony[i] = 0; // Unknown - - init(); -} - -void Sci1SongIterator::init() { - fade.action = FADE_ACTION_NONE; - _resetflag = 0; - _loops = 0; - priority = 0; - - _ccc = 0; - _deviceId = 0x00; // Default to Sound Blaster/AdLib for purposes of cue computation - _numChannels = 0; - _initialised = false; - _delayRemaining = 0; - _loops = 0; - _hold = 0; - memset(_polyphony, 0, sizeof(_polyphony)); -} - -Sci1SongIterator::~Sci1SongIterator() { -} - - -SongIterator *Sci1SongIterator::clone(int delta) { - Sci1SongIterator *newit = new Sci1SongIterator(*this); - newit->_delayRemaining = delta; - return newit; -} - -int Sci1SongIterator::getTimepos() { - int max = 0; - int i; - - for (i = 0; i < _numChannels; i++) - if (_channels[i].total_timepos > max) - max = _channels[i].total_timepos; - - return max; -} - -/** - * A song iterator with the purpose of sending notes-off channel commands. - */ -class CleanupSongIterator : public SongIterator { -public: - CleanupSongIterator(uint channels) { - channel_mask = channels; - ID = 17; - } - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream() { return NULL; } - SongIterator *handleMessage(Message msg); - int getTimepos() { return 0; } - SongIterator *clone(int delta) { return new CleanupSongIterator(*this); } -}; - -SongIterator *CleanupSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_BASEMSG_PRINT && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "CLEANUP"); - } - - return NULL; -} - -int CleanupSongIterator::nextCommand(byte *buf, int *result) { - /* Task: Return channel-notes-off for each channel */ - if (channel_mask) { - int bs = sci_ffs(channel_mask) - 1; - - channel_mask &= ~(1 << bs); - buf[0] = 0xb0 | bs; /* Controller */ - buf[1] = SCI_MIDI_CHANNEL_NOTES_OFF; - buf[2] = 0; /* Hmm... */ - *result = 3; - return 0; - } else - return SI_FINISHED; -} - -/**********************/ -/*-- Timer iterator --*/ -/**********************/ -int TimerSongIterator::nextCommand(byte *buf, int *result) { - if (_delta) { - int d = _delta; - _delta = 0; - return d; - } - return SI_FINISHED; -} - -SongIterator *new_timer_iterator(int delta) { - return new TimerSongIterator(delta); -} - -/**********************************/ -/*-- Fast-forward song iterator --*/ -/**********************************/ - -int FastForwardSongIterator::nextCommand(byte *buf, int *result) { - if (_delta <= 0) - return SI_MORPH; /* Did our duty */ - - while (1) { - int rv = _delegate->nextCommand(buf, result); - - if (rv > 0) { - /* Subtract from the delta we want to wait */ - _delta -= rv; - - /* Done */ - if (_delta < 0) - return -_delta; - } - - if (rv <= 0) - return rv; - } -} - -Audio::AudioStream *FastForwardSongIterator::getAudioStream() { - return _delegate->getAudioStream(); -} - -SongIterator *FastForwardSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_PLASTICWRAP) { - assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH); - - if (_delta <= 0) { - SongIterator *it = _delegate; - delete this; - return it; - } - - warning("[ff-iterator] Morphing without need"); - return this; - } - - if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "FASTFORWARD:"); - msg._arg.i++; - } - - // And continue with the delegate - songit_handle_message(&_delegate, msg); - - return NULL; -} - - -int FastForwardSongIterator::getTimepos() { - return _delegate->getTimepos(); -} - -FastForwardSongIterator::FastForwardSongIterator(SongIterator *capsit, int delta) - : _delegate(capsit), _delta(delta) { - - channel_mask = capsit->channel_mask; -} - -SongIterator *FastForwardSongIterator::clone(int delta) { - FastForwardSongIterator *newit = new FastForwardSongIterator(*this); - newit->_delegate = _delegate->clone(delta); - return newit; -} - -SongIterator *new_fast_forward_iterator(SongIterator *capsit, int delta) { - if (capsit == NULL) - return NULL; - - FastForwardSongIterator *it = new FastForwardSongIterator(capsit, delta); - return it; -} - - -/********************/ -/*-- Tee iterator --*/ -/********************/ - - -static void song_iterator_add_death_listener(SongIterator *it, TeeSongIterator *client) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it->_deathListeners[i] == 0) { - it->_deathListeners[i] = client; - return; - } - } - error("FATAL: Too many death listeners for song iterator"); -} - -static void song_iterator_remove_death_listener(SongIterator *it, TeeSongIterator *client) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it->_deathListeners[i] == client) { - it->_deathListeners[i] = 0; - return; - } - } -} - -static void song_iterator_transfer_death_listeners(SongIterator *it, SongIterator *it_from) { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) { - if (it_from->_deathListeners[i]) - song_iterator_add_death_listener(it, it_from->_deathListeners[i]); - it_from->_deathListeners[i] = 0; - } -} - -static void songit_tee_death_notification(TeeSongIterator *self, SongIterator *corpse) { - if (corpse == self->_children[TEE_LEFT].it) { - self->_status &= ~TEE_LEFT_ACTIVE; - self->_children[TEE_LEFT].it = NULL; - } else if (corpse == self->_children[TEE_RIGHT].it) { - self->_status &= ~TEE_RIGHT_ACTIVE; - self->_children[TEE_RIGHT].it = NULL; - } else { - error("songit_tee_death_notification() failed: Breakpoint in %s, line %d", __FILE__, __LINE__); - } -} - -TeeSongIterator::TeeSongIterator(SongIterator *left, SongIterator *right) { - int i; - int firstfree = 1; /* First free channel */ - int incomplete_map = 0; - - _readyToMorph = false; - _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE; - - _children[TEE_LEFT].it = left; - _children[TEE_RIGHT].it = right; - - /* Default to lhs channels */ - channel_mask = left->channel_mask; - for (i = 0; i < 16; i++) - if (channel_mask & (1 << i) & right->channel_mask - && (i != MIDI_RHYTHM_CHANNEL) /* Share rhythm */) { /*conflict*/ - while ((firstfree == MIDI_RHYTHM_CHANNEL) - /* Either if it's the rhythm channel or if it's taken */ - || (firstfree < MIDI_CHANNELS - && ((1 << firstfree) & channel_mask))) - ++firstfree; - - if (firstfree == MIDI_CHANNELS) { - incomplete_map = 1; - //warning("[songit-tee <%08lx,%08lx>] Could not remap right channel #%d: Out of channels", - // left->ID, right->ID, i); - } else { - _children[TEE_RIGHT].it->channel_remap[i] = firstfree; - - channel_mask |= (1 << firstfree); - } - } -#ifdef DEBUG_TEE_ITERATOR - if (incomplete_map) { - int c; - fprintf(stderr, "[songit-tee <%08lx,%08lx>] Channels:" - " %04x <- %04x | %04x\n", - left->ID, right->ID, - channel_mask, - left->channel_mask, right->channel_mask); - for (c = 0 ; c < 2; c++) - for (i = 0 ; i < 16; i++) - fprintf(stderr, " map [%d][%d] -> %d\n", - c, i, _children[c].it->channel_remap[i]); - } -#endif - - - song_iterator_add_death_listener(left, this); - song_iterator_add_death_listener(right, this); -} - -TeeSongIterator::~TeeSongIterator() { - // When we die, remove any listeners from our children - if (_children[TEE_LEFT].it) { - song_iterator_remove_death_listener(_children[TEE_LEFT].it, this); - } - - if (_children[TEE_RIGHT].it) { - song_iterator_remove_death_listener(_children[TEE_RIGHT].it, this); - } -} - - -int TeeSongIterator::nextCommand(byte *buf, int *result) { - static const int ready_masks[2] = {TEE_LEFT_READY, TEE_RIGHT_READY}; - static const int active_masks[2] = {TEE_LEFT_ACTIVE, TEE_RIGHT_ACTIVE}; - static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM}; - int i; - int retid; - -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "[Tee] %02x\n", _status); -#endif - - if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))) - /* None is active? */ - return SI_FINISHED; - - if (_readyToMorph) - return SI_MORPH; - - if ((_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)) - != (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE)) { - /* Not all are is active? */ - int which = 0; -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\tRequesting transformation...\n"); -#endif - if (_status & TEE_LEFT_ACTIVE) - which = TEE_LEFT; - else if (_status & TEE_RIGHT_ACTIVE) - which = TEE_RIGHT; - memcpy(buf, _children[which].buf, sizeof(buf)); - *result = _children[which].result; - _readyToMorph = true; - return _children[which].retval; - } - - /* First, check for unreported PCMs */ - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if ((_status & (ready_masks[i] | pcm_masks[i])) - == (ready_masks[i] | pcm_masks[i])) { - _status &= ~ready_masks[i]; - return SI_PCM; - } - - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if (!(_status & ready_masks[i])) { - - /* Buffers aren't ready yet */ - _children[i].retval = - songit_next(&(_children[i].it), - _children[i].buf, - &(_children[i].result), - IT_READER_MASK_ALL - | IT_READER_MAY_FREE - | IT_READER_MAY_CLEAN); - - _status |= ready_masks[i]; -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\t Must check %d: %d\n", i, _children[i].retval); -#endif - - if (_children[i].retval == SI_ABSOLUTE_CUE || - _children[i].retval == SI_RELATIVE_CUE) - return _children[i].retval; - if (_children[i].retval == SI_FINISHED) { - _status &= ~active_masks[i]; - /* Recurse to complete */ -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\t Child %d signalled completion, recursing w/ status %02x\n", i, _status); -#endif - return nextCommand(buf, result); - } else if (_children[i].retval == SI_PCM) { - _status |= pcm_masks[i]; - _status &= ~ready_masks[i]; - return SI_PCM; - } - } - - - /* We've already handled PCM, MORPH and FINISHED, CUEs & LOOP remain */ - - retid = TEE_LEFT; - if ((_children[TEE_LEFT].retval > 0) - /* Asked to delay */ - && (_children[TEE_RIGHT].retval <= _children[TEE_LEFT].retval)) - /* Is not delaying or not delaying as much */ - retid = TEE_RIGHT; - -#ifdef DEBUG_TEE_ITERATOR - fprintf(stderr, "\tl:%d / r:%d / chose %d\n", - _children[TEE_LEFT].retval, _children[TEE_RIGHT].retval, retid); -#endif - - /* Adjust delta times */ - if (_children[retid].retval > 0 - && _children[1-retid].retval > 0) { - if (_children[1-retid].retval - == _children[retid].retval) - /* If both _children wait the same amount of time, - ** we have to re-fetch commands from both */ - _status &= ~ready_masks[1-retid]; - else - /* If they don't, we can/must re-use the other - ** child's delay time */ - _children[1-retid].retval - -= _children[retid].retval; - } - - _status &= ~ready_masks[retid]; - memcpy(buf, _children[retid].buf, sizeof(buf)); - *result = _children[retid].result; - - return _children[retid].retval; -} - -Audio::AudioStream *TeeSongIterator::getAudioStream() { - static const int pcm_masks[2] = {TEE_LEFT_PCM, TEE_RIGHT_PCM}; - int i; - - for (i = TEE_LEFT; i <= TEE_RIGHT; i++) - if (_status & pcm_masks[i]) { - _status &= ~pcm_masks[i]; - return _children[i].it->getAudioStream(); - } - - return NULL; // No iterator -} - -SongIterator *TeeSongIterator::handleMessage(Message msg) { - if (msg._class == _SIMSG_PLASTICWRAP) { - assert(msg._type == _SIMSG_PLASTICWRAP_ACK_MORPH); - - SongIterator *old_it; - if (!(_status & (TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE))) { - delete this; - return NULL; - } else if (!(_status & TEE_LEFT_ACTIVE)) { - delete _children[TEE_LEFT].it; - _children[TEE_LEFT].it = 0; - old_it = _children[TEE_RIGHT].it; - song_iterator_remove_death_listener(old_it, this); - song_iterator_transfer_death_listeners(old_it, this); - delete this; - return old_it; - } else if (!(_status & TEE_RIGHT_ACTIVE)) { - delete _children[TEE_RIGHT].it; - _children[TEE_RIGHT].it = 0; - old_it = _children[TEE_LEFT].it; - song_iterator_remove_death_listener(old_it, this); - song_iterator_transfer_death_listeners(old_it, this); - delete this; - return old_it; - } - - warning("[tee-iterator] Morphing without need"); - return this; - } - - if (msg._class == _SIMSG_BASE && msg._type == _SIMSG_BASEMSG_PRINT) { - print_tabs_id(msg._arg.i, ID); - debugC(2, kDebugLevelSound, "TEE:"); - msg._arg.i++; - } - - // And continue with the children - if (_children[TEE_LEFT].it) - songit_handle_message(&(_children[TEE_LEFT].it), msg); - if (_children[TEE_RIGHT].it) - songit_handle_message(&(_children[TEE_RIGHT].it), msg); - - return NULL; -} - -void TeeSongIterator::init() { - _status = TEE_LEFT_ACTIVE | TEE_RIGHT_ACTIVE; - _children[TEE_LEFT].it->init(); - _children[TEE_RIGHT].it->init(); -} - -SongIterator *TeeSongIterator::clone(int delta) { - TeeSongIterator *newit = new TeeSongIterator(*this); - - if (_children[TEE_LEFT].it) - newit->_children[TEE_LEFT].it = _children[TEE_LEFT].it->clone(delta); - if (_children[TEE_RIGHT].it) - newit->_children[TEE_RIGHT].it = _children[TEE_RIGHT].it->clone(delta); - - return newit; -} - - -/*************************************/ -/*-- General purpose functionality --*/ -/*************************************/ - -int songit_next(SongIterator **it, byte *buf, int *result, int mask) { - int retval; - - if (!*it) - return SI_FINISHED; - - do { - retval = (*it)->nextCommand(buf, result); - if (retval == SI_MORPH) { - debugC(2, kDebugLevelSound, " Morphing %p (stored at %p)", (void *)*it, (void *)it); - if (!SIMSG_SEND((*it), SIMSG_ACK_MORPH)) { - error("SI_MORPH failed. Breakpoint in %s, line %d", __FILE__, __LINE__); - } else - debugC(2, kDebugLevelSound, "SI_MORPH successful"); - } - - if (retval == SI_FINISHED) - debugC(2, kDebugLevelSound, "[song-iterator] Song finished. mask = %04x, cm=%04x", - mask, (*it)->channel_mask); - if (retval == SI_FINISHED - && (mask & IT_READER_MAY_CLEAN) - && (*it)->channel_mask) { /* This last test will fail - ** with a terminated - ** cleanup iterator */ - int channel_mask = (*it)->channel_mask; - - SongIterator *old_it = *it; - *it = new CleanupSongIterator(channel_mask); - for(uint i = 0; i < MIDI_CHANNELS; i++) - (*it)->channel_remap[i] = old_it->channel_remap[i]; - song_iterator_transfer_death_listeners(*it, old_it); - if (mask & IT_READER_MAY_FREE) - delete old_it; - retval = -9999; /* Continue */ - } - } while (!( /* Until one of the following holds */ - (retval > 0 && (mask & IT_READER_MASK_DELAY)) - || (retval == 0 && (mask & IT_READER_MASK_MIDI)) - || (retval == SI_LOOP && (mask & IT_READER_MASK_LOOP)) - || (retval == SI_ABSOLUTE_CUE && - (mask & IT_READER_MASK_CUE)) - || (retval == SI_RELATIVE_CUE && - (mask & IT_READER_MASK_CUE)) - || (retval == SI_PCM && (mask & IT_READER_MASK_PCM)) - || (retval == SI_FINISHED) - )); - - if (retval == SI_FINISHED && (mask & IT_READER_MAY_FREE)) { - delete *it; - *it = NULL; - } - - return retval; -} - -SongIterator::SongIterator() { - ID = 0; - channel_mask = 0; - fade.action = FADE_ACTION_NONE; - priority = 0; - memset(_deathListeners, 0, sizeof(_deathListeners)); - - // By default, don't remap - for (uint i = 0; i < 16; i++) - channel_remap[i] = i; -} - -SongIterator::SongIterator(const SongIterator &si) { - ID = si.ID; - channel_mask = si.channel_mask; - fade = si.fade; - priority = si.priority; - memset(_deathListeners, 0, sizeof(_deathListeners)); - - for (uint i = 0; i < 16; i++) - channel_remap[i] = si.channel_remap[i]; -} - - -SongIterator::~SongIterator() { - for (int i = 0; i < SONGIT_MAX_LISTENERS; ++i) - if (_deathListeners[i]) - songit_tee_death_notification(_deathListeners[i], this); -} - -SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id) { - BaseSongIterator *it; - - if (!data || size < 22) { - warning("Attempt to instantiate song iterator for null song data"); - return NULL; - } - - - switch (type) { - case SCI_SONG_ITERATOR_TYPE_SCI0: - it = new Sci0SongIterator(data, size, id); - break; - - case SCI_SONG_ITERATOR_TYPE_SCI1: - it = new Sci1SongIterator(data, size, id); - break; - - default: - /**-- Invalid/unsupported sound resources --**/ - warning("Attempt to instantiate invalid/unknown song iterator type %d", type); - return NULL; - } - - return it; -} - -int songit_handle_message(SongIterator **it_reg_p, SongIterator::Message msg) { - SongIterator *it = *it_reg_p; - SongIterator *newit; - - newit = it->handleMessage(msg); - - if (!newit) - return 0; /* Couldn't handle */ - - *it_reg_p = newit; /* Might have self-morphed */ - return 1; -} - -SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2) { - if (it1 == NULL) - return it2; - if (it2 == NULL) - return it1; - - /* Both are non-NULL: */ - return new TeeSongIterator(it1, it2); -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/iterator.h b/engines/sci/sound/iterator/iterator.h deleted file mode 100644 index e5c8f50702..0000000000 --- a/engines/sci/sound/iterator/iterator.h +++ /dev/null @@ -1,326 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song iterator declarations */ - -#ifndef SCI_SFX_SFX_ITERATOR_H -#define SCI_SFX_SFX_ITERATOR_H - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/drivers/mididriver.h" - -namespace Audio { - class AudioStream; -} - -namespace Sci { - -enum SongIteratorStatus { - SI_FINISHED = -1, /**< Song finished playing */ - SI_LOOP = -2, /**< Song just looped */ - SI_ABSOLUTE_CUE = -3, /**< Found a song cue (absolute) */ - SI_RELATIVE_CUE = -4, /**< Found a song cue (relative) */ - SI_PCM = -5, /**< Found a PCM */ - SI_IGNORE = -6, /**< This event got edited out by the remapper */ - SI_MORPH = -255 /**< Song iterator requested self-morph. */ -}; - -#define FADE_ACTION_NONE 0 -#define FADE_ACTION_FADE_AND_STOP 1 -#define FADE_ACTION_FADE_AND_CONT 2 - -struct fade_params_t { - int ticks_per_step; - int final_volume; - int step_size; - int action; -}; - -/* Helper defs for messages */ -enum { - _SIMSG_BASE, /* Any base decoder */ - _SIMSG_PLASTICWRAP /* Any "Plastic" (discardable) wrapper decoder */ -}; - -/* Base messages */ -enum { - _SIMSG_BASEMSG_SET_LOOPS, /* Set loops */ - _SIMSG_BASEMSG_SET_PLAYMASK, /* Set the current playmask for filtering */ - _SIMSG_BASEMSG_SET_RHYTHM, /* Activate/deactivate rhythm channel */ - _SIMSG_BASEMSG_ACK_MORPH, /* Acknowledge self-morph */ - _SIMSG_BASEMSG_STOP, /* Stop iterator */ - _SIMSG_BASEMSG_PRINT, /* Print self to stderr, after printing param1 tabs */ - _SIMSG_BASEMSG_SET_HOLD, /* Set value of hold parameter to expect */ - _SIMSG_BASEMSG_SET_FADE /* Set fade parameters */ -}; - -/* "Plastic" (discardable) wrapper messages */ -enum { - _SIMSG_PLASTICWRAP_ACK_MORPH = _SIMSG_BASEMSG_ACK_MORPH /* Acknowledge self-morph */ -}; - -/* Messages */ -#define SIMSG_SET_LOOPS(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_LOOPS,(x) -#define SIMSG_SET_PLAYMASK(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_PLAYMASK,(x) -#define SIMSG_SET_RHYTHM(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_RHYTHM,(x) -#define SIMSG_ACK_MORPH _SIMSG_PLASTICWRAP,_SIMSG_PLASTICWRAP_ACK_MORPH,0 -#define SIMSG_STOP _SIMSG_BASE,_SIMSG_BASEMSG_STOP,0 -#define SIMSG_PRINT(indentation) _SIMSG_BASE,_SIMSG_BASEMSG_PRINT,(indentation) -#define SIMSG_SET_HOLD(x) _SIMSG_BASE,_SIMSG_BASEMSG_SET_HOLD,(x) - -/* Message transmission macro: Takes song reference, message reference */ -#define SIMSG_SEND(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, m)) -#define SIMSG_SEND_FADE(o, m) songit_handle_message(&(o), SongIterator::Message((o)->ID, _SIMSG_BASE, _SIMSG_BASEMSG_SET_FADE, m)) - -typedef unsigned long songit_id_t; - - -#define SONGIT_MAX_LISTENERS 2 - -class TeeSongIterator; - -class SongIterator { -public: - struct Message { - songit_id_t ID; - uint _class; /* Type of iterator supposed to receive this */ - uint _type; - union { - uint i; - void *p; - } _arg; - - Message() : ID(0), _class(0xFFFF), _type(0xFFFF) {} - - /** - * Create a song iterator message. - * - * @param id: song ID the message is targeted to - * @param recipient_class: Message recipient class - * @param type message type - * @param a argument - * - * @note You should only use this with the SIMSG_* macros - */ - Message(songit_id_t id, int recipient_class, int type, int a) - : ID(id), _class(recipient_class), _type(type) { - _arg.i = a; - } - - /** - * Create a song iterator message, wherein the first parameter is a pointer. - * - * @param id: song ID the message is targeted to - * @param recipient_class: Message recipient class - * @param type message type - * @param a argument - * - * @note You should only use this with the SIMSG_* macros - */ - Message(songit_id_t id, int recipient_class, int type, void *a) - : ID(id), _class(recipient_class), _type(type) { - _arg.p = a; - } - }; - -public: - songit_id_t ID; - uint16 channel_mask; /* Bitmask of all channels this iterator will use */ - fade_params_t fade; - int priority; - - /* Death listeners */ - /* These are not reset during initialisation */ - TeeSongIterator *_deathListeners[SONGIT_MAX_LISTENERS]; - - /* See songit_* for the constructor and non-virtual member functions */ - - byte channel_remap[MIDI_CHANNELS]; ///< Remapping for channels - -public: - SongIterator(); - SongIterator(const SongIterator &); - virtual ~SongIterator(); - - /** - * Resets/initializes the sound iterator. - */ - virtual void init() {} - - /** - * Reads the next MIDI operation _or_ delta time. - * @param buf The buffer to write to (needs to be able to store at least 4 bytes) - * @param result Number of bytes written to the buffer - * (equals the number of bytes that need to be passed - * to the lower layers) for 0, the cue value for SI_CUE, - * or the number of loops remaining for SI_LOOP. - * @return zero if a MIDI operation was written, SI_FINISHED - * if the song has finished playing, SI_LOOP if looping - * (after updating the loop variable), SI_CUE if we found - * a cue, SI_PCM if a PCM was found, or the number of ticks - * to wait before this function should be called next. - * - * @note If SI_PCM is returned, get_pcm() may be used to retrieve the associated - * PCM, but this must be done before any subsequent calls to next(). - * - * @todo The actual buffer size should either be specified or passed in, so that - * we can detect buffer overruns. - */ - virtual int nextCommand(byte *buf, int *result) = 0; - - /** - Checks for the presence of a pcm sample. - * @return NULL if no PCM data was found, an AudioStream otherwise. - */ - virtual Audio::AudioStream *getAudioStream() = 0; - - /** - * Handles a message to the song iterator. - * @param msg the message to handle - * @return NULL if the message was not understood, - * this if the message could be handled, or a new song iterator - * if the current iterator had to be morphed (but the message could - * still be handled) - * - * @note This function is not supposed to be called directly; use - * songit_handle_message() instead. It should not recurse, since songit_handle_message() - * takes care of that and makes sure that its delegate received the message (and - * was morphed) before self. - */ - virtual SongIterator *handleMessage(Message msg) = 0; - - /** - * Gets the song position to store in a savegame. - */ - virtual int getTimepos() = 0; - - /** - * Clone this song iterator. - * @param delta number of ticks that still need to elapse until the - * next item should be read from the song iterator - */ - virtual SongIterator *clone(int delta) = 0; - - -private: - // Make the assignment operator unreachable, just in case... - SongIterator& operator=(const SongIterator&); -}; - - -/********************************/ -/*-- Song iterator operations --*/ -/********************************/ - -enum SongIteratorType { - SCI_SONG_ITERATOR_TYPE_SCI0 = 0, - SCI_SONG_ITERATOR_TYPE_SCI1 = 1 -}; - -#define IT_READER_MASK_MIDI (1 << 0) -#define IT_READER_MASK_DELAY (1 << 1) -#define IT_READER_MASK_LOOP (1 << 2) -#define IT_READER_MASK_CUE (1 << 3) -#define IT_READER_MASK_PCM (1 << 4) -#define IT_READER_MAY_FREE (1 << 10) /* Free SI_FINISHED iterators */ -#define IT_READER_MAY_CLEAN (1 << 11) -/* MAY_CLEAN: May instantiate cleanup iterators -** (use for players; this closes open channels at the end of a song) */ - -#define IT_READER_MASK_ALL ( IT_READER_MASK_MIDI \ - | IT_READER_MASK_DELAY \ - | IT_READER_MASK_LOOP \ - | IT_READER_MASK_CUE \ - | IT_READER_MASK_PCM ) - -/* Convenience wrapper around it->next -** Parameters: (SongIterator **it) Reference to the iterator to access -** (byte *) buf: The buffer to write to (needs to be able to -** store at least 4 bytes) -** (int) mask: IT_READER_MASK options specifying the events to -** listen for -** Returns : (int) zero if a MIDI operation was written, SI_FINISHED -** if the song has finished playing, SI_LOOP if looping -** (after updating the loop variable), SI_CUE if we found -** a cue, SI_PCM if a PCM was found, or the number of ticks -** to wait before this function should be called next. -** (int) *result: Number of bytes written to the buffer -** (equals the number of bytes that need to be passed -** to the lower layers) for 0, the cue value for SI_CUE, -** or the number of loops remaining for SI_LOOP. -*/ -int songit_next(SongIterator **it, byte *buf, int *result, int mask); - -/* Constructs a new song iterator object -** Parameters: (byte *) data: The song data to iterate over -** (uint) size: Number of bytes in the song -** (int) type: One of the SCI_SONG_ITERATOR_TYPEs -** (songit_id_t) id: An ID for addressing the song iterator -** Returns : (SongIterator *) A newly allocated but uninitialized song -** iterator, or NULL if 'type' was invalid or unsupported -*/ -SongIterator *songit_new(byte *data, uint size, SongIteratorType type, songit_id_t id); - -/* Constructs a new song timer iterator object -** Parameters: (int) delta: The delta after which to fire SI_FINISHED -** Returns : (SongIterator *) A newly allocated but uninitialized song -** iterator -*/ -SongIterator *new_timer_iterator(int delta); - -/* Handles a message to the song iterator -** Parameters: (SongIterator **): A reference to the variable storing the song iterator -** Returns : (int) Non-zero if the message was understood -** The song iterator may polymorph as result of msg, so a writeable reference is required. -*/ -int songit_handle_message(SongIterator **it_reg, SongIterator::Message msg); - - -/* Creates a new song iterator which fast-forwards -** Parameters: (SongIterator *) it: The iterator to wrap -** (int) delta: The number of ticks to skip -** Returns : (SongIterator) A newly created song iterator -** which skips all delta times -** until 'delta' has been used up -*/ -SongIterator *new_fast_forward_iterator(SongIterator *it, int delta); - -/* Combines two song iterators into one -** Parameters: (sfx_iterator_t *) it1: One of the two iterators, or NULL -** (sfx_iterator_t *) it2: The other iterator, or NULL -** Returns : (sfx_iterator_t *) A combined iterator -** If a combined iterator is returned, it will be flagged to be allowed to -** dispose of 'it1' and 'it2', where applicable. This means that this -** call should be used by song players, but not by the core sound system -*/ -SongIterator *sfx_iterator_combine(SongIterator *it1, SongIterator *it2); - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_SFX_ITERATOR_H diff --git a/engines/sci/sound/iterator/iterator_internal.h b/engines/sci/sound/iterator/iterator_internal.h deleted file mode 100644 index 5a0f0d3ec9..0000000000 --- a/engines/sci/sound/iterator/iterator_internal.h +++ /dev/null @@ -1,276 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#ifndef SCI_SFX_SFX_ITERATOR_INTERNAL -#define SCI_SFX_SFX_ITERATOR_INTERNAL - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/iterator.h" -#include "sci/sound/drivers/mididriver.h" - -#include "common/array.h" -#include "common/list.h" - -namespace Sci { - -/* Iterator types */ - -enum { - SI_STATE_UNINITIALISED = -1, - SI_STATE_DELTA_TIME = 0, ///< Now at a delta time - SI_STATE_COMMAND = 1, ///< Now at a MIDI operation - SI_STATE_PENDING = 2, ///< Pending for loop - SI_STATE_FINISHED = 3, ///< End of song - SI_STATE_PCM = 4, ///< Should report a PCM next (-> DELTA_TIME) - SI_STATE_PCM_MAGIC_DELTA = 5 ///< Should report a ``magic'' one tick delta time next (goes on to FINISHED) -}; - -struct SongIteratorChannel { - - int state; ///< State of this song iterator channel - int offset; ///< Offset into the data chunk */ - int end; ///< Last allowed byte in track */ - int id; ///< Some channel ID */ - - /** - * Number of ticks before the specified channel is next used, or - * CHANNEL_DELAY_MISSING to indicate that the delay has not yet - * been read. - */ - int delay; - - /* Two additional offsets for recovering: */ - int loop_offset; - int initial_offset; - - int playmask; ///< Active playmask (MIDI channels to play in here) */ - int loop_timepos; ///< Total delay for this channel's loop marker */ - int total_timepos; ///< Number of ticks since the beginning, ignoring loops */ - int timepos_increment; ///< Number of ticks until the next command (to add) */ - - byte last_cmd; ///< Last operation executed, for running status */ - -public: - void init(int id, int offset, int end); - void resetSynthChannels(); -}; - -class BaseSongIterator : public SongIterator { -public: - int _polyphony[MIDI_CHANNELS]; ///< # of simultaneous notes on each - - int _ccc; ///< Cumulative cue counter, for those who need it - byte _resetflag; ///< for 0x4C -- on DoSound StopSound, do we return to start? - int _deviceId; ///< ID of the device we generating events for - int _numActiveChannels; ///< Number of active channels - Common::Array _data; ///< Song data - - int _loops; ///< Number of loops remaining - -public: - BaseSongIterator(byte *data, uint size, songit_id_t id); - -protected: - int parseMidiCommand(byte *buf, int *result, SongIteratorChannel *channel, int flags); - int processMidi(byte *buf, int *result, SongIteratorChannel *channel, int flags); -}; - -/********************************/ -/*--------- SCI 0 --------------*/ -/********************************/ - -class Sci0SongIterator : public BaseSongIterator { -public: - SongIteratorChannel _channel; - -public: - Sci0SongIterator(byte *data, uint size, songit_id_t id); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos(); - SongIterator *clone(int delta); -}; - - -/********************************/ -/*--------- SCI 1 --------------*/ -/********************************/ - - -struct Sci1Sample { - /** - * Time left-- initially, this is 'Sample point 1'. - * After initialisation, it is 'sample point 1 minus the sample - * point of the previous sample' - */ - int delta; - int size; - bool announced; /* Announced for download (SI_PCM) */ - int rate; - byte *_data; -}; - -class Sci1SongIterator : public BaseSongIterator { -public: - SongIteratorChannel _channels[MIDI_CHANNELS]; - - /* Invariant: Whenever channels[i].delay == CHANNEL_DELAY_MISSING, - ** channel_offset[i] points to a delta time object. */ - - bool _initialised; /**!< Whether the MIDI channel setup has been initialised */ - int _numChannels; /**!< Number of channels actually used */ - Common::List _samples; - int _numLoopedChannels; /**!< Number of channels that are ready to loop */ - - int _delayRemaining; /**!< Number of ticks that haven't been polled yet */ - int _hold; - -public: - Sci1SongIterator(byte *data, uint size, songit_id_t id); - ~Sci1SongIterator(); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos(); - SongIterator *clone(int delta); - -private: - int initSample(const int offset); - int initSong(); - - int getSmallestDelta() const; - - void updateDelta(int delta); - - /** Checks that none of the channels is waiting for its delta to be read */ - bool noDeltaTime() const; - - /** Determine the channel # of the next active event, or -1 */ - int getCommandIndex() const; -}; - -#define PLAYMASK_NONE 0x0 - -/***************************/ -/*--------- Timer ---------*/ -/***************************/ - -/** - * A song iterator which waits a specified time and then fires - * SI_FINISHED. Used by DoSound, where audio resources are played (SCI1) - */ -class TimerSongIterator : public SongIterator { -protected: - int _delta; /**!< Remaining time */ - -public: - TimerSongIterator(int delta) : _delta(delta) {} - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream() { return NULL; } - SongIterator *handleMessage(Message msg) { return NULL; } - int getTimepos() { return 0; } - SongIterator *clone(int delta) { return new TimerSongIterator(*this); } -}; - -/**********************************/ -/*--------- Fast Forward ---------*/ -/**********************************/ - -/** - * A song iterator which fast-forwards another iterator. - * Skips all delta times until a specified 'delta' has been used up. - */ -class FastForwardSongIterator : public SongIterator { -protected: - SongIterator *_delegate; - int _delta; /**!< Remaining time */ - -public: - FastForwardSongIterator(SongIterator *capsit, int delta); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - int getTimepos(); - SongIterator *clone(int delta); -}; - - -/**********************************/ -/*--------- Tee iterator ---------*/ -/**********************************/ - -enum { - TEE_LEFT = 0, - TEE_RIGHT = 1, - TEE_LEFT_ACTIVE = (1<<0), - TEE_RIGHT_ACTIVE = (1<<1), - TEE_LEFT_READY = (1<<2), /**!< left result is ready */ - TEE_RIGHT_READY = (1<<3), /**!< right result is ready */ - TEE_LEFT_PCM = (1<<4), - TEE_RIGHT_PCM = (1<<5) -}; - -/** - * This iterator combines two iterators, returns the next event available from either. - */ -class TeeSongIterator : public SongIterator { -public: - int _status; - - bool _readyToMorph; /**!< One of TEE_MORPH_* above */ - - struct { - SongIterator *it; - byte buf[4]; - int result; - int retval; - } _children[2]; - -public: - TeeSongIterator(SongIterator *left, SongIterator *right); - ~TeeSongIterator(); - - int nextCommand(byte *buf, int *result); - Audio::AudioStream *getAudioStream(); - SongIterator *handleMessage(Message msg); - void init(); - int getTimepos() { return 0; } - SongIterator *clone(int delta); -}; - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS - -#endif // SCI_SFX_SFX_ITERATOR_INTERNAL diff --git a/engines/sci/sound/iterator/songlib.cpp b/engines/sci/sound/iterator/songlib.cpp deleted file mode 100644 index 8bc2e8f476..0000000000 --- a/engines/sci/sound/iterator/songlib.cpp +++ /dev/null @@ -1,189 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/core.h" -#include "sci/sound/iterator/iterator.h" - -namespace Sci { - -#define debug_stream stderr - -Song::Song() : _wakeupTime(0, SFX_TICKS_PER_SEC) { - _handle = 0; - _resourceNum = 0; - _priority = 0; - _status = SOUND_STATUS_STOPPED; - - _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; - _restoreTime = 0; - - _loops = 0; - _hold = 0; - - _it = 0; - _delay = 0; - - _next = NULL; - _nextPlaying = NULL; - _nextStopping = NULL; -} - -Song::Song(SongHandle handle, SongIterator *it, int priority) : _wakeupTime(0, SFX_TICKS_PER_SEC) { - _handle = handle; - _resourceNum = 0; - _priority = priority; - _status = SOUND_STATUS_STOPPED; - - _restoreBehavior = RESTORE_BEHAVIOR_CONTINUE; - _restoreTime = 0; - - _loops = 0; - _hold = 0; - - _it = it; - _delay = 0; - - _next = NULL; - _nextPlaying = NULL; - _nextStopping = NULL; -} - -void SongLibrary::addSong(Song *song) { - Song **seeker = NULL; - int pri = song->_priority; - - if (NULL == song) { - warning("addSong(): NULL passed for song"); - return; - } - - seeker = &_lib; - while (*seeker && ((*seeker)->_priority > pri)) - seeker = &((*seeker)->_next); - - song->_next = *seeker; - *seeker = song; -} - -void SongLibrary::freeSounds() { - Song *next = _lib; - while (next) { - Song *song = next; - delete song->_it; - song->_it = NULL; - next = song->_next; - delete song; - } - _lib = NULL; -} - - -Song *SongLibrary::findSong(SongHandle handle) { - Song *seeker = _lib; - - while (seeker) { - if (seeker->_handle == handle) - break; - seeker = seeker->_next; - } - - return seeker; -} - -Song *SongLibrary::findNextActive(Song *other) { - Song *seeker = other ? other->_next : _lib; - - while (seeker) { - if ((seeker->_status == SOUND_STATUS_WAITING) || - (seeker->_status == SOUND_STATUS_PLAYING)) - break; - seeker = seeker->_next; - } - - /* Only return songs that have equal priority */ - if (other && seeker && other->_priority > seeker->_priority) - return NULL; - - return seeker; -} - -Song *SongLibrary::findFirstActive() { - return findNextActive(NULL); -} - -int SongLibrary::removeSong(SongHandle handle) { - int retval; - Song *goner = _lib; - - if (!goner) - return -1; - - if (goner->_handle == handle) - _lib = goner->_next; - - else { - while ((goner->_next) && (goner->_next->_handle != handle)) - goner = goner->_next; - - if (goner->_next) { /* Found him? */ - Song *oldnext = goner->_next; - - goner->_next = goner->_next->_next; - goner = oldnext; - } else return -1; /* No. */ - } - - retval = goner->_status; - - delete goner->_it; - delete goner; - - return retval; -} - -int SongLibrary::countSongs() { - Song *seeker = _lib; - int retval = 0; - - while (seeker) { - retval++; - seeker = seeker->_next; - } - - return retval; -} - -void SongLibrary::setSongRestoreBehavior(SongHandle handle, RESTORE_BEHAVIOR action) { - Song *seeker = findSong(handle); - - seeker->_restoreBehavior = action; -} - -} // End of namespace Sci - -#endif // USE_OLD_MUSIC_FUNCTIONS diff --git a/engines/sci/sound/iterator/songlib.h b/engines/sci/sound/iterator/songlib.h deleted file mode 100644 index acb704edaa..0000000000 --- a/engines/sci/sound/iterator/songlib.h +++ /dev/null @@ -1,171 +0,0 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - * $URL$ - * $Id$ - * - */ - -/* Song library */ - -#ifndef SCI_SFX_SFX_SONGLIB_H -#define SCI_SFX_SFX_SONGLIB_H - -#include "common/scummsys.h" -#include "sound/timestamp.h" - -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS -#ifdef USE_OLD_MUSIC_FUNCTIONS - -namespace Sci { - -class SongIterator; - -#define SOUND_STATUS_STOPPED 0 -#define SOUND_STATUS_PLAYING 1 -#define SOUND_STATUS_SUSPENDED 2 -/* suspended: only if ordered from kernel space */ -#define SOUND_STATUS_WAITING 3 -/* "waiting" means "tagged for playing, but not active right now" */ - -typedef unsigned long SongHandle; - -enum RESTORE_BEHAVIOR { - RESTORE_BEHAVIOR_CONTINUE, /* restart a song when restored from - a saved game */ - RESTORE_BEHAVIOR_RESTART /* continue it from where it was */ -}; - -class Song { -public: - SongHandle _handle; - int _resourceNum; /** -#include - -using namespace Sci; - -#define ASSERT_S(x) if (!(x)) { error("Failed assertion in L%d: " #x, __LINE__); return; } -#define ASSERT(x) ASSERT_S(x) - -/* Tests the song iterators */ - -int errors = 0; - -void error(char *fmt, ...) { - va_list ap; - - fprintf(stderr, "[ERROR] "); - va_start(ap, fmt); - vfprintf(stderr, fmt, ap); - va_end(ap); - - ++errors; -} - - -/* The simple iterator will finish after a fixed amount of time. Before that, -** it emits (absolute) cues in ascending order. */ -struct simple_iterator : public SongIterator { - int lifetime_remaining; - char *cues; - int cue_counter; - int cue_progress; - int cues_nr; -}; - -int simple_it_next(SongIterator *_self, unsigned char *buf, int *result) { - simple_iterator *self = (simple_iterator *)_self; - - if (self->lifetime_remaining == -1) { - error("Song iterator called post mortem"); - return SI_FINISHED; - } - - if (self->lifetime_remaining) { - - if (self->cue_counter < self->cues_nr) { - int time_to_cue = self->cues[self->cue_counter]; - - if (self->cue_progress == time_to_cue) { - ++self->cue_counter; - self->cue_progress = 0; - *result = self->cue_counter; - return SI_ABSOLUTE_CUE; - } else { - int retval = time_to_cue - self->cue_progress; - self->cue_progress = time_to_cue; - - if (retval > self->lifetime_remaining) { - retval = self->lifetime_remaining; - self->lifetime_remaining = 0; - self->cue_progress = retval; - return retval; - } - - self->lifetime_remaining -= retval; - return retval; - } - } else { - int retval = self->lifetime_remaining; - self->lifetime_remaining = 0; - return retval; - } - - } else { - self->lifetime_remaining = -1; - return SI_FINISHED; - } -} - -Audio::AudioStream *simple_it_pcm_feed(SongIterator *_self) { - error("No PCM feed"); - return NULL; -} - -void simple_it_init(SongIterator *_self) { -} - -SongIterator *simple_it_handle_message(SongIterator *_self, SongIterator::Message msg) { - return NULL; -} - -void simple_it_cleanup(SongIterator *_self) { -} - -/* Initialises the simple iterator. -** Parameters: (int) delay: Number of ticks until the iterator finishes -** (int *) cues: An array of cue delays (cue values are [1,2...]) -** (int) cues_nr: Number of cues in ``cues'' -** The first cue is emitted after cues[0] ticks, and it is 1. After cues[1] additional ticks -** the next cue is emitted, and so on. */ -SongIterator *setup_simple_iterator(int delay, char *cues, int cues_nr) { - simple_iterator.lifetime_remaining = delay; - simple_iterator.cues = cues; - simple_iterator.cue_counter = 0; - simple_iterator.cues_nr = cues_nr; - simple_iterator.cue_progress = 0; - - simple_iterator.ID = 42; - simple_iterator.channel_mask = 0x004f; - simple_iterator.flags = 0; - simple_iterator.priority = 1; - - simple_iterator.death_listeners_nr = 0; - - simple_iterator.cleanup = simple_it_cleanup; - simple_iterator.init = simple_it_init; - simple_iterator.handle_message = simple_it_handle_message; - simple_iterator.get_pcm_feed = simple_it_pcm_feed; - simple_iterator.next = simple_it_next; - - return (SongIterator *) &simple_iterator; -} - -#define ASSERT_SIT ASSERT(it == simple_it) -#define ASSERT_FFIT ASSERT(it == ff_it) -#define ASSERT_NEXT(n) ASSERT(songit_next(&it, data, &result, IT_READER_MASK_ALL) == n) -#define ASSERT_RESULT(n) ASSERT(result == n) -#define ASSERT_CUE(n) ASSERT_NEXT(SI_ABSOLUTE_CUE); ASSERT_RESULT(n) - -void test_simple_it() { - SongIterator *it; - SongIterator *simple_it = (SongIterator *) & simple_iterator; - unsigned char data[4]; - int result; - puts("[TEST] simple iterator (test artifact)"); - - it = setup_simple_iterator(42, NULL, 0); - - ASSERT_SIT; - ASSERT_NEXT(42); - ASSERT_SIT; - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ASSERT_SIT; - ASSERT_NEXT(3); - ASSERT_CUE(1); - ASSERT_SIT; - ASSERT_NEXT(4); - ASSERT_CUE(2); - ASSERT_SIT; -// warning("XXX => %d", songit_next(&it, data, &result, IT_READER_MASK_ALL)); - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - puts("[TEST] Test OK."); -} - -void test_fastforward() { - SongIterator *it; - SongIterator *simple_it = (SongIterator *) & simple_iterator; - SongIterator *ff_it; - unsigned char data[4]; - int result; - puts("[TEST] fast-forward iterator"); - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 0); - ASSERT_FFIT; - ASSERT_NEXT(42); - ASSERT_SIT; /* Must have morphed back */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 1); - ASSERT_FFIT; - ASSERT_NEXT(41); - /* May or may not have morphed back here */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 41); - ASSERT_FFIT; - ASSERT_NEXT(1); - /* May or may not have morphed back here */ - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 42); - ASSERT_NEXT(SI_FINISHED); - /* May or may not have morphed back here */ - - it = setup_simple_iterator(42, NULL, 0); - ff_it = it = new_fast_forward_iterator(it, 10000); - ASSERT_NEXT(SI_FINISHED); - /* May or may not have morphed back here */ - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 2); - ASSERT_FFIT; - ASSERT_NEXT(1); - ASSERT_CUE(1); - ASSERT_SIT; - ASSERT_NEXT(4); - ASSERT_CUE(2); - ASSERT_SIT; - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 5); - ASSERT_FFIT; - ASSERT_CUE(1); - ASSERT_FFIT; - ASSERT_NEXT(2); - ASSERT_CUE(2); - ASSERT_SIT; - ASSERT_NEXT(35); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - it = setup_simple_iterator(42, "\003\004", 2); - ff_it = it = new_fast_forward_iterator(it, 41); - ASSERT_FFIT; - ASSERT_CUE(1); - ASSERT_FFIT; - ASSERT_CUE(2); - ASSERT_FFIT; - ASSERT_NEXT(1); - ASSERT_NEXT(SI_FINISHED); - ASSERT_SIT; - - puts("[TEST] Test OK."); -} - -#define SIMPLE_SONG_SIZE 50 - -static unsigned char simple_song[SIMPLE_SONG_SIZE] = { - 0x00, /* Regular song */ - /* Only use channel 0 for all devices */ - 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Song begins here */ - 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */ - 02, 64, 0x42, /* Play E after 2 more ticks, using running status mode */ - 0xf8, 10, 0x80, 60, 0x02, /* Stop C after 250 ticks */ - 0, 64, 0x00, /* Stop E immediately */ - 00, 0xfc /* Stop song */ -}; - -#define ASSERT_MIDI3(cmd, arg0, arg1) \ - ASSERT(data[0] == cmd); \ - ASSERT(data[1] == arg0); \ - ASSERT(data[2] == arg1); - -void test_iterator_sci0() { - SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - - puts("[TEST] SCI0-style song"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -void test_iterator_sci0_loop() { - SongIterator *it = songit_new(simple_song, SIMPLE_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - SIMSG_SEND(it, SIMSG_SET_LOOPS(2)); /* Loop one additional time */ - - puts("[TEST] SCI0-style song with looping"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(250); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x02); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -#define LOOP_SONG_SIZE 54 - -unsigned char loop_song[LOOP_SONG_SIZE] = { - 0x00, /* Regular song song */ - /* Only use channel 0 for all devices */ - 0x02, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, - /* Song begins here */ - 42, 0x90, 60, 0x7f, /* Play C after 42 ticks */ - 13, 0x80, 60, 0x00, /* Stop C after 13 ticks */ - 00, 0xCF, 0x7f, /* Set loop point */ - 02, 0x90, 64, 0x42, /* Play E after 2 more ticks, using running status mode */ - 03, 0x80, 64, 0x00, /* Stop E after 3 ticks */ - 00, 0xfc /* Stop song/loop */ -}; - - -void test_iterator_sci0_mark_loop() { - SongIterator *it = songit_new(loop_song, LOOP_SONG_SIZE, SCI_SONG_ITERATOR_TYPE_SCI0, 0l); - unsigned char data[4]; - int result; - SIMSG_SEND(it, SIMSG_SET_PLAYMASK(0x0001)); /* Initialise song, enabling channel 0 */ - SIMSG_SEND(it, SIMSG_SET_LOOPS(3)); /* Loop once more */ - - puts("[TEST] SCI0-style song with loop mark, looping"); - ASSERT_NEXT(42); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 60, 0x7f); - ASSERT_NEXT(13); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 60, 0x00); - /* Loop point here: we don't observe that in the iterator interface yet, though */ - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - /* Now we loop back to the loop pont */ - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - /* ...and one final time */ - ASSERT_NEXT(SI_LOOP); - ASSERT_NEXT(2); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x90, 64, 0x42); - ASSERT_NEXT(3); - ASSERT_NEXT(0); - ASSERT_MIDI3(0x80, 64, 0x00); - - ASSERT_NEXT(SI_FINISHED); - puts("[TEST] Test OK."); -} - - - -int main(int argc, char **argv) { - test_simple_it(); - test_fastforward(); - test_iterator_sci0(); - test_iterator_sci0_loop(); - test_iterator_sci0_mark_loop(); - if (errors != 0) - warning("[ERROR] %d errors total", errors); - return (errors != 0); -} diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index a29b6edee2..486848b48f 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -26,15 +26,11 @@ #ifndef SCI_MUSIC_H #define SCI_MUSIC_H -#ifndef USE_OLD_MUSIC_FUNCTIONS #include "common/serializer.h" -#endif #include "common/mutex.h" #include "sound/mixer.h" #include "sound/audiostream.h" -//#include "sound/mididrv.h" -//#include "sound/midiparser.h" #include "sci/sci.h" #include "sci/resource.h" @@ -55,11 +51,7 @@ enum SoundStatus { class MidiParser_SCI; class SegManager; -class MusicEntry -#ifndef USE_OLD_MUSIC_FUNCTIONS - : public Common::Serializable -#endif -{ +class MusicEntry : public Common::Serializable { public: // Do not get these directly for the sound objects! // It's a bad idea, as the sound code (i.e. the SciMusic @@ -96,9 +88,6 @@ public: Audio::Mixer::SoundType soundType; -#ifndef USE_OLD_MUSIC_FUNCTIONS -//protected: -#endif MidiParser_SCI *pMidiParser; // TODO: We need to revise how we store the different @@ -114,19 +103,13 @@ public: void doFade(); void onTimer(); -#ifndef USE_OLD_MUSIC_FUNCTIONS virtual void saveLoadWithSerializer(Common::Serializer &ser); -#endif }; typedef Common::Array MusicList; typedef Common::Array MidiCommandQueue; -class SciMusic -#ifndef USE_OLD_MUSIC_FUNCTIONS - : public Common::Serializable -#endif -{ +class SciMusic : public Common::Serializable { public: SciMusic(SciVersion soundVersion); @@ -193,9 +176,7 @@ public: void setReverb(byte reverb); -#ifndef USE_OLD_MUSIC_FUNCTIONS virtual void saveLoadWithSerializer(Common::Serializer &ser); -#endif // Mutex for music code. Used to guard access to the song playlist, to the // MIDI parser and to the MIDI driver/player. Note that guarded code must NOT diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 7cdb3e08bf..d318b1ced0 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -23,12 +23,6 @@ * */ -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - -#ifdef USE_OLD_MUSIC_FUNCTIONS -#include "sci/sound/iterator/iterator.h" // for SongIteratorStatus -#endif - #include "common/config-manager.h" #include "sci/sound/audio.h" #include "sci/sound/music.h" @@ -42,107 +36,13 @@ namespace Sci { #define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */ #define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */ -#ifdef USE_OLD_MUSIC_FUNCTIONS -#define FROBNICATE_HANDLE(reg) ((reg).segment << 16 | (reg).offset) -#define DEFROBNICATE_HANDLE(handle) (make_reg((handle >> 16) & 0xffff, handle & 0xffff)) -#endif - #define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x)) -#ifdef USE_OLD_MUSIC_FUNCTIONS -static void script_set_priority(ResourceManager *resMan, SegManager *segMan, SfxState *state, reg_t obj, int priority) { - int song_nr = readSelectorValue(segMan, obj, SELECTOR(number)); - Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0); - int flags = readSelectorValue(segMan, obj, SELECTOR(flags)); - - if (priority == -1) { - if (song->data[0] == 0xf0) - priority = song->data[1]; - else - warning("Attempt to unset song priority when there is no built-in value"); - - flags &= ~SCI1_SOUND_FLAG_SCRIPTED_PRI; - } else flags |= SCI1_SOUND_FLAG_SCRIPTED_PRI; - - state->sfx_song_renice(FROBNICATE_HANDLE(obj), priority); - writeSelectorValue(segMan, obj, SELECTOR(flags), flags); -} - -SongIterator *build_iterator(ResourceManager *resMan, int song_nr, SongIteratorType type, songit_id_t id) { - Resource *song = resMan->findResource(ResourceId(kResourceTypeSound, song_nr), 0); - - if (!song) - return NULL; - - return songit_new(song->data, song->size, type, id); -} - -void process_sound_events(EngineState *s) { /* Get all sound events, apply their changes to the heap */ - int result; - SongHandle handle; - int cue; - SegManager *segMan = s->_segMan; - - if (getSciVersion() > SCI_VERSION_01) - return; - // SCI1 and later explicitly poll for everything - - while ((result = s->_sound.sfx_poll(&handle, &cue))) { - reg_t obj = DEFROBNICATE_HANDLE(handle); - if (!s->_segMan->isObject(obj)) { - warning("Non-object %04x:%04x received sound signal (%d/%d)", PRINT_REG(obj), result, cue); - return; - } - - switch (result) { - - case SI_LOOP: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x looped (to %d)", - PRINT_REG(obj), cue); - /* writeSelectorValue(segMan, obj, SELECTOR(loops), readSelectorValue(segMan, obj, SELECTOR(loop));; - 1);*/ - writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - break; - - case SI_RELATIVE_CUE: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received relative cue %d", - PRINT_REG(obj), cue); - writeSelectorValue(segMan, obj, SELECTOR(signal), cue + 0x7f); - break; - - case SI_ABSOLUTE_CUE: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x received absolute cue %d", - PRINT_REG(obj), cue); - writeSelectorValue(segMan, obj, SELECTOR(signal), cue); - break; - - case SI_FINISHED: - debugC(2, kDebugLevelSound, "[process-sound] Song %04x:%04x finished", - PRINT_REG(obj)); - writeSelectorValue(segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - writeSelectorValue(segMan, obj, SELECTOR(state), kSoundStopped); - break; - - default: - warning("Unexpected result from sfx_poll: %d", result); - break; - } - } -} - -#endif SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - // The following hack is needed to ease the change from old to new sound - // code (because the new sound code does not use SfxState) - _state = &g_sci->getEngineState()->_sound; // HACK -#endif - - #ifndef USE_OLD_MUSIC_FUNCTIONS - _music = new SciMusic(_soundVersion); - _music->init(); - #endif + _music = new SciMusic(_soundVersion); + _music->init(); switch (_soundVersion) { case SCI_VERSION_0_EARLY: @@ -215,9 +115,7 @@ SoundCommandParser::~SoundCommandParser() { for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i) delete *i; -#ifndef USE_OLD_MUSIC_FUNCTIONS delete _music; -#endif } reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { @@ -261,40 +159,6 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number)); -#ifdef USE_OLD_MUSIC_FUNCTIONS - - SongHandle handle = FROBNICATE_HANDLE(obj); - - if (_soundVersion != SCI_VERSION_1_LATE) { - if (!obj.segment) - return; - } - - SongIteratorType type = (_soundVersion <= SCI_VERSION_0_LATE) ? SCI_SONG_ITERATOR_TYPE_SCI0 : SCI_SONG_ITERATOR_TYPE_SCI1; - - if (_soundVersion <= SCI_VERSION_0_LATE) { - if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr))) { - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _state->sfx_remove_song(handle); - } - } - - if (!obj.segment || !_resMan->testResource(ResourceId(kResourceTypeSound, resourceId))) - return; - - _state->sfx_add_song(build_iterator(_resMan, resourceId, type, handle), 0, handle, resourceId); - - - // Notify the engine - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundInitialized); - else - writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); - - writeSelector(_segMan, obj, SELECTOR(handle), obj); - -#else - // Check if a track with the same sound object is already playing MusicEntry *oldSound = _music->getSlot(obj); if (oldSound) @@ -342,84 +206,12 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { writeSelector(_segMan, obj, SELECTOR(handle), obj); } -#endif - } void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - - if (_soundVersion <= SCI_VERSION_0_LATE) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundPlaying); - } else if (_soundVersion == SCI_VERSION_1_EARLY) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - _state->sfx_song_renice(handle, readSelectorValue(_segMan, obj, SELECTOR(pri))); - RESTORE_BEHAVIOR rb = (RESTORE_BEHAVIOR) value; /* Too lazy to look up a default value for this */ - _state->_songlib.setSongRestoreBehavior(handle, rb); - writeSelectorValue(_segMan, obj, SELECTOR(signal), 0); - } else if (_soundVersion == SCI_VERSION_1_LATE) { - int looping = readSelectorValue(_segMan, obj, SELECTOR(loop)); - //int vol = readSelectorValue(_segMan, obj, SELECTOR(vol)); - int pri = readSelectorValue(_segMan, obj, SELECTOR(pri)); - int sampleLen = 0; - Song *song = _state->_songlib.findSong(handle); - int songNumber = readSelectorValue(_segMan, obj, SELECTOR(number)); - - if (readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && (song && songNumber != song->_resourceNum)) { - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - _state->sfx_remove_song(handle); - writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); - } - - if (!readSelectorValue(_segMan, obj, SELECTOR(nodePtr)) && obj.segment) { - // In SCI1.1 games, sound effects are started from here. If we can - // find a relevant audio resource, play it, otherwise switch to - // synthesized effects. If the resource exists, play it using map - // 65535 (sound effects map). - if (_resMan->testResource(ResourceId(kResourceTypeAudio, songNumber)) && - getSciVersion() >= SCI_VERSION_1_1) { - // Found a relevant audio resource, play it - _audio->stopAudio(); - warning("Initializing audio resource instead of requested sound resource %d", songNumber); - sampleLen = _audio->startAudio(65535, songNumber); - // Also create iterator, that will fire SI_FINISHED event, when - // the sound is done playing. - _state->sfx_add_song(new_timer_iterator(sampleLen), 0, handle, songNumber); - } else { - if (!_resMan->testResource(ResourceId(kResourceTypeSound, songNumber))) { - warning("Could not open song number %d", songNumber); - // Send a "stop handle" event so that the engine won't wait - // forever here. - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - return; - } - debugC(2, kDebugLevelSound, "Initializing song number %d", songNumber); - _state->sfx_add_song(build_iterator(_resMan, songNumber, SCI_SONG_ITERATOR_TYPE_SCI1, - handle), 0, handle, songNumber); - } - - writeSelector(_segMan, obj, SELECTOR(nodePtr), obj); - writeSelector(_segMan, obj, SELECTOR(handle), obj); - } - - if (obj.segment) { - _state->sfx_song_set_status(handle, SOUND_STATUS_PLAYING); - _state->sfx_song_set_loops(handle, looping); - _state->sfx_song_renice(handle, pri); - writeSelectorValue(_segMan, obj, SELECTOR(signal), 0); - } - } - -#else - MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -456,43 +248,16 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { musicSlot->loop, musicSlot->priority, musicSlot->volume); _music->soundPlay(musicSlot); - -#endif - } void SoundCommandParser::cmdDummy(reg_t obj, int16 value) { warning("cmdDummy invoked"); // not supposed to occur } -#ifdef USE_OLD_MUSIC_FUNCTIONS -void SoundCommandParser::changeSoundStatus(reg_t obj, int newStatus) { - SongHandle handle = FROBNICATE_HANDLE(obj); - if (obj.segment) { - _state->sfx_song_set_status(handle, newStatus); - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), newStatus); - } -} -#endif - void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - changeSoundStatus(obj, SOUND_STATUS_STOPPED); - - if (obj.segment) { - _state->sfx_remove_song(handle); - - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(handle), 0x0000); - } - -#else - MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -507,7 +272,6 @@ void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { writeSelector(_segMan, obj, SELECTOR(nodePtr), NULL_REG); else writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); -#endif } void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) { @@ -518,12 +282,6 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - changeSoundStatus(obj, SOUND_STATUS_STOPPED); - - if (_soundVersion >= SCI_VERSION_1_EARLY) - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -549,20 +307,9 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin musicSlot->dataInc = 0; musicSlot->signal = 0; _music->soundStop(musicSlot); -#endif } void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (!obj.segment) - return; - - if (_soundVersion <= SCI_VERSION_0_LATE) - changeSoundStatus(obj, SOUND_STATUS_SUSPENDED); - else - changeSoundStatus(obj, value ? SOUND_STATUS_SUSPENDED : SOUND_STATUS_PLAYING); -#else - if (!obj.segment) { // pause the whole playlist // Pausing/Resuming the whole playlist was introduced in the SCI1 late // sound scheme. @@ -585,8 +332,6 @@ void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { _music->soundToggle(musicSlot, value); } } - -#endif } void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { @@ -595,9 +340,6 @@ void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - changeSoundStatus(obj, SOUND_STATUS_PLAYING); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -606,24 +348,15 @@ void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); _music->soundResume(musicSlot); -#endif } void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS if (_argc > 1) // the first parameter is the sound command _music->soundSetSoundOn(obj.toUint16()); _acc = make_reg(0, _music->soundGetSoundOn()); -#endif } void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _acc = make_reg(0, _state->sfx_getVolume()); - - if (obj != SIGNAL_REG) - _state->sfx_setVolume(obj.toSint16()); -#else debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value); _acc = make_reg(0, _music->soundGetMasterVolume()); @@ -634,44 +367,12 @@ void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) { ConfMan.setInt("sfx_volume", vol); g_engine->syncSoundSettings(); } -#endif } void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - if (_soundVersion != SCI_VERSION_1_LATE) { - /* FIXME: The next couple of lines actually STOP the handle, rather - ** than fading it! */ - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - if (_soundVersion <= SCI_VERSION_0_LATE) - writeSelectorValue(_segMan, obj, SELECTOR(state), SOUND_STATUS_STOPPED); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } else { - fade_params_t fade; - fade.final_volume = _argv[2].toUint16(); - fade.ticks_per_step = _argv[3].toUint16(); - fade.step_size = _argv[4].toUint16(); - fade.action = _argv[5].toUint16() ? - FADE_ACTION_FADE_AND_STOP : - FADE_ACTION_FADE_AND_CONT; - - _state->sfx_song_set_fade(handle, &fade); - - /* FIXME: The next couple of lines actually STOP the handle, rather - ** than fading it! */ - if (_argv[5].toUint16()) { - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - _state->sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - } else { - // FIXME: Support fade-and-continue. For now, send signal right away. - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - } - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -711,28 +412,16 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { } debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); -#endif } void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - _acc = make_reg(0, _state->sfx_get_player_polyphony()); -#else _acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices -#endif } void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - if (_soundVersion <= SCI_VERSION_0_LATE && obj.segment) { - _state->sfx_song_set_loops(handle, readSelectorValue(_segMan, obj, SELECTOR(loop))); - script_set_priority(_resMan, _segMan, _state, obj, readSelectorValue(_segMan, obj, SELECTOR(pri))); - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -746,85 +435,12 @@ void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri)); if (objPrio != musicSlot->priority) _music->soundSetPriority(musicSlot, objPrio); - -#endif } void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - int signal = 0; - int min = 0; - int sec = 0; - int frame = 0; - int result = SI_LOOP; // small hack - SongHandle handle = FROBNICATE_HANDLE(obj); - - while (result == SI_LOOP) - result = _state->sfx_poll_specific(handle, &signal); - - switch (result) { - case SI_ABSOLUTE_CUE: - debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Absolute Cue: %d", - PRINT_REG(obj), signal); - debugC(2, kDebugLevelSound, "abs-signal %04X", signal); - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal); - break; - - case SI_RELATIVE_CUE: - debugC(2, kDebugLevelSound, "--- [CUE] %04x:%04x Relative Cue: %d", - PRINT_REG(obj), signal); - - /* FIXME to match commented-out semantics - * below, with proper storage of dataInc and - * signal in the iterator code. */ - writeSelectorValue(_segMan, obj, SELECTOR(dataInc), signal); - debugC(2, kDebugLevelSound, "rel-signal %04X", signal); - if (_soundVersion == SCI_VERSION_1_EARLY) - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal); - else - writeSelectorValue(_segMan, obj, SELECTOR(signal), signal + 127); - break; - - case SI_FINISHED: - debugC(2, kDebugLevelSound, "--- [FINISHED] %04x:%04x", PRINT_REG(obj)); - writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - break; - - case SI_LOOP: - break; // Doesn't happen - } - - //switch (signal) { - //case 0x00: - // if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) { - // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc); - // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc+0x7f); - // } else { - // writeSelectorValue(segMan, obj, SELECTOR(signal), signal); - // } - // break; - //case 0xFF: // May be unnecessary - // s->_sound.sfx_song_set_status(handle, SOUND_STATUS_STOPPED); - // break; - //default : - // if (dataInc != readSelectorValue(segMan, obj, SELECTOR(dataInc))) { - // writeSelectorValue(segMan, obj, SELECTOR(dataInc), dataInc); - // writeSelectorValue(segMan, obj, SELECTOR(signal), dataInc + 0x7f); - // } else { - // writeSelectorValue(segMan, obj, SELECTOR(signal), signal); - // } - // break; - //} - - if (_soundVersion == SCI_VERSION_1_EARLY) { - writeSelectorValue(_segMan, obj, SELECTOR(min), min); - writeSelectorValue(_segMan, obj, SELECTOR(sec), sec); - writeSelectorValue(_segMan, obj, SELECTOR(frame), frame); - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -900,15 +516,9 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(sec), musicSlot->ticker % 3600 / 60); writeSelectorValue(_segMan, obj, SELECTOR(frame), musicSlot->ticker); } - -#endif } void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - //SongHandle handle = FROBNICATE_HANDLE(obj); - //_state->sfx_send_midi(handle, value, _midiCmd, _controller, _param); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! @@ -918,20 +528,13 @@ void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { return; } _music->sendMidiCommand(musicSlot, _midiCommand); -#endif } void SoundCommandParser::cmdReverb(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->setReverb(obj.toUint16() & 0xF); -#endif } void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) { -#ifdef USE_OLD_MUSIC_FUNCTIONS - SongHandle handle = FROBNICATE_HANDLE(obj); - _state->sfx_song_set_hold(handle, value); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -940,7 +543,6 @@ void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) { // Set the special hold marker ID where the song should be looped at. musicSlot->hold = value; -#endif } void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) { @@ -949,7 +551,6 @@ void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) { } void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { -#ifndef USE_OLD_MUSIC_FUNCTIONS Common::StackLock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); @@ -964,14 +565,12 @@ void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { (*i)->dataInc = 0; _music->soundStop(*i); } -#endif } void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { if (!obj.segment) return; -#ifndef USE_OLD_MUSIC_FUNCTIONS MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Do not throw a warning if the sound can't be found, as in some games @@ -991,16 +590,12 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { _music->soundSetVolume(musicSlot, value); writeSelectorValue(_segMan, obj, SELECTOR(vol), value); } -#endif } void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - script_set_priority(_resMan, _segMan, _state, obj, value); -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -1024,19 +619,12 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); //DoSOund(0xF,hobj,w) } -#endif } void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { if (!obj.segment) return; -#ifdef USE_OLD_MUSIC_FUNCTIONS - if (!readSelector(_segMan, obj, SELECTOR(nodePtr)).isNull()) { - SongHandle handle = FROBNICATE_HANDLE(obj); - _state->sfx_song_set_loops(handle, value); - } -#else MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // Apparently, it's perfectly normal for a game to call cmdSetSoundLoop @@ -1058,7 +646,6 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { } writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); -#endif } void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) { @@ -1066,8 +653,6 @@ void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) { warning("STUB: cmdSuspendSound"); } -#ifndef USE_OLD_MUSIC_FUNCTIONS - void SoundCommandParser::updateSci0Cues() { bool noOnePlaying = true; MusicEntry *pWaitingForPlay = NULL; @@ -1101,34 +686,23 @@ void SoundCommandParser::updateSci0Cues() { } } -#endif - void SoundCommandParser::clearPlayList() { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->clearPlayList(); -#endif } void SoundCommandParser::printPlayList(Console *con) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->printPlayList(con); -#endif } void SoundCommandParser::printSongInfo(reg_t obj, Console *con) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->printSongInfo(obj, con); -#endif } void SoundCommandParser::stopAllSounds() { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->stopAll(); -#endif } void SoundCommandParser::startNewSound(int number) { -#ifndef USE_OLD_MUSIC_FUNCTIONS Common::StackLock lock(_music->_mutex); // Overwrite the first sound in the playlist @@ -1138,19 +712,14 @@ void SoundCommandParser::startNewSound(int number) { writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); cmdInitSound(soundObj, 0); cmdPlaySound(soundObj, 0); -#endif } void SoundCommandParser::setMasterVolume(int vol) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->soundSetMasterVolume(vol); -#endif } void SoundCommandParser::pauseAll(bool pause) { -#ifndef USE_OLD_MUSIC_FUNCTIONS _music->pauseAll(pause); -#endif } } // End of namespace Sci diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index 09cca23450..d1a81462fe 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -26,8 +26,6 @@ #ifndef SCI_SOUNDCMD_H #define SCI_SOUNDCMD_H -#include "sci/sci.h" // for USE_OLD_MUSIC_FUNCTIONS - #include "common/list.h" #include "sci/engine/state.h" @@ -53,10 +51,6 @@ public: kMaxSciVolume = 15 }; -#ifdef USE_OLD_MUSIC_FUNCTIONS - void updateSfxState(SfxState *newState) { _state = newState; } -#endif - reg_t parseCommand(int argc, reg_t *argv, reg_t acc); // Functions used for game state loading @@ -76,7 +70,6 @@ public: void printPlayList(Console *con); void printSongInfo(reg_t obj, Console *con); -#ifndef USE_OLD_MUSIC_FUNCTIONS /** * Synchronizes the current state of the music list to the rest of the engine, so that * the changes that the sound thread makes to the music are registered with the engine @@ -85,7 +78,6 @@ public: * by the engine scripts themselves, so the engine itself polls for changes to the music */ void updateSci0Cues(); -#endif private: typedef Common::Array SoundCommandContainer; @@ -93,12 +85,7 @@ private: ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; -#ifdef USE_OLD_MUSIC_FUNCTIONS - SfxState *_state; - int _midiCmd, _controller, _param; -#else SciMusic *_music; -#endif AudioPlayer *_audio; SciVersion _soundVersion; int _argc; @@ -131,10 +118,6 @@ private: void cmdSuspendSound(reg_t obj, int16 value); void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying); - -#ifdef USE_OLD_MUSIC_FUNCTIONS - void changeSoundStatus(reg_t obj, int newStatus); -#endif }; } // End of namespace Sci -- cgit v1.2.3 From 4e999c8295adeade2317d9c486b943d3fd290c2c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 14:26:47 +0000 Subject: SCI: support for hires views in gk1 svn-id: r50533 --- engines/sci/graphics/frameout.cpp | 35 +++++++++++++++++++++++++++++++---- engines/sci/graphics/view.cpp | 9 +++++++++ engines/sci/graphics/view.h | 5 +++++ 3 files changed, 45 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 446db82566..48a7742f14 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -128,6 +128,8 @@ void GfxFrameout::kernelFrameout() { // Allocate enough space for all screen items FrameoutEntry *itemData = (FrameoutEntry *)malloc(_screenItems.size() * sizeof(FrameoutEntry)); + const SciGameId gameId = g_sci->getGameId(); + for (Common::List::iterator it = _planes.begin(); it != _planes.end(); it++) { reg_t planeObject = *it; uint16 planePriority = readSelectorValue(_segMan, planeObject, SELECTOR(priority)); @@ -189,6 +191,14 @@ void GfxFrameout::kernelFrameout() { itemEntry->y = readSelectorValue(_segMan, itemObject, SELECTOR(y)); itemEntry->z = readSelectorValue(_segMan, itemObject, SELECTOR(z)); itemEntry->priority = readSelectorValue(_segMan, itemObject, SELECTOR(priority)); + if (gameId == GID_GK1) { + if ((itemEntry->viewId == 11000) && (itemEntry->loopNo == 0) && (itemEntry->celNo == 0) && (itemEntry->priority == 1)) { + itemEntry->priority = 0; // HACK for gk1 hires main menu + } + if ((itemEntry->viewId == 10100) && (itemEntry->priority == 0)) { + itemEntry->priority = 1; // HACK for gk1 hires main menu + } + } itemEntry->signal = readSelectorValue(_segMan, itemObject, SELECTOR(signal)); itemEntry->scaleX = readSelectorValue(_segMan, itemObject, SELECTOR(scaleX)); itemEntry->scaleY = readSelectorValue(_segMan, itemObject, SELECTOR(scaleY)); @@ -228,23 +238,40 @@ void GfxFrameout::kernelFrameout() { if (itemEntry->viewId != 0xFFFF) { GfxView *view = _cache->getView(itemEntry->viewId); + if (view->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(itemEntry->y, itemEntry->x); + if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) view->getCelRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->celRect); else view->getCelScaledRect(itemEntry->loopNo, itemEntry->celNo, itemEntry->x, itemEntry->y, itemEntry->z, itemEntry->scaleX, itemEntry->scaleY, itemEntry->celRect); - if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= _screen->getHeight()) + int16 screenHeight = _screen->getHeight(); + int16 screenWidth = _screen->getWidth(); + if (view->isSci2Hires()) { + screenHeight = _screen->getDisplayHeight(); + screenWidth = _screen->getDisplayWidth(); + } + + if (itemEntry->celRect.top < 0 || itemEntry->celRect.top >= screenHeight) continue; - if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= _screen->getWidth()) + if (itemEntry->celRect.left < 0 || itemEntry->celRect.left >= screenWidth) continue; Common::Rect clipRect; clipRect = itemEntry->celRect; - clipRect.clip(planeRect); + if (view->isSci2Hires()) { + Common::Rect upscaledPlaneRect = planeRect; + _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.top, upscaledPlaneRect.left); + _screen->adjustToUpscaledCoordinates(upscaledPlaneRect.bottom, upscaledPlaneRect.right); + clipRect.clip(upscaledPlaneRect); + } else { + clipRect.clip(planeRect); + } if ((itemEntry->scaleX == 128) && (itemEntry->scaleY == 128)) - view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, false); + view->draw(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, 0, view->isSci2Hires()); else view->drawScaled(itemEntry->celRect, clipRect, clipRect, itemEntry->loopNo, itemEntry->celNo, 255, itemEntry->scaleX, itemEntry->scaleY); } else { diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 244114e866..816dad0cbb 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -81,6 +81,7 @@ void GfxView::initData(GuiResourceId resourceId) { _loopCount = 0; _embeddedPal = false; _EGAmapping = NULL; + _isSci2Hires = false; // If we find an SCI1/SCI1.1 view (not amiga), we switch to that type for // EGA. This could get used to make view patches for EGA games, where the @@ -191,6 +192,7 @@ void GfxView::initData(GuiResourceId resourceId) { assert(headerSize >= 16); _loopCount = _resourceData[2]; assert(_loopCount); + _isSci2Hires = _resourceData[5] == 1 ? true : false; palOffset = READ_SCI11ENDIAN_UINT32(_resourceData + 8); // FIXME: After LoopCount there is another byte and its set for view 50 // within Laura Bow 2 CD, check what it means. @@ -240,6 +242,9 @@ void GfxView::initData(GuiResourceId resourceId) { cel->offsetEGA = 0; cel->offsetRLE = READ_SCI11ENDIAN_UINT32(celData + 24); cel->offsetLiteral = READ_SCI11ENDIAN_UINT32(celData + 28); + // GK1-hires content is actually uncompressed, we need to swap both so that we process it as such + if ((cel->offsetRLE) && (!cel->offsetLiteral)) + SWAP(cel->offsetRLE, cel->offsetLiteral); cel->rawBitmap = 0; if (_loop[loopNo].mirrorFlag) @@ -288,6 +293,10 @@ Palette *GfxView::getPalette() { return _embeddedPal ? &_viewPalette : NULL; } +bool GfxView::isSci2Hires() { + return _isSci2Hires; +} + void GfxView::getCelRect(int16 loopNo, int16 celNo, int16 x, int16 y, int16 z, Common::Rect &outRect) const { const CelInfo *celInfo = getCelInfo(loopNo, celNo); outRect.left = x + celInfo->displaceX - (celInfo->width >> 1); diff --git a/engines/sci/graphics/view.h b/engines/sci/graphics/view.h index 93239e7586..6eb1830b99 100644 --- a/engines/sci/graphics/view.h +++ b/engines/sci/graphics/view.h @@ -73,6 +73,8 @@ public: uint16 getCelCount(int16 loopNo) const; Palette *getPalette(); + bool isSci2Hires(); + private: void initData(GuiResourceId resourceId); void unpackCel(int16 loopNo, int16 celNo, byte *outPtr, uint32 pixelCount); @@ -92,6 +94,9 @@ private: bool _embeddedPal; Palette _viewPalette; + // set for SCI2 views in gk1/windows, means that views are hires and should be handled accordingly + bool _isSci2Hires; + byte *_EGAmapping; }; -- cgit v1.2.3 From 04d8ac41142de7f1a3a732073d1e236c0192f533 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 14:39:03 +0000 Subject: SCI: removing sq1 workaround for kUnLoad for now, maybe it was originally meant for calling kUnLoad with just 1 argument svn-id: r50534 --- engines/sci/engine/kernel.cpp | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index ec3cdc5106..b0c369605e 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -206,12 +206,6 @@ static const char *s_defaultKernelNames[] = { // i* -> optional multiple integers // .* -> any parameters afterwards (or none) -// gameID, scriptNr,lvl, object-name, method-name, call,index,replace -static const SciWorkaroundEntry kUnLoad_workarounds[] = { - { GID_SQ1, 998, 0, "View", "delete", -1, 0, { 1, 0 } }, // exiting ulence flats bar - slotGuyBody::dispose calls view::delete resulting in parameter 1 to be a reference - SCI_WORKAROUNDENTRY_TERMINATOR -}; - // gameID, scriptNr,lvl, object-name, method-name, call,index,replace static const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard @@ -252,7 +246,8 @@ struct SciKernelMapEntry { // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "iRi*", NULL, kUnLoad_workarounds }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "iRi*", NULL, NULL }, + // ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?) { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds }, { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, -- cgit v1.2.3 From bcc010a56e6e58baf1f19f829802e1dbaad83f60 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 15:26:45 +0000 Subject: SCI: remove some duplicate code svn-id: r50535 --- engines/sci/graphics/view.cpp | 8 ++------ 1 file changed, 2 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/view.cpp b/engines/sci/graphics/view.cpp index 816dad0cbb..93df45820c 100644 --- a/engines/sci/graphics/view.cpp +++ b/engines/sci/graphics/view.cpp @@ -265,15 +265,11 @@ GuiResourceId GfxView::getResourceId() const { } int16 GfxView::getWidth(int16 loopNo, int16 celNo) const { - loopNo = CLIP(loopNo, 0, _loopCount - 1); - celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? _loop[loopNo].cel[celNo].width : 0; + return _loopCount ? getCelInfo(loopNo, celNo)->width : 0; } int16 GfxView::getHeight(int16 loopNo, int16 celNo) const { - loopNo = CLIP(loopNo, 0, _loopCount - 1); - celNo = CLIP(celNo, 0, _loop[loopNo].celCount - 1); - return _loopCount ? _loop[loopNo].cel[celNo].height : 0; + return _loopCount ? getCelInfo(loopNo, celNo)->height : 0; } const CelInfo *GfxView::getCelInfo(int16 loopNo, int16 celNo) const { -- cgit v1.2.3 From 1287e6f252296d4c3fef58b080c4ae2fdef40a73 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 30 Jun 2010 15:44:26 +0000 Subject: SCI: adjust brRect and nsRect, if sci2 hires views are used, fixes hotspots in gk1 svn-id: r50536 --- engines/sci/graphics/compare.cpp | 19 ++++++++++++++++++- engines/sci/graphics/cursor.cpp | 17 ++--------------- engines/sci/graphics/screen.cpp | 18 ++++++++++++++++++ engines/sci/graphics/screen.h | 1 + 4 files changed, 39 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/compare.cpp b/engines/sci/graphics/compare.cpp index 7cd55b1139..31c2b210ce 100644 --- a/engines/sci/graphics/compare.cpp +++ b/engines/sci/graphics/compare.cpp @@ -130,10 +130,18 @@ void GfxCompare::kernelSetNowSeen(reg_t objectReference) { if (SELECTOR(z) > -1) z = (int16)readSelectorValue(_segMan, objectReference, SELECTOR(z)); - // now get cel rectangle view = _cache->getView(viewId); + + if (view->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(y, x); + view->getCelRect(loopNo, celNo, x, y, z, celRect); + if (view->isSci2Hires()) { + _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left); + _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); + } + if (lookupSelector(_segMan, objectReference, SELECTOR(nsTop), NULL, NULL) == kSelectorVariable) { writeSelectorValue(_segMan, objectReference, SELECTOR(nsLeft), celRect.left); writeSelectorValue(_segMan, objectReference, SELECTOR(nsRight), celRect.right); @@ -200,7 +208,16 @@ void GfxCompare::kernelBaseSetter(reg_t object) { GfxView *tmpView = _cache->getView(viewId); Common::Rect celRect; + if (tmpView->isSci2Hires()) + _screen->adjustToUpscaledCoordinates(y, x); + tmpView->getCelRect(loopNo, celNo, x, y, z, celRect); + + if (tmpView->isSci2Hires()) { + _screen->adjustBackUpscaledCoordinates(celRect.top, celRect.left); + _screen->adjustBackUpscaledCoordinates(celRect.bottom, celRect.right); + } + celRect.bottom = y + 1; celRect.top = celRect.bottom - yStep; diff --git a/engines/sci/graphics/cursor.cpp b/engines/sci/graphics/cursor.cpp index 23c41c4c87..e1c05c97da 100644 --- a/engines/sci/graphics/cursor.cpp +++ b/engines/sci/graphics/cursor.cpp @@ -276,21 +276,8 @@ void GfxCursor::setPosition(Common::Point pos) { Common::Point GfxCursor::getPosition() { Common::Point mousePos = g_system->getEventManager()->getMousePos(); - switch (_upscaledHires) { - case GFX_SCREEN_UPSCALED_640x400: - mousePos.x /= 2; - mousePos.y /= 2; - break; - case GFX_SCREEN_UPSCALED_640x440: - mousePos.x /= 2; - mousePos.y = (mousePos.y * 5) / 11; - break; - case GFX_SCREEN_UPSCALED_640x480: - mousePos.x /= 2; - mousePos.y = (mousePos.y * 5) / 12; - default: - break; - } + if (_upscaledHires) + _screen->adjustBackUpscaledCoordinates(mousePos.y, mousePos.x); return mousePos; } diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 053372bdac..c446a98768 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -617,6 +617,24 @@ void GfxScreen::adjustToUpscaledCoordinates(int16 &y, int16 &x) { y = _upscaledMapping[y]; } +void GfxScreen::adjustBackUpscaledCoordinates(int16 &y, int16 &x) { + switch (_upscaledHires) { + case GFX_SCREEN_UPSCALED_640x400: + x /= 2; + y /= 2; + break; + case GFX_SCREEN_UPSCALED_640x440: + x /= 2; + y = (y * 5) / 11; + break; + case GFX_SCREEN_UPSCALED_640x480: + x /= 2; + y = (y * 5) / 12; + default: + break; + } +} + int16 GfxScreen::kernelPicNotValid(int16 newPicNotValid) { int16 oldPicNotValid; diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 03dfd3529c..113cf911a6 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -112,6 +112,7 @@ public: void scale2x(const byte *src, byte *dst, int16 srcWidth, int16 srcHeight); void adjustToUpscaledCoordinates(int16 &y, int16 &x); + void adjustBackUpscaledCoordinates(int16 &y, int16 &x); void dither(bool addToFlag); void debugUnditherSetState(bool flag); -- cgit v1.2.3 From b85fd471a6f64f7f291c7b52e6061b99a26714e9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 17:36:52 +0000 Subject: Added support for kAddAfter with 4 parameters (used in Torin's Passage, for example) svn-id: r50537 --- engines/sci/engine/klists.cpp | 5 ++--- 1 file changed, 2 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 4f8087539b..8e9ec6dccd 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -271,9 +271,8 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } - if (argc == 4) // Torin's Passage - // TODO: Find out what the 4th parameter is - warning("kAddAfter with 4 params called, 4th param is %04x:%04x", PRINT_REG(argv[3])); + if (argc == 4) + newnode->key = argv[3]; if (firstnode) { // We're really appending after reg_t oldnext = firstnode->succ; -- cgit v1.2.3 From 3cd5821085817cece98365a28d24aa35a5749689 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 30 Jun 2010 17:47:44 +0000 Subject: SCI: Silenced a warning about a non game breaking script bug in Castle of Dr. Brain, room 360 svn-id: r50538 --- engines/sci/engine/vm.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 48f17d34de..87ff985461 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -605,6 +605,9 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } else if (!strcmp(objectName, "longSong") && selector == 3 && g_sci->getGameId() == GID_QFG1) { // QFG1VGA has a script bug in the longSong object when invoking the // loop selector, which doesn't affect gameplay, thus don't diplay it + } else if (!strcmp(objectName, "PuzPiece") && selector == 77 && g_sci->getGameId() == GID_CASTLEBRAIN) { + // Castle of Dr. Brain has a script bug in the PuzPiece object when invoking + // the value selector, which doesn't affect gameplay, thus don't display it } else { // Unknown script bug, show it. Usually these aren't fatal. reg_t oldReg = *varp.getPointer(s->_segMan); -- cgit v1.2.3 From b0b4f34d276b3451d6d46ac29cab6f5166cea757 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 05:33:51 +0000 Subject: Added a workaround for an uninitialized temp read in KQ6 floppy, when opening the controls window - from bug report #3023602 svn-id: r50541 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 87ff985461..e7e16e5a35 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -351,6 +351,7 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is + { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc) { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller -- cgit v1.2.3 From b45d2cd92b137dc429f12f67b887a193f601afb2 Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Thu, 1 Jul 2010 07:10:40 +0000 Subject: Implement playing RAW/MP3/OGG/FLAC dubbing from ZIP archives. Playing works well, but I am not enabling it in the game player yet, because I have not implemented measuring the time duration of compressed dubbing, which is needed in the (exclusively used) blocking mode. svn-id: r50543 --- engines/draci/sound.cpp | 157 +++++++++++++++++++++++++++++++++++++++++++----- engines/draci/sound.h | 78 ++++++++++++++++++++---- 2 files changed, 209 insertions(+), 26 deletions(-) (limited to 'engines') diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index 65e7e41ac4..e430da7bdc 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -23,11 +23,13 @@ * */ +#include "common/archive.h" #include "common/config-manager.h" #include "common/debug.h" #include "common/file.h" #include "common/str.h" #include "common/stream.h" +#include "common/unzip.h" #include "draci/sound.h" #include "draci/draci.h" @@ -36,14 +38,17 @@ #include "sound/audiostream.h" #include "sound/mixer.h" #include "sound/decoders/raw.h" +#include "sound/decoders/mp3.h" +#include "sound/decoders/vorbis.h" +#include "sound/decoders/flac.h" namespace Draci { -void LegacySoundArchive::openArchive(const Common::String &path) { +void LegacySoundArchive::openArchive(const char *path) { // Close previously opened archive (if any) closeArchive(); - debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path.c_str()); + debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path); _f = new Common::File(); _f->open(path); @@ -83,7 +88,6 @@ void LegacySoundArchive::openArchive(const Common::String &path) { _samples[i]._offset = sampleStarts[i]; _samples[i]._length = sampleStarts[i+1] - sampleStarts[i]; _samples[i]._frequency = 0; // set in getSample() - _samples[i]._data = NULL; } if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength && _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) { @@ -144,25 +148,106 @@ SoundSample *LegacySoundArchive::getSample(int i, uint freq) { } debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d from archive %s... ", - i, _path.c_str()); + i, _path); // Check if file has already been opened and return that if (_samples[i]._data) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(2, kDraciArchiverDebugLevel, "Cached"); } else { + // It would be nice to unify the approach with ZipSoundArchive + // and allocate a MemoryReadStream with buffer stored inside it + // that playSoundBuffer() would just play. Unfortunately, + // streams are not thread-safe and the same sample couldn't + // thus be played more than once at the same time (this holds + // even if we create a SeekableSubReadStream from it as this + // just uses the parent). The only thread-safe solution is to + // share a read-only buffer and allocate separate + // MemoryReadStream's on top of it. + _samples[i]._data = new byte[_samples[i]._length]; + _samples[i]._format = RAW; + // Read in the file (without the file header) _f->seek(_samples[i]._offset); - _samples[i]._data = new byte[_samples[i]._length]; _f->read(_samples[i]._data, _samples[i]._length); - debugC(3, kDraciArchiverDebugLevel, "Cached sample %d from archive %s", - i, _path.c_str()); + debugC(3, kDraciArchiverDebugLevel, "Read sample %d from archive %s", + i, _path); } _samples[i]._frequency = freq ? freq : _defaultFreq; return _samples + i; } +void ZipSoundArchive::openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency) { + closeArchive(); + + _archive = Common::makeZipArchive(path); + _path = path; + _extension = extension; + _format = format; + _defaultFreq = raw_frequency; + + if (_archive) { + Common::ArchiveMemberList files; + _archive->listMembers(files); + _sampleCount = files.size(); + } +} + +void ZipSoundArchive::closeArchive() { + clearCache(); + delete _archive; + _archive = NULL; + _path = _extension = NULL; + _sampleCount = _defaultFreq = 0; + _format = RAW; +} + +void ZipSoundArchive::clearCache() { + // Just deallocate the link-list of (very short) headers for each + // dubbed sentence played in the current location. If the callers have + // not called .close() on any of the items, call them now. + for (Common::List::iterator it = _cache.begin(); it != _cache.end(); ++it) { + it->close(); + } + _cache.clear(); +} + +SoundSample *ZipSoundArchive::getSample(int i, uint freq) { + if (i < 0 || i >= (int) _sampleCount) { + return NULL; + } + debugCN(2, kDraciArchiverDebugLevel, "Accessing sample %d.%s from archive %s (format %d@%d, capacity %d): ", + i, _extension, _path, static_cast (_format), _defaultFreq, _sampleCount); + if (freq != 0 && (_format != RAW && _format != RAW80)) { + error("Cannot resample a sound in compressed format"); + return NULL; + } + + // We cannot really cache anything, because createReadStreamForMember() + // returns the data as a ReadStream, which is not thread-safe. We thus + // read it again each time even if it has possibly been already cached + // a while ago. This is not such a problem for dubbing as for regular + // sound samples. + SoundSample sample; + sample._frequency = freq ? freq : _defaultFreq; + sample._format = _format; + // Read in the file (without the file header) + char file_name[20]; + sprintf(file_name, "%d.%s", i+1, _extension); + sample._stream = _archive->createReadStreamForMember(file_name); + if (!sample._stream) { + debugC(2, kDraciArchiverDebugLevel, "Doesn't exist"); + return NULL; + } else { + debugC(2, kDraciArchiverDebugLevel, "Read"); + _cache.push_back(sample); + // Return a pointer that we own and which we will deallocate + // including its contents. + return &_cache.back(); + } +} + Sound::Sound(Audio::Mixer *mixer) : _mixer(mixer), _muteSound(false), _muteVoice(false), _showSubtitles(true), _talkSpeed(kStandardSpeed) { @@ -194,17 +279,59 @@ SndHandle *Sound::getHandle() { void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, sndHandleType handleType, bool loop) { + if (!buffer._stream && !buffer._data) { + warning("Empty stream"); + return; + } + // Create a new SeekableReadStream which will be automatically disposed + // after the sample stops playing. Do not dispose the original + // data/stream though. + // Beware that if the sample comes from an archive (i.e., is stored in + // buffer._stream), then you must NOT play it more than once at the + // same time, because streams are not thread-safe. Playing it + // repeatedly is OK. Currently this is ensured by that archives are + // only used for dubbing, which is only played from one place in + // script.cpp, which blocks until the dubbed sentence has finished + // playing. + Common::SeekableReadStream* stream; + if (buffer._stream) { + stream = new Common::SeekableSubReadStream(buffer._stream, 0, buffer._stream->size(), DisposeAfterUse::NO); + } else { + stream = new Common::MemoryReadStream(buffer._data, buffer._length, DisposeAfterUse::NO); + } - byte flags = Audio::FLAG_UNSIGNED; + Audio::SeekableAudioStream *reader = NULL; + switch (buffer._format) { + case RAW80: + stream->skip(80); // and fall-thru + case RAW: + reader = Audio::makeRawStream(stream, buffer._frequency, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); + break; +#ifdef USE_MAD + case MP3: + reader = Audio::makeMP3Stream(stream, DisposeAfterUse::YES); + break; +#endif +#ifdef USE_VORBIS + case OGG: + reader = Audio::makeVorbisStream(stream, DisposeAfterUse::YES); + break; +#endif +#ifdef USE_FLAC + case FLAC: + reader = Audio::makeFLACStream(stream, DisposeAfterUse::YES); + break; +#endif + default: + error("Unsupported compression format %d", static_cast (buffer._format)); + delete stream; + return; + } const Audio::Mixer::SoundType soundType = (handleType == kVoiceHandle) ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType; - - // Don't use DisposeAfterUse::YES, because our caching system deletes samples by itself. - Audio::AudioStream *stream = Audio::makeLoopingAudioStream( - Audio::makeRawStream(buffer._data, buffer._length, buffer._frequency, flags, DisposeAfterUse::NO), - loop ? 0 : 1); - _mixer->playStream(soundType, handle, stream, -1, volume); + Audio::AudioStream *audio_stream = Audio::makeLoopingAudioStream(reader, loop ? 0 : 1); + _mixer->playStream(soundType, handle, audio_stream, -1, volume); } void Sound::playSound(const SoundSample *buffer, int volume, bool loop) { diff --git a/engines/draci/sound.h b/engines/draci/sound.h index e4cf7efdec..b1a91bb55b 100644 --- a/engines/draci/sound.h +++ b/engines/draci/sound.h @@ -28,22 +28,39 @@ #include "common/str.h" #include "common/file.h" +#include "common/list.h" #include "sound/mixer.h" +namespace Common { +class Archive; +class SeekableReadStream; +} + namespace Draci { +enum SoundFormat { RAW, RAW80, MP3, OGG, FLAC }; // RAW80 means skip the first 80 bytes + /** * Represents individual files inside the archive. */ struct SoundSample { - uint _offset; + uint _offset; // For internal use of LegacySoundArchive uint _length; - uint _frequency; - byte* _data; + uint _frequency; // Only when _format == RAW or RAW80 + SoundFormat _format; + + byte *_data; // At most one of these two pointer can be non-NULL + Common::SeekableReadStream* _stream; + + SoundSample() : _offset(0), _length(0), _frequency(0), _format(RAW), _data(NULL), _stream(NULL) { } + // The standard copy constructor is good enough, since we only stored numbers and pointers. + // Don't call close() automaticall in the destructor, otherwise copying causes SIGSEGV. void close() { delete[] _data; + delete _stream; _data = NULL; + _stream = NULL; } }; @@ -75,27 +92,28 @@ public: /** * Caches a given sample into memory and returns a pointer into it. We - * own the pointer. If freq is nonzero, then the sample is played at a - * different frequency (only used for uncompressed samples). + * own the returned pointer, but the user may call .close() on it, + * which deallocates the memory of the actual sample data. If freq is + * nonzero, then the sample is played at a different frequency (only + * works for uncompressed samples). */ virtual SoundSample *getSample(int i, uint freq) = 0; }; /** * Reads CD.SAM (with dubbing) and CD2.SAM (with sound samples) from the - * original game. + * original game. Caches all read samples in a thread-safe manner. */ class LegacySoundArchive : public SoundArchive { public: - LegacySoundArchive(const Common::String &path, uint defaultFreq) : - _path(), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) { + LegacySoundArchive(const char *path, uint defaultFreq) : + _path(NULL), _samples(NULL), _sampleCount(0), _defaultFreq(defaultFreq), _opened(false), _f(NULL) { openArchive(path); } - virtual ~LegacySoundArchive() { closeArchive(); } + void openArchive(const char *path); void closeArchive(); - void openArchive(const Common::String &path); virtual uint size() const { return _sampleCount; } virtual bool isOpen() const { return _opened; } @@ -104,7 +122,7 @@ public: virtual SoundSample *getSample(int i, uint freq); private: - Common::String _path; ///< Path to file + const char *_path; ///< Path to file SoundSample *_samples; ///< Internal array of files uint _sampleCount; ///< Number of files in archive uint _defaultFreq; ///< The default sampling frequency of the archived samples @@ -112,6 +130,44 @@ private: Common::File *_f; ///< Opened file }; +/** + * Reads ZIP archives with uncompressed files containing lossy-compressed + * samples in arbitrary format. Doesn't do any real caching and is + * thread-safe. + */ +class ZipSoundArchive : public SoundArchive { +public: + ZipSoundArchive() : _archive(NULL), _path(NULL), _extension(NULL), _format(RAW), _sampleCount(0), _defaultFreq(0), _cache() { } + virtual ~ZipSoundArchive() { closeArchive(); } + + void openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency = 0); + void closeArchive(); + + virtual uint size() const { return _sampleCount; } + virtual bool isOpen() const { return _archive != NULL; } + + virtual void clearCache(); + virtual SoundSample *getSample(int i, uint freq); + +private: + Common::Archive *_archive; + const char *_path; + const char *_extension; + SoundFormat _format; + uint _sampleCount; + uint _defaultFreq; + + // Since we typically play at most 1 dubbing at a time, we could get + // away with having just 1 record allocated and reusing it each time. + // However, that would be thread-unsafe if two samples were played. + // Although the player does not do that, it is nicer to allow for it in + // principle. For each dubbed sentence, we allocate a new record in + // the following link-list, which is cleared during each location + // change. The dubbed samples themselves are manually deallocated + // after they end. + Common::List _cache; +}; + #define SOUND_HANDLES 10 enum sndHandleType { -- cgit v1.2.3 From 6c6d8b3fb39afe4a5866348ca2d34a7b13b566bb Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Thu, 1 Jul 2010 12:01:17 +0000 Subject: Introduced a hash for storing all the miscellaneous data values, and used it to more properly implement display of all the wakeup text in the first room svn-id: r50544 --- engines/m4/animation.cpp | 4 ++++ engines/m4/animation.h | 1 + engines/m4/globals.h | 4 ++++ engines/m4/mads_logic.cpp | 54 ++++++++++++++++++++++++++++++++++++++++------- engines/m4/mads_logic.h | 2 ++ engines/m4/mads_scene.h | 1 + engines/m4/mads_views.h | 1 + 7 files changed, 59 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/m4/animation.cpp b/engines/m4/animation.cpp index f9dd8287ae..0ead57aac9 100644 --- a/engines/m4/animation.cpp +++ b/engines/m4/animation.cpp @@ -482,6 +482,10 @@ void MadsAnimation::setCurrentFrame(int frameNumber) { _nextScrollTimer = _nextFrameTimer = _madsVm->_currentTimer; } +int MadsAnimation::getCurrentFrame() { + return _currentFrame; +} + void MadsAnimation::load1(int frameNumber) { if (_skipLoad) return; diff --git a/engines/m4/animation.h b/engines/m4/animation.h index 21fa411426..583d829066 100644 --- a/engines/m4/animation.h +++ b/engines/m4/animation.h @@ -119,6 +119,7 @@ public: virtual void load(const Common::String &filename, int abortTimers); virtual void update(); virtual void setCurrentFrame(int frameNumber); + virtual int getCurrentFrame(); bool freeFlag() const { return _freeFlag; } bool getAnimMode() const { return _animMode; } diff --git a/engines/m4/globals.h b/engines/m4/globals.h index 3a986ee294..0217a96777 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -28,6 +28,7 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/hashmap.h" #include "common/rect.h" #include "common/file.h" #include "common/list.h" @@ -223,6 +224,8 @@ struct MadsConfigData { int screenFades; }; +typedef Common::HashMap IntStorage; + class MadsGlobals : public Globals { private: struct MessageItem { @@ -250,6 +253,7 @@ public: int sceneNumber; int previousScene; uint16 actionNouns[3]; + IntStorage _dataMap; void loadMadsVocab(); uint32 getVocabSize() { return _madsVocab.size(); } diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 9cb053a876..72c5fde40b 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -69,6 +69,10 @@ void MadsSceneLogic::getAnimName() { strcpy(_madsVm->scene()->_aaName, newName); } +IntStorage &MadsSceneLogic::dataMap() { + return _madsVm->globals()->_dataMap; +} + /*--------------------------------------------------------------------------*/ uint16 MadsSceneLogic::loadSpriteSet(uint16 suffixNum, uint16 sepChar) { @@ -239,9 +243,13 @@ void MadsSceneLogic::enterScene() { _madsVm->scene()->getSceneResources().playerPos = Common::Point(68, 140); _madsVm->scene()->getSceneResources().playerDir = 4; - // TODO: Flags setting + + dataMap()[0x56FC] = 0; + dataMap()[0x5482] = 0; + dataMap()[0x5484] = 30; } + _madsVm->globals()->_dataMap[0x5486] = 0; lowRoomsEntrySound(); } @@ -250,14 +258,44 @@ void MadsSceneLogic::doAction() { } void MadsSceneLogic::sceneStep() { - // FIXME: Temporary code to display a message on-screen - static bool tempBool = false; - if (!tempBool) { - tempBool = true; + // Wake up message sequence + Animation *anim = _madsVm->scene()->activeAnimation(); + if (anim) { + if ((anim->getCurrentFrame() == 6) && (dataMap()[0x5482] == 0)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(49)); + dataMap()[0x5484] += 14; + } - _madsVm->scene()->_kernelMessages.add(Common::Point(63, 100), 0x1110, 0, 0, 240, - _madsVm->globals()->getQuote(49)); - } + if ((anim->getCurrentFrame() == 7) && (dataMap()[0x5482] == 1)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(54)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 10) && (dataMap()[0x5482] == 2)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(55)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 17) && (dataMap()[0x5482] == 3)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(56)); + dataMap()[0x5484] += 14; + } + + if ((anim->getCurrentFrame() == 20) && (dataMap()[0x5482] == 4)) { + dataMap()[0x5482]++; + _madsVm->scene()->_kernelMessages.add(Common::Point(63, dataMap()[0x5484]), + 0x1110, 0, 0, 240, _madsVm->globals()->getQuote(50)); + dataMap()[0x5484] += 14; + } + } } } diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h index 8c3f41d08b..299464f62b 100644 --- a/engines/m4/mads_logic.h +++ b/engines/m4/mads_logic.h @@ -50,6 +50,8 @@ private: const char *formAnimName(char sepChar, int16 suffixNum); void getSceneSpriteSet(); void getAnimName(); + + IntStorage &dataMap(); public: void selectScene(int sceneNum); diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index ef5cd312d7..c5fe6f01cd 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -128,6 +128,7 @@ public: void loadPlayerSprites(const char *prefix); void showMADSV2TextBox(char *text, int x, int y, char *faceName); void loadAnimation(const Common::String &animName, int v0); + Animation *activeAnimation() const { return _activeAnimation; } MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; } MadsSceneResources &getSceneResources() { return _sceneResources; } diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 2fbe6a6dc7..e3344bc8a4 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -376,6 +376,7 @@ public: virtual void load(const Common::String &filename, int v0) = 0; virtual void update() = 0; virtual void setCurrentFrame(int frameNumber) = 0; + virtual int getCurrentFrame() = 0; }; -- cgit v1.2.3 From e309f05162b3b49b3236ebd8faaed124d9c5862a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:04:04 +0000 Subject: SCI: Simplify SegManager::findObjectByName svn-id: r50548 --- engines/sci/engine/seg_manager.cpp | 94 +++++++++++++++----------------------- 1 file changed, 37 insertions(+), 57 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index ea1fc389cd..69ab9fbe22 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -263,78 +263,58 @@ const char *SegManager::getObjectName(reg_t pos) { } reg_t SegManager::findObjectByName(const Common::String &name, int index) { - reg_t retVal = NULL_REG; + Common::Array result; + uint i; // Now all values are available; iterate over all objects. - int timesFound = 0; - for (uint i = 0; i < _heap.size(); i++) { - SegmentObj *mobj = _heap[i]; - int idx = 0; - int max_index = 0; - ObjMap::iterator it; - Script *scr = 0; - CloneTable *ct = 0; - - if (mobj) { - if (mobj->getType() == SEG_TYPE_SCRIPT) { - scr = (Script *)mobj; - max_index = scr->_objects.size(); - it = scr->_objects.begin(); - } else if (mobj->getType() == SEG_TYPE_CLONES) { - ct = (CloneTable *)mobj; - max_index = ct->_table.size(); - } - } + for (i = 0; i < _heap.size(); i++) { + const SegmentObj *mobj = _heap[i]; - // It's a script or a clone table, scan all objects in it - for (; idx < max_index; ++idx) { - const Object *obj = NULL; - reg_t objpos; - objpos.offset = 0; - objpos.segment = i; - - if (mobj->getType() == SEG_TYPE_SCRIPT) { - obj = &(it->_value); - objpos.offset = obj->getPos().offset; - ++it; - } else if (mobj->getType() == SEG_TYPE_CLONES) { + if (!mobj) + continue; + + reg_t objpos = make_reg(i, 0); + + if (mobj->getType() == SEG_TYPE_SCRIPT) { + // It's a script, scan all objects in it + const Script *scr = (const Script *)mobj; + for (ObjMap::const_iterator it = scr->_objects.begin(); it != scr->_objects.end(); ++it) { + objpos.offset = it->_value.getPos().offset; + if (name == getObjectName(objpos)) + result.push_back(objpos); + } + } else if (mobj->getType() == SEG_TYPE_CLONES) { + // It's clone table, scan all objects in it + const CloneTable *ct = (const CloneTable *)mobj; + for (uint idx = 0; idx < ct->_table.size(); ++idx) { if (!ct->isValidEntry(idx)) continue; - obj = &(ct->_table[idx]); - objpos.offset = idx; - } - const char *objname = getObjectName(objpos); - if (name == objname) { - // Found a match! - if ((index < 0) && (timesFound > 0)) { - if (timesFound == 1) { - // First time we realized the ambiguity - printf("Ambiguous:\n"); - printf(" %3x: [%04x:%04x] %s\n", 0, PRINT_REG(retVal), name.c_str()); - } - printf(" %3x: [%04x:%04x] %s\n", timesFound, PRINT_REG(objpos), name.c_str()); - } - if (index < 0 || timesFound == index) - retVal = objpos; - ++timesFound; + objpos.offset = idx; + if (name == getObjectName(objpos)) + result.push_back(objpos); } } - } - if (!timesFound) + if (result.empty()) return NULL_REG; - if (timesFound > 1 && index < 0) { - printf("Ambiguous: Aborting.\n"); - return NULL_REG; // Ambiguous + if (result.size() > 1) { + printf("Ambiguous:\n"); + for (i = 0; i < result.size(); i++) + printf(" %3x: [%04x:%04x] %s\n", i, PRINT_REG(result[i]), name.c_str()); + if (index < 0) { + printf("Ambiguous: Aborting.\n"); + return NULL_REG; // Ambiguous + } } - if (timesFound <= index) + if (index < 0) + return result[0]; + else if (result.size() <= (uint)index) return NULL_REG; // Not found - - return retVal; + return result[index]; } // validate the seg -- cgit v1.2.3 From 3f429d64a2ef826782bf9af8971ba397b0e2743c Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:04:29 +0000 Subject: SCI: Rename some variables to match our naming conventions svn-id: r50549 --- engines/sci/engine/kernel32.cpp | 10 +++--- engines/sci/engine/klists.cpp | 12 +++---- engines/sci/engine/savegame.cpp | 6 ++-- engines/sci/engine/seg_manager.cpp | 74 +++++++++++++++++++------------------- engines/sci/engine/seg_manager.h | 20 +++++------ 5 files changed, 61 insertions(+), 61 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 1773046308..5975c7b3bc 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -609,13 +609,13 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { if (argv[1].segment == s->_segMan->getSysStringsSegment()) { // Resize if necessary const uint16 sysStringId = argv[1].toUint16(); - if ((uint32)s->_segMan->sysStrings->_strings[sysStringId]._maxSize < index1 + count) { - free(s->_segMan->sysStrings->_strings[sysStringId]._value); - s->_segMan->sysStrings->_strings[sysStringId]._maxSize = index1 + count; - s->_segMan->sysStrings->_strings[sysStringId]._value = (char *)calloc(index1 + count, sizeof(char)); + if ((uint32)s->_segMan->_sysStrings->_strings[sysStringId]._maxSize < index1 + count) { + free(s->_segMan->_sysStrings->_strings[sysStringId]._value); + s->_segMan->_sysStrings->_strings[sysStringId]._maxSize = index1 + count; + s->_segMan->_sysStrings->_strings[sysStringId]._value = (char *)calloc(index1 + count, sizeof(char)); } - strncpy(s->_segMan->sysStrings->_strings[sysStringId]._value + index1, string2 + index2, count); + strncpy(s->_segMan->_sysStrings->_strings[sysStringId]._value + index1, string2 + index2, count); } else { SciString *string1 = s->_segMan->lookupString(argv[1]); diff --git a/engines/sci/engine/klists.cpp b/engines/sci/engine/klists.cpp index 8e9ec6dccd..0701883a9b 100644 --- a/engines/sci/engine/klists.cpp +++ b/engines/sci/engine/klists.cpp @@ -179,7 +179,7 @@ reg_t kEmptyList(EngineState *s, int argc, reg_t *argv) { return make_reg(0, ((list) ? list->first.isNull() : 0)); } -static void _k_add_to_front(EngineState *s, reg_t listRef, reg_t nodeRef) { +static void addToFront(EngineState *s, reg_t listRef, reg_t nodeRef) { List *list = s->_segMan->lookupList(listRef); Node *newNode = s->_segMan->lookupNode(nodeRef); @@ -202,7 +202,7 @@ static void _k_add_to_front(EngineState *s, reg_t listRef, reg_t nodeRef) { list->first = nodeRef; } -static void _k_add_to_end(EngineState *s, reg_t listRef, reg_t nodeRef) { +static void addToEnd(EngineState *s, reg_t listRef, reg_t nodeRef) { List *list = s->_segMan->lookupList(listRef); Node *newNode = s->_segMan->lookupNode(nodeRef); @@ -250,7 +250,7 @@ reg_t kNodeValue(EngineState *s, int argc, reg_t *argv) { } reg_t kAddToFront(EngineState *s, int argc, reg_t *argv) { - _k_add_to_front(s, argv[0], argv[1]); + addToFront(s, argv[0], argv[1]); return s->r_acc; } @@ -288,14 +288,14 @@ reg_t kAddAfter(EngineState *s, int argc, reg_t *argv) { s->_segMan->lookupNode(oldnext)->pred = argv[2]; } else { // !firstnode - _k_add_to_front(s, argv[0], argv[2]); // Set as initial list node + addToFront(s, argv[0], argv[2]); // Set as initial list node } return s->r_acc; } reg_t kAddToEnd(EngineState *s, int argc, reg_t *argv) { - _k_add_to_end(s, argv[0], argv[1]); + addToEnd(s, argv[0], argv[1]); return s->r_acc; } @@ -417,7 +417,7 @@ reg_t kSort(EngineState *s, int argc, reg_t *argv) { for (i = 0;i < input_size;i++) { reg_t lNode = s->_segMan->newNode(temp_array[i].value, temp_array[i].key); - _k_add_to_end(s, output_data, lNode); + addToEnd(s, output_data, lNode); } free(temp_array); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 7a6496fe63..6a1cbe4740 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -245,9 +245,9 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { } } - s.syncAsSint32LE(Clones_seg_id); - s.syncAsSint32LE(Lists_seg_id); - s.syncAsSint32LE(Nodes_seg_id); + s.syncAsSint32LE(_clonesSegId); + s.syncAsSint32LE(_listsSegId); + s.syncAsSint32LE(_nodesSegId); } diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 69ab9fbe22..517e723d40 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -40,14 +40,14 @@ enum { SegManager::SegManager(ResourceManager *resMan) { _heap.push_back(0); - Clones_seg_id = 0; - Lists_seg_id = 0; - Nodes_seg_id = 0; - Hunks_seg_id = 0; + _clonesSegId = 0; + _listsSegId = 0; + _nodesSegId = 0; + _hunksSegId = 0; #ifdef ENABLE_SCI32 - Arrays_seg_id = 0; - String_seg_id = 0; + _arraysSegId = 0; + _stringSegId = 0; #endif _resMan = resMan; @@ -71,10 +71,10 @@ void SegManager::resetSegMan() { // And reinitialize _heap.push_back(0); - Clones_seg_id = 0; - Lists_seg_id = 0; - Nodes_seg_id = 0; - Hunks_seg_id = 0; + _clonesSegId = 0; + _listsSegId = 0; + _nodesSegId = 0; + _hunksSegId = 0; // Reinitialize class table _classTable.clear(); @@ -82,10 +82,10 @@ void SegManager::resetSegMan() { } void SegManager::initSysStrings() { - sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &sysStringsSegment); + _sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &_sysStringsSegId); // Allocate static buffer for savegame and CWD directories - SystemString *strSaveDir = &sysStrings->_strings[SYS_STRING_SAVEDIR]; + SystemString *strSaveDir = &_sysStrings->_strings[SYS_STRING_SAVEDIR]; strSaveDir->_name = "savedir"; strSaveDir->_maxSize = MAX_SAVE_DIR_SIZE; strSaveDir->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char)); @@ -94,7 +94,7 @@ void SegManager::initSysStrings() { ::strcpy(strSaveDir->_value, ""); // Allocate static buffer for the parser base - SystemString *strParserBase = &sysStrings->_strings[SYS_STRING_PARSER_BASE]; + SystemString *strParserBase = &_sysStrings->_strings[SYS_STRING_PARSER_BASE]; strParserBase->_name = "parser-base"; strParserBase->_maxSize = MAX_PARSER_BASE; strParserBase->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char)); @@ -412,13 +412,13 @@ reg_t SegManager::allocateHunkEntry(const char *hunk_type, int size) { HunkTable *table; int offset; - if (!Hunks_seg_id) - allocSegment(new HunkTable(), &(Hunks_seg_id)); - table = (HunkTable *)_heap[Hunks_seg_id]; + if (!_hunksSegId) + allocSegment(new HunkTable(), &(_hunksSegId)); + table = (HunkTable *)_heap[_hunksSegId]; offset = table->allocEntry(); - reg_t addr = make_reg(Hunks_seg_id, offset); + reg_t addr = make_reg(_hunksSegId, offset); Hunk *h = &(table->_table[offset]); if (!h) @@ -446,14 +446,14 @@ Clone *SegManager::allocateClone(reg_t *addr) { CloneTable *table; int offset; - if (!Clones_seg_id) - table = (CloneTable *)allocSegment(new CloneTable(), &(Clones_seg_id)); + if (!_clonesSegId) + table = (CloneTable *)allocSegment(new CloneTable(), &(_clonesSegId)); else - table = (CloneTable *)_heap[Clones_seg_id]; + table = (CloneTable *)_heap[_clonesSegId]; offset = table->allocEntry(); - *addr = make_reg(Clones_seg_id, offset); + *addr = make_reg(_clonesSegId, offset); return &(table->_table[offset]); } @@ -461,13 +461,13 @@ List *SegManager::allocateList(reg_t *addr) { ListTable *table; int offset; - if (!Lists_seg_id) - allocSegment(new ListTable(), &(Lists_seg_id)); - table = (ListTable *)_heap[Lists_seg_id]; + if (!_listsSegId) + allocSegment(new ListTable(), &(_listsSegId)); + table = (ListTable *)_heap[_listsSegId]; offset = table->allocEntry(); - *addr = make_reg(Lists_seg_id, offset); + *addr = make_reg(_listsSegId, offset); return &(table->_table[offset]); } @@ -475,13 +475,13 @@ Node *SegManager::allocateNode(reg_t *addr) { NodeTable *table; int offset; - if (!Nodes_seg_id) - allocSegment(new NodeTable(), &(Nodes_seg_id)); - table = (NodeTable *)_heap[Nodes_seg_id]; + if (!_nodesSegId) + allocSegment(new NodeTable(), &(_nodesSegId)); + table = (NodeTable *)_heap[_nodesSegId]; offset = table->allocEntry(); - *addr = make_reg(Nodes_seg_id, offset); + *addr = make_reg(_nodesSegId, offset); return &(table->_table[offset]); } @@ -851,14 +851,14 @@ SciArray *SegManager::allocateArray(reg_t *addr) { ArrayTable *table; int offset; - if (!Arrays_seg_id) { - table = (ArrayTable *)allocSegment(new ArrayTable(), &(Arrays_seg_id)); + if (!_arraysSegId) { + table = (ArrayTable *)allocSegment(new ArrayTable(), &(_arraysSegId)); } else - table = (ArrayTable *)_heap[Arrays_seg_id]; + table = (ArrayTable *)_heap[_arraysSegId]; offset = table->allocEntry(); - *addr = make_reg(Arrays_seg_id, offset); + *addr = make_reg(_arraysSegId, offset); return &(table->_table[offset]); } @@ -891,14 +891,14 @@ SciString *SegManager::allocateString(reg_t *addr) { StringTable *table; int offset; - if (!String_seg_id) { - table = (StringTable *)allocSegment(new StringTable(), &(String_seg_id)); + if (!_stringSegId) { + table = (StringTable *)allocSegment(new StringTable(), &(_stringSegId)); } else - table = (StringTable *)_heap[String_seg_id]; + table = (StringTable *)_heap[_stringSegId]; offset = table->allocEntry(); - *addr = make_reg(String_seg_id, offset); + *addr = make_reg(_stringSegId, offset); return &(table->_table[offset]); } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 0ef904618b..50a0464ee2 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -446,7 +446,7 @@ public: /** * Obtains the system strings segment ID */ - SegmentId getSysStringsSegment() { return sysStringsSegment; } + SegmentId getSysStringsSegment() { return _sysStringsSegId; } public: // TODO: make private Common::Array _heap; @@ -460,7 +460,7 @@ public: // TODO: make private SciString *allocateString(reg_t *addr); SciString *lookupString(reg_t addr); void freeString(reg_t addr); - SegmentId getStringSegmentId() { return String_seg_id; } + SegmentId getStringSegmentId() { return _stringSegId; } #endif private: @@ -469,21 +469,21 @@ private: ResourceManager *_resMan; - SegmentId Clones_seg_id; ///< ID of the (a) clones segment - SegmentId Lists_seg_id; ///< ID of the (a) list segment - SegmentId Nodes_seg_id; ///< ID of the (a) node segment - SegmentId Hunks_seg_id; ///< ID of the (a) hunk segment + SegmentId _clonesSegId; ///< ID of the (a) clones segment + SegmentId _listsSegId; ///< ID of the (a) list segment + SegmentId _nodesSegId; ///< ID of the (a) node segment + SegmentId _hunksSegId; ///< ID of the (a) hunk segment /* System strings */ - SegmentId sysStringsSegment; + SegmentId _sysStringsSegId; public: // TODO: make private. Only kString() needs direct access - SystemStrings *sysStrings; + SystemStrings *_sysStrings; private: #ifdef ENABLE_SCI32 - SegmentId Arrays_seg_id; - SegmentId String_seg_id; + SegmentId _arraysSegId; + SegmentId _stringSegId; #endif private: -- cgit v1.2.3 From 36799dc83f59674de8956ea2ec29029783633f45 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:04:48 +0000 Subject: SCI: Add SegManager::getSystemString() method svn-id: r50550 --- engines/sci/engine/kernel32.cpp | 12 +++++++----- engines/sci/engine/seg_manager.cpp | 4 ++-- engines/sci/engine/seg_manager.h | 15 ++++++++++++--- 3 files changed, 21 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 5975c7b3bc..25a822f77d 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -609,13 +609,15 @@ reg_t kString(EngineState *s, int argc, reg_t *argv) { if (argv[1].segment == s->_segMan->getSysStringsSegment()) { // Resize if necessary const uint16 sysStringId = argv[1].toUint16(); - if ((uint32)s->_segMan->_sysStrings->_strings[sysStringId]._maxSize < index1 + count) { - free(s->_segMan->_sysStrings->_strings[sysStringId]._value); - s->_segMan->_sysStrings->_strings[sysStringId]._maxSize = index1 + count; - s->_segMan->_sysStrings->_strings[sysStringId]._value = (char *)calloc(index1 + count, sizeof(char)); + SystemString *sysString = s->_segMan->getSystemString(sysStringId); + assert(sysString); + if ((uint32)sysString->_maxSize < index1 + count) { + free(sysString->_value); + sysString->_maxSize = index1 + count; + sysString->_value = (char *)calloc(index1 + count, sizeof(char)); } - strncpy(s->_segMan->_sysStrings->_strings[sysStringId]._value + index1, string2 + index2, count); + strncpy(sysString->_value + index1, string2 + index2, count); } else { SciString *string1 = s->_segMan->lookupString(argv[1]); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 517e723d40..a5cfc5013b 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -85,7 +85,7 @@ void SegManager::initSysStrings() { _sysStrings = (SystemStrings *)allocSegment(new SystemStrings(), &_sysStringsSegId); // Allocate static buffer for savegame and CWD directories - SystemString *strSaveDir = &_sysStrings->_strings[SYS_STRING_SAVEDIR]; + SystemString *strSaveDir = getSystemString(SYS_STRING_SAVEDIR); strSaveDir->_name = "savedir"; strSaveDir->_maxSize = MAX_SAVE_DIR_SIZE; strSaveDir->_value = (char *)calloc(MAX_SAVE_DIR_SIZE, sizeof(char)); @@ -94,7 +94,7 @@ void SegManager::initSysStrings() { ::strcpy(strSaveDir->_value, ""); // Allocate static buffer for the parser base - SystemString *strParserBase = &_sysStrings->_strings[SYS_STRING_PARSER_BASE]; + SystemString *strParserBase = getSystemString(SYS_STRING_PARSER_BASE); strParserBase->_name = "parser-base"; strParserBase->_maxSize = MAX_PARSER_BASE; strParserBase->_value = (char *)calloc(MAX_PARSER_BASE, sizeof(char)); diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 50a0464ee2..6fb1114555 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -448,6 +448,18 @@ public: */ SegmentId getSysStringsSegment() { return _sysStringsSegId; } + /** + * Get a pointer to the system string with the specified index, + * or NULL if that index is invalid. + * + * This method is currently only used by kString(). + */ + SystemString *getSystemString(uint idx) const { + if (idx >= SYS_STRINGS_MAX) + return NULL; + return &_sysStrings->_strings[idx]; + } + public: // TODO: make private Common::Array _heap; // Only accessible from saveLoadWithSerializer() @@ -476,11 +488,8 @@ private: /* System strings */ SegmentId _sysStringsSegId; -public: // TODO: make private. Only kString() needs direct access SystemStrings *_sysStrings; -private: - #ifdef ENABLE_SCI32 SegmentId _arraysSegId; SegmentId _stringSegId; -- cgit v1.2.3 From c822cd67cbebf22999a6b4d95d965ea5873e1b9a Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:05:10 +0000 Subject: SCI: Make SegManager::_classTable private. This require a small tweak to the save/load code: I moved the syncing logic for _classtable from EngineState::saveLoadWithSerializer to SegManager::saveLoadWithSerializer, which in theory should have no effect (luckily, _classtable was being synced right after the segment manager). svn-id: r50551 --- engines/sci/engine/savegame.cpp | 4 ++-- engines/sci/engine/seg_manager.h | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 6a1cbe4740..bf29dbb046 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -248,6 +248,8 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_clonesSegId); s.syncAsSint32LE(_listsSegId); s.syncAsSint32LE(_nodesSegId); + + syncArray(s, _classTable); } @@ -343,8 +345,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { _segMan->saveLoadWithSerializer(s); - syncArray(s, _segMan->_classTable); - g_sci->_soundCmd->syncPlayList(s); } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 6fb1114555..5bb6f7e524 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -462,8 +462,6 @@ public: public: // TODO: make private Common::Array _heap; - // Only accessible from saveLoadWithSerializer() - Common::Array _classTable; /**< Table of all classes */ #ifdef ENABLE_SCI32 SciArray *allocateArray(reg_t *addr); @@ -476,6 +474,8 @@ public: // TODO: make private #endif private: + // Only accessible from saveLoadWithSerializer() + Common::Array _classTable; /**< Table of all classes */ /** Map script ids to segment ids. */ Common::HashMap _scriptSegMap; -- cgit v1.2.3 From b8904a48ed81d04a2cbe84f78d80aaa75344d16e Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:05:29 +0000 Subject: SCI: Make SegManager::_heap private svn-id: r50552 --- engines/sci/engine/gc.cpp | 24 +++++++++++++----------- engines/sci/engine/seg_manager.cpp | 2 +- engines/sci/engine/seg_manager.h | 11 +++++------ 3 files changed, 19 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 3dd7acfa1c..75456bcef0 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -51,12 +51,12 @@ struct WorklistManager { } }; -static reg_t_hash_map *normalise_hashmap_ptrs(SegManager *segMan, reg_t_hash_map &nonnormal_map) { +static reg_t_hash_map *normalizeAddresses(SegManager *segMan, reg_t_hash_map &nonnormal_map) { reg_t_hash_map *normal_map = new reg_t_hash_map(); for (reg_t_hash_map::iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { reg_t reg = i->_key; - SegmentObj *mobj = (reg.segment < segMan->_heap.size()) ? segMan->_heap[reg.segment] : NULL; + SegmentObj *mobj = segMan->getSegmentObj(reg.segment); if (mobj) { reg = mobj->findCanonicAddress(segMan, reg); @@ -113,11 +113,12 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { debugC(2, kDebugLevelGC, "[GC] -- Finished adding execution stack"); + const Common::Array &heap = segMan->getSegments(); + // Init: Explicitly loaded scripts - for (i = 1; i < segMan->_heap.size(); i++) { - if (segMan->_heap[i] - && segMan->_heap[i]->getType() == SEG_TYPE_SCRIPT) { - Script *script = (Script *)segMan->_heap[i]; + for (i = 1; i < heap.size(); i++) { + if (heap[i] && heap[i]->getType() == SEG_TYPE_SCRIPT) { + Script *script = (Script *)heap[i]; if (script->getLockers()) { // Explicitly loaded? wm.pushArray(script->listObjectReferences()); @@ -134,15 +135,15 @@ reg_t_hash_map *find_all_used_references(EngineState *s) { wm._worklist.pop_back(); if (reg.segment != stack_seg) { // No need to repeat this one debugC(2, kDebugLevelGC, "[GC] Checking %04x:%04x", PRINT_REG(reg)); - if (reg.segment < segMan->_heap.size() && segMan->_heap[reg.segment]) { + if (reg.segment < heap.size() && heap[reg.segment]) { // Valid heap object? Find its outgoing references! - wm.pushArray(segMan->_heap[reg.segment]->listAllOutgoingReferences(reg)); + wm.pushArray(heap[reg.segment]->listAllOutgoingReferences(reg)); } } } // Normalise - normal_map = normalise_hashmap_ptrs(segMan, wm._map); + normal_map = normalizeAddresses(segMan, wm._map); return normal_map; } @@ -162,8 +163,9 @@ void run_gc(EngineState *s) { // Iterate over all segments, and check for each whether it // contains stuff that can be collected. - for (uint seg = 1; seg < segMan->_heap.size(); seg++) { - SegmentObj *mobj = segMan->_heap[seg]; + const Common::Array &heap = segMan->getSegments(); + for (uint seg = 1; seg < heap.size(); seg++) { + SegmentObj *mobj = heap[seg]; if (mobj != NULL) { const SegmentType type = mobj->getType(); segnames[type] = SegmentObj::getSegmentTypeName(type); diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index a5cfc5013b..185a266203 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -553,7 +553,7 @@ static void *derefPtr(SegManager *segMan, reg_t pointer, int entries, bool wantR if (ret.isRaw != wantRaw) { warning("Dereferencing pointer %04x:%04x (type %d) which is %s, but expected %s", PRINT_REG(pointer), - segMan->_heap[pointer.segment]->getType(), + segMan->getSegmentType(pointer.segment), ret.isRaw ? "raw" : "not raw", wantRaw ? "raw" : "not raw"); } diff --git a/engines/sci/engine/seg_manager.h b/engines/sci/engine/seg_manager.h index 5bb6f7e524..a7f5f8517f 100644 --- a/engines/sci/engine/seg_manager.h +++ b/engines/sci/engine/seg_manager.h @@ -438,8 +438,8 @@ public: */ reg_t findObjectByName(const Common::String &name, int index = -1); - uint32 classTableSize() { return _classTable.size(); } - Class getClass(int index) { return _classTable[index]; } + uint32 classTableSize() const { return _classTable.size(); } + Class getClass(int index) const { return _classTable[index]; } void setClassOffset(int index, reg_t offset) { _classTable[index].reg = offset; } void resizeClassTable(uint32 size) { _classTable.resize(size); } @@ -460,9 +460,6 @@ public: return &_sysStrings->_strings[idx]; } -public: // TODO: make private - Common::Array _heap; - #ifdef ENABLE_SCI32 SciArray *allocateArray(reg_t *addr); SciArray *lookupArray(reg_t addr); @@ -473,8 +470,10 @@ public: // TODO: make private SegmentId getStringSegmentId() { return _stringSegId; } #endif + const Common::Array &getSegments() const { return _heap; } + private: - // Only accessible from saveLoadWithSerializer() + Common::Array _heap; Common::Array _classTable; /**< Table of all classes */ /** Map script ids to segment ids. */ Common::HashMap _scriptSegMap; -- cgit v1.2.3 From 9d47b191f6302ac8960bb4d91d32104c0993a198 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:05:47 +0000 Subject: SCI: Rename some more stuff svn-id: r50553 --- engines/sci/console.cpp | 4 ++-- engines/sci/engine/gc.cpp | 14 +++++++------- engines/sci/engine/gc.h | 9 +++++---- 3 files changed, 14 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b5fc903108..b83ffee0e7 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1757,10 +1757,10 @@ bool Console::cmdGCInvoke(int argc, const char **argv) { } bool Console::cmdGCObjects(int argc, const char **argv) { - reg_t_hash_map *use_map = find_all_used_references(_engine->_gamestate); + AddrSet *use_map = findAllActiveReferences(_engine->_gamestate); DebugPrintf("Reachable object references (normalised):\n"); - for (reg_t_hash_map::iterator i = use_map->begin(); i != use_map->end(); ++i) { + for (AddrSet::iterator i = use_map->begin(); i != use_map->end(); ++i) { DebugPrintf(" - %04x:%04x\n", PRINT_REG(i->_key)); } diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index 75456bcef0..936b83d760 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -30,7 +30,7 @@ namespace Sci { struct WorklistManager { Common::Array _worklist; - reg_t_hash_map _map; + AddrSet _map; void push(reg_t reg) { if (!reg.segment) // No numbers @@ -51,10 +51,10 @@ struct WorklistManager { } }; -static reg_t_hash_map *normalizeAddresses(SegManager *segMan, reg_t_hash_map &nonnormal_map) { - reg_t_hash_map *normal_map = new reg_t_hash_map(); +static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) { + AddrSet *normal_map = new AddrSet(); - for (reg_t_hash_map::iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { + for (AddrSet::const_iterator i = nonnormal_map.begin(); i != nonnormal_map.end(); ++i) { reg_t reg = i->_key; SegmentObj *mobj = segMan->getSegmentObj(reg.segment); @@ -68,9 +68,9 @@ static reg_t_hash_map *normalizeAddresses(SegManager *segMan, reg_t_hash_map &no } -reg_t_hash_map *find_all_used_references(EngineState *s) { +AddrSet *findAllActiveReferences(EngineState *s) { SegManager *segMan = s->_segMan; - reg_t_hash_map *normal_map = NULL; + AddrSet *normal_map = NULL; WorklistManager wm; uint i; @@ -159,7 +159,7 @@ void run_gc(EngineState *s) { memset(segcount, 0, sizeof(segcount)); // Compute the set of all segments references currently in use. - reg_t_hash_map *activeRefs = find_all_used_references(s); + AddrSet *activeRefs = findAllActiveReferences(s); // Iterate over all segments, and check for each whether it // contains stuff that can be collected. diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index cfae517790..f4318a1453 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -35,21 +35,22 @@ namespace Sci { struct reg_t_Hash { uint operator()(const reg_t& x) const { - return (x.segment << 3) | x.offset; + return (x.segment << 3) ^ x.offset ^ (x.offset << 16); } }; /* - * The reg_t_hash_map is actually really a hashset + * The AddrSet is a "set" of reg_t values. + * We don't have a HashSet type, so we abuse a HashMap for this. */ -typedef Common::HashMap reg_t_hash_map; +typedef Common::HashMap AddrSet; /** * Finds all used references and normalises them to their memory addresses * @param s The state to gather all information from * @return A hash map containing entries for all used references */ -reg_t_hash_map *find_all_used_references(EngineState *s); +AddrSet *findAllActiveReferences(EngineState *s); /** * Runs garbage collection on the current system state -- cgit v1.2.3 From aa6be750fb6c04c06fd7c423b64e445c515b0154 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 16:06:04 +0000 Subject: SCI: Invoke resetSegMan from SegManager::saveLoadWithSerializer, not from EngineState::saveLoadWithSerializer svn-id: r50554 --- engines/sci/engine/savegame.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index bf29dbb046..dd8c3ca31d 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -178,6 +178,9 @@ void syncWithSerializer(Common::Serializer &s, reg_t &obj) { } void SegManager::saveLoadWithSerializer(Common::Serializer &s) { + if (s.isLoading()) + resetSegMan(); + s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be reserved_id s.skip(4, VER(9), VER(18)); // OBSOLETE: Used to be _exportsAreWide s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be gc_mark_bits @@ -340,9 +343,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not - if (s.isLoading()) - _segMan->resetSegMan(); - _segMan->saveLoadWithSerializer(s); g_sci->_soundCmd->syncPlayList(s); -- cgit v1.2.3 From 2d6f912bd10f70ae556af627f2b4ae6565f904ed Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Thu, 1 Jul 2010 17:06:14 +0000 Subject: Fix playing RAW and RAW80 streams svn-id: r50558 --- engines/draci/sound.cpp | 14 ++++++++++---- engines/draci/sound.h | 2 +- 2 files changed, 11 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index e430da7bdc..eddf10e3ad 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -180,6 +180,10 @@ SoundSample *LegacySoundArchive::getSample(int i, uint freq) { void ZipSoundArchive::openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency) { closeArchive(); + if ((_format == RAW || _format == RAW80) && !raw_frequency) { + error("openArchive() expects frequency for RAW data"); + return; + } _archive = Common::makeZipArchive(path); _path = path; @@ -294,17 +298,19 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffe // script.cpp, which blocks until the dubbed sentence has finished // playing. Common::SeekableReadStream* stream; + const int skip = buffer._format == RAW80 ? 80 : 0; if (buffer._stream) { - stream = new Common::SeekableSubReadStream(buffer._stream, 0, buffer._stream->size(), DisposeAfterUse::NO); + stream = new Common::SeekableSubReadStream( + buffer._stream, skip, buffer._stream->size() /* end */, DisposeAfterUse::NO); } else { - stream = new Common::MemoryReadStream(buffer._data, buffer._length, DisposeAfterUse::NO); + stream = new Common::MemoryReadStream( + buffer._data + skip, buffer._length - skip /* length */, DisposeAfterUse::NO); } Audio::SeekableAudioStream *reader = NULL; switch (buffer._format) { - case RAW80: - stream->skip(80); // and fall-thru case RAW: + case RAW80: reader = Audio::makeRawStream(stream, buffer._frequency, Audio::FLAG_UNSIGNED, DisposeAfterUse::YES); break; #ifdef USE_MAD diff --git a/engines/draci/sound.h b/engines/draci/sound.h index b1a91bb55b..2fade6de0b 100644 --- a/engines/draci/sound.h +++ b/engines/draci/sound.h @@ -54,7 +54,7 @@ struct SoundSample { Common::SeekableReadStream* _stream; SoundSample() : _offset(0), _length(0), _frequency(0), _format(RAW), _data(NULL), _stream(NULL) { } - // The standard copy constructor is good enough, since we only stored numbers and pointers. + // The standard copy constructor is good enough, since we only store numbers and pointers. // Don't call close() automaticall in the destructor, otherwise copying causes SIGSEGV. void close() { delete[] _data; -- cgit v1.2.3 From 6859a305553ad3d5e88da1bcdd63aee7c8c44824 Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Thu, 1 Jul 2010 17:16:06 +0000 Subject: Fix a typo in the RAW format bugfix :-) svn-id: r50559 --- engines/draci/sound.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index eddf10e3ad..aa696832bb 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -180,7 +180,7 @@ SoundSample *LegacySoundArchive::getSample(int i, uint freq) { void ZipSoundArchive::openArchive(const char *path, const char *extension, SoundFormat format, int raw_frequency) { closeArchive(); - if ((_format == RAW || _format == RAW80) && !raw_frequency) { + if ((format == RAW || format == RAW80) && !raw_frequency) { error("openArchive() expects frequency for RAW data"); return; } -- cgit v1.2.3 From a1dc56429c3d61afe960924abdc4ee241c4c9fe6 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 17:42:39 +0000 Subject: SCI: Removed duplicate warning for missing audio samples svn-id: r50560 --- engines/sci/sound/audio.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/audio.cpp b/engines/sci/sound/audio.cpp index ed9061ab81..2e92754cad 100644 --- a/engines/sci/sound/audio.cpp +++ b/engines/sci/sound/audio.cpp @@ -70,10 +70,11 @@ int AudioPlayer::startAudio(uint16 module, uint32 number) { _mixer->playStream(Audio::Mixer::kSpeechSoundType, &_audioHandle, audioStream); return sampleLen; } else { - warning("startAudio: unable to create stream for audio number %d, module %d", number, module); + // Don't throw a warning in this case. getAudioStream() already has. Some games + // do miss audio entries (perhaps because of a typo, or because they were simply + // forgotten). + return 0; } - - return 0; } int AudioPlayer::wPlayAudio(uint16 module, uint32 tuple) { -- cgit v1.2.3 From cc243bae34c9aab022c113d0c09b7a70cb30f0c8 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 1 Jul 2010 17:47:46 +0000 Subject: KYRA/PC98: implement proper volume control (which distinguishes between music and sfx) svn-id: r50561 --- engines/kyra/sound_intern.h | 4 ++ engines/kyra/sound_towns.cpp | 129 +++++++++++++++++++++++++++++++++++++++---- 2 files changed, 123 insertions(+), 10 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_intern.h b/engines/kyra/sound_intern.h index f4aab4db29..a229dc310d 100644 --- a/engines/kyra/sound_intern.h +++ b/engines/kyra/sound_intern.h @@ -180,6 +180,8 @@ public: int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx) { return -1; } void playSoundEffect(uint8); + void updateVolumeSettings(); + protected: int _lastTrack; uint8 *_musicTrackData; @@ -207,6 +209,8 @@ public: int32 voicePlay(const char *file, Audio::SoundHandle *handle, uint8 volume, bool isSfx); void playSoundEffect(uint8 track); + void updateVolumeSettings(); + protected: Audio::AudioStream *_currentSFX; int _lastTrack; diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index b0d3f994f2..298264c730 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -23,7 +23,9 @@ * */ +#include "common/config-manager.h" #include "common/system.h" + #include "kyra/resource.h" #include "kyra/sound_intern.h" #include "kyra/screen.h" @@ -1491,6 +1493,9 @@ public: void nextTick(int32 *buffer, uint32 bufferSize); + void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; } + void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; } + uint8 chanEnable() const { return _chanEnable; } private: void updatesRegs(); @@ -1530,6 +1535,11 @@ private: uint8 **_reg; + uint16 _volumeA; + uint16 _volumeB; + int _volMaskA; + int _volMaskB; + bool _ready; }; @@ -1544,6 +1554,9 @@ public: void nextTick(int32 *buffer, uint32 bufferSize); + void setVolumeIntern(int volA, int volB) { _volumeA = volA; _volumeB = volB; } + void setVolumeChannelMasks(int channelMaskA, int channelMaskB) { _volMaskA = channelMaskA; _volMaskB = channelMaskB; } + private: struct RhtChannel { const uint8 *data; @@ -1579,6 +1592,11 @@ private: uint8 **_reg; + uint16 _volumeA; + uint16 _volumeB; + int _volMaskA; + int _volMaskB; + bool _ready; }; @@ -1605,20 +1623,27 @@ public: int getRate() const { return _mixer->getOutputRate(); } protected: - void generateTables(); - void toggleRegProtection(bool prot) { _regProtectionFlag = prot; } uint8 readSSGStatus() { return _ssg->chanEnable(); } virtual void timerCallbackA() = 0; virtual void timerCallbackB() = 0; + // The audio driver can store and apply two different audio settings + // (usually for music and sound effects). The channel mask will determine + // which channels get effected by the setting. The first bits will be + // the normal opn channels, the next bits the ssg channels and the final + // bit the rhythm channel. + void setVolumeIntern(int volA, int volB); + void setVolumeChannelMasks(int channelMaskA, int channelMaskB); + const int _numChan; const int _numSSG; const bool _hasPercussion; Common::Mutex _mutex; private: + void generateTables(); void nextTick(int32 *buffer, uint32 bufferSize); void generateOutput(int32 &leftSample, int32 &rightSample, int32 *del, int32 *feed); @@ -1671,6 +1696,9 @@ private: OpnTimer _timers[2]; + int _volMaskA, _volMaskB; + uint16 _volumeA, _volumeB; + const float _baserate; uint32 _timerbase; @@ -1710,6 +1738,9 @@ public: bool looping() { return _looping == _updateChannelsFlag ? true : false; } bool musicPlaying() { return _musicPlaying; } + void setMusicVolume(int volume) { _musicVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); } + void setSoundEffectVolume(int volume) { _sfxVolume = volume; setVolumeIntern(_musicVolume, _sfxVolume); } + protected: void startSoundEffect(); @@ -1752,6 +1783,9 @@ protected: uint8 *_sfxData; uint16 _sfxOffsets[2]; + uint16 _musicVolume; + uint16 _sfxVolume; + static const uint8 _drvTables[]; bool _ready; @@ -2558,7 +2592,8 @@ bool TownsPC98_OpnChannelPCM::control_ff_endOfTrack(uint8 para) { TownsPC98_OpnSquareSineSource::TownsPC98_OpnSquareSineSource(const uint32 timerbase) : _tlTable(0), _tleTable(0), _updateRequest(-1), _tickLength(timerbase * 27), _ready(0), _reg(0), _rand(1), _outN(1), _nTick(0), _evpUpdateCnt(0), _evpTimer(0x1f), _pReslt(0x1f), _attack(0), _cont(false), _evpUpdate(true), - _timer(0), _noiseGenerator(0), _chanEnable(0) { + _timer(0), _noiseGenerator(0), _chanEnable(0), + _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) { memset(_channels, 0, sizeof(_channels)); memset(_updateRequestBuf, 0, sizeof(_updateRequestBuf)); @@ -2718,6 +2753,13 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { } finOut /= 3; + + if ((1 << i) & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if ((1 << i) & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } @@ -2733,7 +2775,7 @@ void TownsPC98_OpnSquareSineSource::updatesRegs() { } TownsPC98_OpnPercussionSource::TownsPC98_OpnPercussionSource(const uint32 timerbase) : - _tickLength(timerbase * 2), _timer(0), _ready(false) { + _tickLength(timerbase * 2), _timer(0), _ready(false), _volMaskA(0), _volMaskB(0), _volumeA(Audio::Mixer::kMaxMixerVolume), _volumeB(Audio::Mixer::kMaxMixerVolume) { memset(_rhChan, 0, sizeof(RhtChannel) * 6); _reg = new uint8 *[40]; @@ -2892,6 +2934,12 @@ void TownsPC98_OpnPercussionSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut <<= 1; + if (1 & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if (1 & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; } @@ -2928,6 +2976,7 @@ TownsPC98_OpnCore::TownsPC98_OpnCore(Audio::Mixer *mixer, OpnType type) : _numChan(type == OD_TYPE26 ? 3 : 6), _numSSG(type == OD_TOWNS ? 0 : 3), _hasPercussion(type == OD_TYPE86 ? true : false), _oprRates(0), _oprRateshift(0), _oprAttackDecay(0), _oprFrq(0), _oprSinTbl(0), _oprLevelOut(0), _oprDetune(0), _baserate(55125.0f / (float)mixer->getOutputRate()), + _volMaskA(0), _volMaskB(0), _volumeA(255), _volumeB(255), _regProtectionFlag(false), _ready(false) { memset(&_timers[0], 0, sizeof(OpnTimer)); @@ -2978,7 +3027,7 @@ bool TownsPC98_OpnCore::init() { _prc->init(_percussionData); } - _mixer->playStream(Audio::Mixer::kMusicSoundType, + _mixer->playStream(Audio::Mixer::kPlainSoundType, &_soundHandle, this, -1, Audio::Mixer::kMaxChannelVolume, 0, DisposeAfterUse::NO, true); _ready = true; @@ -3229,6 +3278,26 @@ int TownsPC98_OpnCore::readBuffer(int16 *buffer, const int numSamples) { return numSamples; } +void TownsPC98_OpnCore::setVolumeIntern(int volA, int volB) { + Common::StackLock lock(_mutex); + _volumeA = volA; + _volumeB = volB; + if (_ssg) + _ssg->setVolumeIntern(volA, volB); + if (_prc) + _prc->setVolumeIntern(volA, volB); +} + +void TownsPC98_OpnCore::setVolumeChannelMasks(int channelMaskA, int channelMaskB) { + Common::StackLock lock(_mutex); + _volMaskA = channelMaskA; + _volMaskB = channelMaskB; + if (_ssg) + _ssg->setVolumeChannelMasks(_volMaskA >> _numChan, _volMaskB >> _numChan); + if (_prc) + _prc->setVolumeChannelMasks(_volMaskA >> (_numChan + _numSSG), _volMaskB >> (_numChan + _numSSG)); +} + void TownsPC98_OpnCore::generateTables() { delete[] _oprRates; _oprRates = new uint8[128]; @@ -3389,6 +3458,12 @@ void TownsPC98_OpnCore::nextTick(int32 *buffer, uint32 bufferSize) { int32 finOut = (output << 2) / ((_numChan + _numSSG - 3) / 3); + if ((1 << i) & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + + if ((1 << i) & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + if (_chanInternal[i].enableLeft) *leftSample += finOut; @@ -3409,11 +3484,14 @@ TownsPC98_OpnDriver::TownsPC98_OpnDriver(Audio::Mixer *mixer, OpnType type) : To _updateChannelsFlag(type == OD_TYPE26 ? 0x07 : 0x3F), _finishedChannelsFlag(0), _updateSSGFlag(type == OD_TOWNS ? 0x00 : 0x07), _finishedSSGFlag(0), _updateRhythmFlag(type == OD_TYPE86 ? 0x01 : 0x00), _finishedRhythmFlag(0), - _updateSfxFlag(type == OD_TOWNS ? 0x00 : 0x06), _finishedSfxFlag(0), + _updateSfxFlag(0), _finishedSfxFlag(0), _musicTickCounter(0), + _musicVolume(255), _sfxVolume(255), + _musicPlaying(false), _sfxPlaying(false), _fading(false), _looping(0), _ready(false) { + _sfxOffsets[0] = _sfxOffsets[1] = 0; } @@ -3451,6 +3529,8 @@ bool TownsPC98_OpnDriver::init() { TownsPC98_OpnCore::init(); + setVolumeChannelMasks(-1, 0); + _channels = new TownsPC98_OpnChannel *[_numChan]; for (int i = 0; i < _numChan; i++) { int ii = i * 6; @@ -3665,8 +3745,11 @@ void TownsPC98_OpnDriver::timerCallbackA() { _trackPtr = _musicBuffer; } - if (_finishedSfxFlag == _updateSfxFlag) + if (_updateSfxFlag && _finishedSfxFlag == _updateSfxFlag) { _sfxPlaying = false; + _updateSfxFlag = 0; + setVolumeChannelMasks(-1, 0); + } } void TownsPC98_OpnDriver::setMusicTempo(uint8 tempo) { @@ -3681,14 +3764,21 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { } void TownsPC98_OpnDriver::startSoundEffect() { - for (int i = 0; i < 2; i++) { + int i = 0; + for (; i < 2; i++) { if (_sfxOffsets[i]) { _ssgChannels[i + 1]->protect(); _sfxChannels[i]->reset(); _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]); + _updateSfxFlag |= _sfxChannels[i]->_idFlag; } } + int volFlags = 0; + for (i = 0; i < (_numChan + _numSSG - 2); i++) + volFlags |= (1 << i); + setVolumeChannelMasks(volFlags, ~volFlags); + _sfxData = 0; } @@ -4049,7 +4139,9 @@ SoundPC98::~SoundPC98() { bool SoundPC98::init() { _driver = new TownsPC98_OpnDriver(_mixer, TownsPC98_OpnDriver::OD_TYPE26); - return _driver->init(); + bool reslt = _driver->init(); + updateVolumeSettings(); + return reslt; } void SoundPC98::loadSoundFile(uint file) { @@ -4122,6 +4214,13 @@ void SoundPC98::playSoundEffect(uint8 track) { _driver->loadSoundEffectData(_sfxTrackData, track); } +void SoundPC98::updateVolumeSettings() { + if (!_driver) + return; + + _driver->setMusicVolume(ConfMan.getInt("music_volume")); + _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume")); +} // KYRA 2 @@ -4160,7 +4259,9 @@ bool SoundTownsPC98_v2::init() { _useFmSfx = true; } - return _driver->init(); + bool reslt = _driver->init(); + updateVolumeSettings(); + return reslt; } void SoundTownsPC98_v2::loadSoundFile(Common::String file) { @@ -4315,6 +4416,14 @@ void SoundTownsPC98_v2::playSoundEffect(uint8 track) { _driver->loadSoundEffectData(_sfxTrackData, track); } +void SoundTownsPC98_v2::updateVolumeSettings() { + if (!_driver) + return; + + _driver->setMusicVolume(ConfMan.getInt("music_volume")); + _driver->setSoundEffectVolume(ConfMan.getInt("sfx_volume")); +} + // static resources const uint32 TownsPC98_OpnCore::_adtStat[] = { -- cgit v1.2.3 From 7f3b772938b7b7ab06d764eb47a52d01513f907a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 17:52:50 +0000 Subject: SCI: Added workarounds for 2 uninitialized reads in Jones floppy (EGA and VGA), and added information on the SQ6 uninitialized workarounds svn-id: r50562 --- engines/sci/engine/vm.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e7e16e5a35..32aad38880 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -344,6 +344,8 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // called when the game starts + { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // called when the game starts { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class @@ -355,8 +357,8 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller - { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, - { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, + { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, // called when the game starts + { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, // called when pressing "Start game" in the main menu SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From eb84a130adabde931f025da93c950638fe0316ef Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Thu, 1 Jul 2010 18:34:14 +0000 Subject: KYRA/PC98: minor cleanup svn-id: r50563 --- engines/kyra/sound_towns.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 298264c730..e50981c4c0 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -3764,8 +3764,8 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { } void TownsPC98_OpnDriver::startSoundEffect() { - int i = 0; - for (; i < 2; i++) { + _updateSfxFlag = 0; + for (int i = 0; i < 2; i++) { if (_sfxOffsets[i]) { _ssgChannels[i + 1]->protect(); _sfxChannels[i]->reset(); @@ -3775,7 +3775,7 @@ void TownsPC98_OpnDriver::startSoundEffect() { } int volFlags = 0; - for (i = 0; i < (_numChan + _numSSG - 2); i++) + for (int i = 0; i < (_numChan + _numSSG - 2); i++) volFlags |= (1 << i); setVolumeChannelMasks(volFlags, ~volFlags); -- cgit v1.2.3 From 1a675dcd86d7d3d3cae97c7e7b1bc81555af93f1 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 1 Jul 2010 18:47:27 +0000 Subject: Add support for the 'fallback' MIDI in T7G's intro when the CD track cannot be found. The intro music in the Mac version now plays. svn-id: r50564 --- engines/groovie/groovie.cpp | 12 ++++++++---- engines/groovie/groovie.h | 2 ++ engines/groovie/music.cpp | 14 ++++++++++++++ 3 files changed, 24 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index e0760e1d41..9da413d362 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -110,7 +110,7 @@ Common::Error GroovieEngine::run() { // Prepare the font too switch (_gameDescription->version) { case kGroovieT7G: - if (_gameDescription->desc.platform == Common::kPlatformMacintosh) { + if (getPlatform() == Common::kPlatformMacintosh) { _macResFork = new Common::MacResManager(); if (!_macResFork->open(_gameDescription->desc.filesDescriptions[0].fileName)) error("Could not open %s as a resource fork", _gameDescription->desc.filesDescriptions[0].fileName); @@ -141,7 +141,7 @@ Common::Error GroovieEngine::run() { } // Create the music player - if (_gameDescription->desc.platform == Common::kPlatformMacintosh) + if (getPlatform() == Common::kPlatformMacintosh) _musicPlayer = new MusicPlayerMac(this); else _musicPlayer = new MusicPlayerXMI(this, _gameDescription->version == kGroovieT7G ? "fat" : "sample"); @@ -154,8 +154,8 @@ Common::Error GroovieEngine::run() { if (_gameDescription->version == kGroovieT7G) { // Run The 7th Guest's demo if requested if (ConfMan.hasKey("demo_mode") && ConfMan.getBool("demo_mode")) - filename = Common::String("demo.grv"); - else if (_gameDescription->desc.platform == Common::kPlatformMacintosh) + filename = "demo.grv"; + else if (getPlatform() == Common::kPlatformMacintosh) filename = "script.grv"; // Stored inside the executable's resource fork } else if (_gameDescription->version == kGroovieV2) { // Open the disk index @@ -307,6 +307,10 @@ Common::Error GroovieEngine::run() { return Common::kNoError; } +Common::Platform GroovieEngine::getPlatform() const { + return _gameDescription->desc.platform; +} + bool GroovieEngine::hasFeature(EngineFeature f) const { return (f == kSupportsRTL) || diff --git a/engines/groovie/groovie.h b/engines/groovie/groovie.h index 437debfd17..8ae5f4157f 100644 --- a/engines/groovie/groovie.h +++ b/engines/groovie/groovie.h @@ -82,6 +82,8 @@ public: GroovieEngine(OSystem *syst, const GroovieGameDescription *gd); ~GroovieEngine(); + Common::Platform getPlatform() const; + protected: // Engine APIs diff --git a/engines/groovie/music.cpp b/engines/groovie/music.cpp index f226ef3397..6959a6a6f1 100644 --- a/engines/groovie/music.cpp +++ b/engines/groovie/music.cpp @@ -111,6 +111,20 @@ void MusicPlayer::playCD(uint8 track) { // Play the track starting at the requested offset (1000ms = 75 frames) AudioCD.play(track - 1, 1, startms * 75 / 1000, 0); + + // If the audio is not playing from the CD, play the "fallback" MIDI. + // The Mac version has no CD tracks, so it will always use the MIDI. + if (!AudioCD.isPlaying()) { + if (track == 2) { + // Intro MIDI fallback + if (_vm->getPlatform() == Common::kPlatformMacintosh) + playSong(70); + else + playSong((19 << 10) | 36); // XMI.GJD, file 36 + } else if (track == 3) { + // TODO: Credits MIDI fallback + } + } } void MusicPlayer::startBackground() { -- cgit v1.2.3 From fa014867cfe6bde10467761e1241b646ecb0460f Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 20:16:42 +0000 Subject: SCI: Mark the ShiftScreen, ListOps and ATan SCI1 kernel functions as unused (dummy) - we haven't seen them being used anywhere. Added a check and an error in case a kernel function which is considered to be unused is called. svn-id: r50567 --- engines/sci/engine/kernel.cpp | 17 +++-------------- engines/sci/engine/vm.cpp | 5 +++++ 2 files changed, 8 insertions(+), 14 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index b0c369605e..58619986cb 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -170,18 +170,18 @@ static const char *s_defaultKernelNames[] = { /*0x6c*/ "Graph", /*0x6d*/ "Joystick", // End of kernel function table for SCI0 - /*0x6e*/ "ShiftScreen", + /*0x6e*/ "Dummy", // ShiftScreen /*0x6f*/ "Palette", /*0x70*/ "MemorySegment", /*0x71*/ "Intersections", // MoveCursor (SCI1 late), PalVary (SCI1.1) /*0x72*/ "Memory", - /*0x73*/ "ListOps", + /*0x73*/ "Dummy", // ListOps /*0x74*/ "FileIO", /*0x75*/ "DoAudio", /*0x76*/ "DoSync", /*0x77*/ "AvoidPath", /*0x78*/ "Sort", // StrSplit (SCI01) - /*0x79*/ "ATan", + /*0x79*/ "Dummy", // ATan /*0x7a*/ "Lock", /*0x7b*/ "StrSplit", /*0x7c*/ "GetMessage", // Message (SCI1.1) @@ -429,17 +429,6 @@ static SciKernelMapEntry s_kernelMap[] = { #endif }; -#if 0 - // Stub functions - /*09*/ { "Show", kShow, "i" }, - { "ShiftScreen", kShiftScreen, ".*" }, - { "ListOps", kListOps, ".*" }, - { "ATan", kATan, ".*" }, - { "Record", kRecord, ".*" }, - { "PlayBack", kPlayBack, ".*" }, - { "DbugStr", kDbugStr, ".*" }, -#endif - Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) : _resMan(resMan), _segMan(segMan), _invalid("") { loadSelectorNames(); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 32aad38880..49049585ee 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -852,6 +852,11 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { } warning("%s", warningMsg.c_str()); + + // Make sure that the game doesn't call a function that is considered unused. If + // that happens, error out. + if (kernelCall.origName == "Dummy") + error("Kernel function %d was called, which was considered to be unused", kernelFuncNr); } } -- cgit v1.2.3 From 0e3f923f78055d0ffe76d5020392653728496f02 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 20:32:41 +0000 Subject: The Shivers demo calls the debug kernel function 0x83 (PrintDebug), thus it isn't unused (thanks to clone2727 for pointing that out) svn-id: r50568 --- engines/sci/engine/kernel32.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 25a822f77d..564e0b76c3 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -336,7 +336,7 @@ static const char *sci21_default_knames[] = { /*0x80*/ "Dummy", /*0x81*/ "Dummy", /*0x82*/ "Dummy", - /*0x83*/ "Dummy", + /*0x83*/ "PrintDebug", // used by the Shivers 2 demo /*0x84*/ "Dummy", /*0x85*/ "Dummy", /*0x86*/ "Dummy", -- cgit v1.2.3 From d5e037e703dfa5ab64bb390e31f817deb85cfb02 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 21:08:38 +0000 Subject: Added some slight fixes for the RAMA demo, which starts now, though it dies horribly when clicking on anything svn-id: r50569 --- engines/sci/engine/features.cpp | 12 ++++++++++++ engines/sci/engine/kernel32.cpp | 7 +++++++ 2 files changed, 19 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/features.cpp b/engines/sci/engine/features.cpp index f0abdde694..fee6e69da7 100644 --- a/engines/sci/engine/features.cpp +++ b/engines/sci/engine/features.cpp @@ -405,6 +405,18 @@ SciVersion GameFeatures::detectGfxFunctionsType() { #ifdef ENABLE_SCI32 bool GameFeatures::autoDetectSci21KernelType() { + // First, check if the Sound object is loaded + reg_t soundObjAddr = _segMan->findObjectByName("Sound"); + if (soundObjAddr.isNull()) { + // Usually, this means that the Sound object isn't loaded yet. + // This case doesn't occur in early SCI2.1 games, and we've only + // seen it happen in the RAMA demo, thus we can assume that the + // game is using a SCI2.1 table + warning("autoDetectSci21KernelType(): Sound object not loaded, assuming a SCI2.1 table"); + _sci21KernelType = SCI_VERSION_2_1; + return true; + } + // Look up the script address reg_t addr = getDetectionAddr("Sound", SELECTOR(play)); diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 564e0b76c3..2d492eb3ee 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -463,6 +463,13 @@ reg_t kArray(EngineState *s, int argc, reg_t *argv) { return argv[1]; } case 6: { // Cpy + if (s->_segMan->getSegmentObj(argv[1].segment)->getType() != SEG_TYPE_ARRAY || + s->_segMan->getSegmentObj(argv[3].segment)->getType() != SEG_TYPE_ARRAY) { + // Happens in the RAMA demo + warning("kArray(Cpy): Request to copy a segment which isn't an array, ignoring"); + return NULL_REG; + } + SciArray *array1 = s->_segMan->lookupArray(argv[1]); SciArray *array2 = s->_segMan->lookupArray(argv[3]); uint32 index1 = argv[2].toUint16(); -- cgit v1.2.3 From 4c04375c8c39a3be660096d66d9d31dc5dd93a93 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 1 Jul 2010 22:09:19 +0000 Subject: SCI: added another workaround for uninit temps, this time for jones/cd svn-id: r50574 --- engines/sci/engine/vm.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 49049585ee..4e26839d16 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -344,8 +344,9 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu - { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // called when the game starts - { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // called when the game starts + { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts + { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class -- cgit v1.2.3 From 32dfd0cedce13f00b512d87b3b9bb7c383cc3b45 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 1 Jul 2010 22:23:05 +0000 Subject: SCI: adding jones/ega to detection tables svn-id: r50575 --- engines/sci/detection_tables.h | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index d2136666a7..e761b64991 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -768,7 +768,16 @@ static const struct ADGameDescription SciGameDescriptions[] = { {NULL, 0, NULL, 0}}, Common::EN_ANY, Common::kPlatformPC, ADGF_DEMO, GUIO_NOSPEECH }, - // Jones in the Fast Lane - English DOS + // Jones in the Fast Lane EGA - English DOS + // SCI interpreter version 1.000.172 (not 100% sure FIXME) + {"jones", "", { + {"resource.map", 0, "be4cf9e8c1e253623ef35ae3b8a1d998", 1800}, + {"resource.001", 0, "bac3ec6cb3e3920984ab0f32becf5163", 202105}, + {"resource.002", 0, "b86daa3ba2784d1502da881eedb80d9b", 341771}, + {NULL, 0, NULL, 0}}, + Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, + + // Jones in the Fast Lane VGA - English DOS // SCI interpreter version 1.000.172 {"jones", "", { {"resource.map", 0, "65cbe19b36fffc71c8e7b2686bd49ad7", 1800}, -- cgit v1.2.3 From 4dd02d2f4ab05839f86db9102c954ca34bfc1c34 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Thu, 1 Jul 2010 22:38:36 +0000 Subject: Support the CD kernel call (stub) and add the TRUE_REG constant. Would be nice to use this constant in pre-existing code. svn-id: r50577 --- engines/sci/engine/kernel.cpp | 1 + engines/sci/engine/kernel.h | 1 + engines/sci/engine/kernel32.cpp | 19 ++++++++++++++++++- engines/sci/engine/vm_types.h | 1 + 4 files changed, 21 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 58619986cb..47f7ac3bc8 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -425,6 +425,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL }, { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(CD), SIG_EVERYWHERE, ".*", NULL, NULL }, { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } #endif }; diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a3cf7b5f91..cb66aa9f4d 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -449,6 +449,7 @@ reg_t kList(EngineState *s, int argc, reg_t *argv); reg_t kRobot(EngineState *s, int argc, reg_t *argv); reg_t kPlayVMD(EngineState *s, int argc, reg_t *argv); reg_t kIsOnMe(EngineState *s, int argc, reg_t *argv); +reg_t kCD(EngineState *s, int argc, reg_t *argv); #endif diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 2d492eb3ee..8b854dbca1 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -898,7 +898,7 @@ reg_t kInPolygon(EngineState *s, int argc, reg_t *argv) { reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { // TODO: argument 0 is usually 0, and arguments 1 and 2 are usually 1 switch (argv[0].toUint16()) { - case 0: + case 0: { if (argc != 4) { warning("kCreateTextBitmap(0): expected 4 arguments, got %i", argc); return NULL_REG; @@ -907,6 +907,23 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { Common::String text = s->_segMan->getString(readSelector(s->_segMan, object, SELECTOR(text))); debug("kCreateTextBitmap: %s", text.c_str()); } + default: + warning("CreateTextBitmap(%d)", argv[0].toUint16()); + } + + return NULL_REG; +} + +reg_t kCD(EngineState *s, int argc, reg_t *argv) +{ + // TODO: Stub + switch (argv[0].toUint16()) { + case 0: + // Return whether the contents of disc argv[1] is available. + return TRUE_REG; + default: + warning("CD(%d)", argv[0].toUint16()); + } return NULL_REG; } diff --git a/engines/sci/engine/vm_types.h b/engines/sci/engine/vm_types.h index 614b6f247d..828fba3d7d 100644 --- a/engines/sci/engine/vm_types.h +++ b/engines/sci/engine/vm_types.h @@ -87,6 +87,7 @@ enum { extern const reg_t NULL_REG; extern const reg_t SIGNAL_REG; +extern const reg_t TRUE_REG; // Selector ID typedef int Selector; -- cgit v1.2.3 From e47dee2faaa04286c39ad5e8d2f066157188cb23 Mon Sep 17 00:00:00 2001 From: Lars Skovlund Date: Thu, 1 Jul 2010 22:44:36 +0000 Subject: Accidentally missed this file in commit 50577 svn-id: r50578 --- engines/sci/engine/vm.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 4e26839d16..cdbdd0beb1 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -44,7 +44,7 @@ namespace Sci { const reg_t NULL_REG = {0, 0}; const reg_t SIGNAL_REG = {0, SIGNAL_OFFSET}; - +const reg_t TRUE_REG = {0, 1}; //#define VM_DEBUG_SEND #define SCI_XS_CALLEE_LOCALS ((SegmentId)-1) -- cgit v1.2.3 From 21450f1a2e6033c706c7027a255844ae83a51f92 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Thu, 1 Jul 2010 22:56:02 +0000 Subject: Added a workaround for an unitialized variable in GK2 svn-id: r50580 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index cdbdd0beb1..45cb117bcf 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -344,6 +344,7 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_GK2, 11, 0, "", "export 10", -1, 3, { 0, 0 } }, // called when the game starts { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts -- cgit v1.2.3 From ac351c175f7201e49f175e80105bdc704a9ea02f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Thu, 1 Jul 2010 23:05:13 +0000 Subject: Fix code formatting svn-id: r50581 --- engines/sci/engine/kernel32.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel32.cpp b/engines/sci/engine/kernel32.cpp index 8b854dbca1..eab1b90139 100644 --- a/engines/sci/engine/kernel32.cpp +++ b/engines/sci/engine/kernel32.cpp @@ -914,8 +914,7 @@ reg_t kCreateTextBitmap(EngineState *s, int argc, reg_t *argv) { return NULL_REG; } -reg_t kCD(EngineState *s, int argc, reg_t *argv) -{ +reg_t kCD(EngineState *s, int argc, reg_t *argv) { // TODO: Stub switch (argv[0].toUint16()) { case 0: -- cgit v1.2.3 From 8b0f49b801afbef5ae2523078e82963c1120b3f5 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Thu, 1 Jul 2010 23:13:42 +0000 Subject: Only print the ambiguous object notice in findObjectByName if we didn't specify an index. svn-id: r50584 --- engines/sci/engine/seg_manager.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 185a266203..135ad38792 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -300,14 +300,11 @@ reg_t SegManager::findObjectByName(const Common::String &name, int index) { if (result.empty()) return NULL_REG; - if (result.size() > 1) { + if (result.size() > 1 && index < 0) { printf("Ambiguous:\n"); for (i = 0; i < result.size(); i++) printf(" %3x: [%04x:%04x] %s\n", i, PRINT_REG(result[i]), name.c_str()); - if (index < 0) { - printf("Ambiguous: Aborting.\n"); - return NULL_REG; // Ambiguous - } + return NULL_REG; // Ambiguous } if (index < 0) -- cgit v1.2.3 From b252d5f0b97e229e73ed1c63b48d8c2e7896775a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 08:53:51 +0000 Subject: getString() on a NULL pointer is an empty string (verified in SCI2.1) svn-id: r50591 --- engines/sci/engine/seg_manager.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 135ad38792..339920936f 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -789,6 +789,9 @@ size_t SegManager::strlen(reg_t str) { Common::String SegManager::getString(reg_t pointer, int entries) { Common::String ret; + if (pointer.isNull()) + return ret; // empty text + SegmentRef src_r = dereference(pointer); if (!src_r.isValid()) { warning("SegManager::getString(): Attempt to dereference invalid pointer %04x:%04x", PRINT_REG(pointer)); -- cgit v1.2.3 From 91a414dbc9f712484de2e5dac66ae3dafe467e6a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 08:55:12 +0000 Subject: Extended the SCI2 text drawing hack for SCI2.1 too, and added font caching svn-id: r50592 --- engines/sci/graphics/frameout.cpp | 38 ++++++++++++++++---------------------- 1 file changed, 16 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/frameout.cpp b/engines/sci/graphics/frameout.cpp index 48a7742f14..9ce4474ee3 100644 --- a/engines/sci/graphics/frameout.cpp +++ b/engines/sci/graphics/frameout.cpp @@ -278,29 +278,23 @@ void GfxFrameout::kernelFrameout() { // Most likely a text entry // This draws text the "SCI0-SCI11" way. In SCI2, text is prerendered in kCreateTextBitmap // TODO: rewrite this the "SCI2" way (i.e. implement the text buffer to draw inside kCreateTextBitmap) - // This doesn't work for SCI2.1 games... - if (getSciVersion() == SCI_VERSION_2) { - Kernel *kernel = g_sci->getKernel(); - if (lookupSelector(_segMan, itemEntry->object, kernel->_selectorCache.text, NULL, NULL) == kSelectorVariable) { - Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text))); - int16 fontRes = readSelectorValue(_segMan, itemEntry->object, SELECTOR(font)); - GfxFont *font = new GfxFontFromResource(_resMan, _screen, fontRes); - bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed)); - uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore)); - uint16 curX = itemEntry->x; - uint16 curY = itemEntry->y; - for (uint32 i = 0; i < text.size(); i++) { - unsigned char curChar = text[i]; - // TODO: proper text splitting... this is a hack - if ((curChar == ' ' && i > 0 && text[i - i] == ' ') || curChar == '\n' || - (curX + font->getCharWidth(curChar) > _screen->getWidth())) { - curY += font->getHeight(); - curX = itemEntry->x; - } - font->draw(curChar, curY, curX, foreColor, dimmed); - curX += font->getCharWidth(curChar); + if (lookupSelector(_segMan, itemEntry->object, SELECTOR(text), NULL, NULL) == kSelectorVariable) { + Common::String text = _segMan->getString(readSelector(_segMan, itemEntry->object, SELECTOR(text))); + GfxFont *font = _cache->getFont(readSelectorValue(_segMan, itemEntry->object, SELECTOR(font))); + bool dimmed = readSelectorValue(_segMan, itemEntry->object, SELECTOR(dimmed)); + uint16 foreColor = readSelectorValue(_segMan, itemEntry->object, SELECTOR(fore)); + uint16 curX = itemEntry->x; + uint16 curY = itemEntry->y; + for (uint32 i = 0; i < text.size(); i++) { + unsigned char curChar = text[i]; + // TODO: proper text splitting... this is a hack + if ((curChar == ' ' && i > 0 && text[i - i] == ' ') || curChar == '\n' || + (curX + font->getCharWidth(curChar) > _screen->getWidth())) { + curY += font->getHeight(); + curX = itemEntry->x; } - delete font; + font->draw(curChar, curY, curX, foreColor, dimmed); + curX += font->getCharWidth(curChar); } } } -- cgit v1.2.3 From b8ff75047bdc9dfa591c66ceab6f421cb92ff89f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 2 Jul 2010 09:09:22 +0000 Subject: SCI: changing adjusting of upscaled hires box coordinates svn-id: r50593 --- engines/sci/graphics/paint16.cpp | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/paint16.cpp b/engines/sci/graphics/paint16.cpp index 48967c6888..90b05c68a6 100644 --- a/engines/sci/graphics/paint16.cpp +++ b/engines/sci/graphics/paint16.cpp @@ -317,11 +317,12 @@ reg_t GfxPaint16::bitsSave(const Common::Rect &rect, byte screenMask) { return NULL_REG; if (screenMask == GFX_SCREEN_MASK_DISPLAY) { + // The coordinates we are given are actually up-to-including right/bottom - we extend accordingly + workerRect.bottom++; + workerRect.right++; // Adjust rect to upscaled hires, but dont adjust according to port _screen->adjustToUpscaledCoordinates(workerRect.top, workerRect.left); _screen->adjustToUpscaledCoordinates(workerRect.bottom, workerRect.right); - workerRect.bottom++; - workerRect.right++; } else { _ports->offsetRect(workerRect); } -- cgit v1.2.3 From 7b6be52f227aeaf2b544b3b35dd872f3643b1ff4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 2 Jul 2010 09:50:33 +0000 Subject: SCI: added possible workaround or final solution for hires portraits not fully removed from screen in kq6 - needs to get investigated further but this will get a little bit difficult svn-id: r50594 --- engines/sci/graphics/screen.cpp | 5 +++++ 1 file changed, 5 insertions(+) (limited to 'engines') diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index c446a98768..a314405eb1 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -438,6 +438,11 @@ void GfxScreen::bitsRestore(byte *memoryPtr) { if (!_upscaledHires) error("bitsRestore() called w/o being in upscaled hires mode"); bitsRestoreScreen(rect, memoryPtr, _displayScreen, _displayWidth); + // WORKAROUND - we are not sure what sierra is doing. If we don't do this here, portraits won't get fully removed + // from screen. Some lowres showBits() call is used for that and it's not covering the whole area + // We would need to find out inside the kq6 windows interpreter, but this here works already and seems not to have + // any side-effects. The whole hires is hacked into the interpreter, so maybe this is even right. + copyDisplayRectToScreen(rect); } } -- cgit v1.2.3 From 79768098b13e20bade076b8a36c9d8cd16514b2a Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 10:18:11 +0000 Subject: Added handling for kLock called with resource id -1 (unlock all resources of the requested type). Happens e.g. in KQ6 and LSL6 svn-id: r50595 --- engines/sci/engine/kscripts.cpp | 34 ++++++++++++++++++++++++---------- engines/sci/resource.h | 2 +- 2 files changed, 25 insertions(+), 11 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 4f4df7d875..4a50553b34 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -86,16 +86,30 @@ reg_t kLock(EngineState *s, int argc, reg_t *argv) { g_sci->getResMan()->findResource(id, 1); break; case 0 : - which = g_sci->getResMan()->findResource(id, 0); - - if (which) - g_sci->getResMan()->unlockResource(which); - else { - if (id.getType() == kResourceTypeInvalid) - warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type); - else - // Happens in CD games (e.g. LSL6CD) with the message resource - warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); + if (id.getNumber() == 0xFFFF) { + // Unlock all resources of the requested type + Common::List *resources = g_sci->getResMan()->listResources(type); + Common::List::iterator itr = resources->begin(); + + while (itr != resources->end()) { + Resource *res = g_sci->getResMan()->testResource(*itr); + if (res->isLocked()) + g_sci->getResMan()->unlockResource(res); + ++itr; + } + + } else { + which = g_sci->getResMan()->findResource(id, 0); + + if (which) + g_sci->getResMan()->unlockResource(which); + else { + if (id.getType() == kResourceTypeInvalid) + warning("[resMan] Attempt to unlock resource %i of invalid type %i", id.getNumber(), type); + else + // Happens in CD games (e.g. LSL6CD) with the message resource + warning("[resMan] Attempt to unlock non-existant resource %s", id.toString().c_str()); + } } break; } diff --git a/engines/sci/resource.h b/engines/sci/resource.h index a13781b157..f66b5b3956 100644 --- a/engines/sci/resource.h +++ b/engines/sci/resource.h @@ -210,7 +210,7 @@ public: inline ResourceType getType() const { return _id.getType(); } inline uint16 getNumber() const { return _id.getNumber(); } - + bool isLocked() const { return _status == kResStatusLocked; } /** * Write the resource to the specified stream. * This method is used only by the "dump" debugger command. -- cgit v1.2.3 From dcb92c83521794af87fc64f941e7d3bf71818c36 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 10:38:42 +0000 Subject: Add checks for null reference to strncpy() and strlen() - happens for example when trying to talk to inanimate objects in KQ6 svn-id: r50596 --- engines/sci/engine/seg_manager.cpp | 11 +++++++++++ 1 file changed, 11 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/seg_manager.cpp b/engines/sci/engine/seg_manager.cpp index 339920936f..ef2279e492 100644 --- a/engines/sci/engine/seg_manager.cpp +++ b/engines/sci/engine/seg_manager.cpp @@ -643,6 +643,14 @@ void SegManager::strncpy(reg_t dest, const char* src, size_t n) { } void SegManager::strncpy(reg_t dest, reg_t src, size_t n) { + if (src.isNull()) { + // Clear target string instead. + if (n > 0) + strcpy(dest, ""); + + return; // empty text + } + SegmentRef dest_r = dereference(dest); const SegmentRef src_r = dereference(src); if (!src_r.isValid()) { @@ -770,6 +778,9 @@ void SegManager::memcpy(byte *dest, reg_t src, size_t n) { } size_t SegManager::strlen(reg_t str) { + if (str.isNull()) + return 0; // empty text + SegmentRef str_r = dereference(str); if (!str_r.isValid()) { warning("Attempt to call strlen on invalid pointer %04x:%04x", PRINT_REG(str)); -- cgit v1.2.3 From 7fa26648283b1940f952c33251c27eb38d5b89e7 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 14:39:13 +0000 Subject: Some slight fixes so that Phantom/Dragon start again svn-id: r50598 --- engines/m4/globals.cpp | 4 +++- engines/m4/m4.cpp | 15 +++++++-------- engines/m4/mads_scene.cpp | 43 ++++++++++++++++++++++++++++++------------- 3 files changed, 40 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index b9039e3afd..fb95adf29f 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -528,7 +528,9 @@ void MadsObject::load(Common::SeekableReadStream *stream) { roomNumber = READ_LE_UINT16(&obj[2]); article = (MADSArticles)obj[4]; vocabCount = obj[5] & 0x7f; - assert(vocabCount <= 3); + // Phantom / Dragon + if (vocabCount > 3) + warning("MadsObject::load(), vocab cound > 3 (it's %d)", vocabCount); for (int i = 0; i < vocabCount; ++i) { vocabList[i].flags1 = obj[6 + i * 4]; diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index fc1caec883..f5c6d260a9 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -537,19 +537,18 @@ Common::Error MadsEngine::run() { //for (int i = 0; i < _globals->getMessagesSize(); i++) //printf("%s\n----------\n", _globals->loadMessage(i)); - if ((getGameType() == GType_RexNebular) || (getGameType() == GType_DragonSphere)) { + if (getGameType() == GType_RexNebular) { _scene = NULL; loadMenu(MAIN_MENU); - } else { + // Test code _scene = new MadsScene(this); - if (getGameType() == GType_DragonSphere) { - _scene->loadScene(FIRST_SCENE); - } else if (getGameType() == GType_Phantom) { - //_scene->loadScene(FIRST_SCENE); - _scene->loadScene(106); // a more interesting scene - } + startScene(FIRST_SCENE); + RGBList *_bgPalData; + _scene->loadBackground(FIRST_SCENE, &_bgPalData); + _palette->addRange(_bgPalData); + _scene->translate(_bgPalData); _scene->show(); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 73388a2325..f4581ed629 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -129,11 +129,13 @@ void MadsScene::loadScene(int sceneNumber) { // Add the scene if necessary to the list of scenes that have been visited _vm->globals()->addVisitedScene(sceneNumber); - // Secondary scene load routine - loadScene2("*I0.AA"); + if (_vm->getGameType() == GType_RexNebular) { + // Secondary scene load routine + loadScene2("*I0.AA"); - // Do any scene specific setup - _sceneLogic.enterScene(); + // Do any scene specific setup + _sceneLogic.enterScene(); + } // Purge resources _vm->res()->purge(); @@ -234,12 +236,14 @@ void MadsScene::leftClick(int x, int y) { } void MadsScene::rightClick(int x, int y) { - // ***DEBUG*** - sample dialog display - int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); - const char *msg = _madsVm->globals()->loadMessage(idx); - Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); - _vm->_viewManager->addView(dlg); - _vm->_viewManager->moveToFront(dlg); + if (_vm->getGameType() == GType_RexNebular) { + // ***DEBUG*** - sample dialog display + int idx = 3; //_madsVm->_globals->messageIndexOf(0x277a); + const char *msg = _madsVm->globals()->loadMessage(idx); + Dialog *dlg = new Dialog(_vm, msg, "TEST DIALOG"); + _vm->_viewManager->addView(dlg); + _vm->_viewManager->moveToFront(dlg); + } } void MadsScene::setAction(int action, int objectId) { @@ -338,7 +342,8 @@ void MadsScene::loadPlayerSprites(const char *prefix) { } } - error("Couldn't find player sprites"); + // Phantom/Dragon + warning("Couldn't find player sprites"); } enum boxSprites { @@ -646,8 +651,20 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su // Basic scene info Common::SeekableReadStream *stream = sceneInfo.getItemStream(0); - int resSceneId = stream->readUint16LE(); - assert(resSceneId == sceneNumber); + if (_vm->getGameType() == GType_RexNebular) { + int resSceneId = stream->readUint16LE(); + assert(resSceneId == sceneNumber); + } else { + char roomFilename[10]; + char roomFilenameExpected[10]; + sprintf(roomFilenameExpected, "*RM%d", sceneNumber); + + stream->read(roomFilename, 6); + roomFilename[6] = 0; + assert(!strcmp(roomFilename, roomFilenameExpected)); + } + + // TODO: The following is wrong for Phantom/Dragon artFileNum = stream->readUint16LE(); depthStyle = stream->readUint16LE(); width = stream->readUint16LE(); -- cgit v1.2.3 From c1aecd0b9b32efb3a90f653eb36102f18543b49e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 2 Jul 2010 15:58:09 +0000 Subject: SCI: change drawing of fonts, so that we never do triple pixel line duplications. sierra didn't do this, but it looks much better - "fixes" gk1, kq6 font rendering when running in hires svn-id: r50599 --- engines/sci/graphics/font.cpp | 4 ++-- engines/sci/graphics/screen.cpp | 21 +++++++++++++++++++++ engines/sci/graphics/screen.h | 1 + 3 files changed, 24 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index 91cf01c912..ce4c1fafb3 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -82,7 +82,7 @@ void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bo int charWidth = MIN(getCharWidth(chr), _screen->getWidth() - left); int charHeight = MIN(getCharHeight(chr), _screen->getHeight() - top); byte b = 0, mask = 0xFF; - int y = top; + int y = 0; byte *pIn = getCharData(chr); for (int i = 0; i < charHeight; i++, y++) { @@ -92,7 +92,7 @@ void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bo if ((done & 7) == 0) // fetching next data byte b = *(pIn++) & mask; if (b & 0x80) // if MSB is set - paint it - _screen->putPixel(left + done, y, 1, color, 0, 0); + _screen->putFontPixel(top, left + done, y, color); b = b << 1; } } diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index a314405eb1..1d3a4ea1f7 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -223,6 +223,27 @@ void GfxScreen::putPixel(int x, int y, byte drawMask, byte color, byte priority, _controlScreen[offset] = control; } +/** + * This is used to put font pixels onto the screen - we adjust differently, so that we won't + * do triple pixel lines in any case on upscaled hires. That way the font will not get distorted + * Sierra SCI didn't do this + */ +void GfxScreen::putFontPixel(int startingY, int x, int y, byte color) { + int offset = (startingY + y) * _width + x; + + _visualScreen[offset] = color; + if (!_upscaledHires) { + _displayScreen[offset] = color; + } else { + int displayOffset = (_upscaledMapping[startingY] + y * 2) * _displayWidth + x * 2; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + displayOffset += _displayWidth; + _displayScreen[displayOffset] = color; + _displayScreen[displayOffset + 1] = color; + } +} + /** * This will just change a pixel directly on displayscreen. It is supposed to be * only used on upscaled-Hires games where hires content needs to get drawn ONTO diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 113cf911a6..900c338bb2 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -83,6 +83,7 @@ public: byte getDrawingMask(byte color, byte prio, byte control); void putPixel(int x, int y, byte drawMask, byte color, byte prio, byte control); + void putFontPixel(int startingY, int x, int y, byte color); void putPixelOnDisplay(int x, int y, byte color); void drawLine(Common::Point startPoint, Common::Point endPoint, byte color, byte prio, byte control); void drawLine(int16 left, int16 top, int16 right, int16 bottom, byte color, byte prio, byte control) { -- cgit v1.2.3 From 5625c6d1ee7f270fa8d6e93b3862a3d8dd7514c0 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 2 Jul 2010 19:08:22 +0000 Subject: KYRA/PC98: fix sfx volume control svn-id: r50602 --- engines/kyra/sound_towns.cpp | 70 +++++++++++++++++++++++++++++++++----------- 1 file changed, 53 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index e50981c4c0..57ed3402c5 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1858,10 +1858,29 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) { _dataPtr = data; _totalLevel = 0x7F; - uint8 *src_b = _dataPtr; - int loop = 1; + uint8 *tmp = _dataPtr; + for (bool loop = true; loop; ) { + uint8 cmd = *tmp++; + if (cmd < 0xf0) { + tmp++; + } else if (cmd == 0xff) { + if (READ_LE_UINT16(tmp)) + _drv->_looping |= _idFlag; + else + loop = false; + } else if (cmd == 0xf6) { + // reset repeat section countdown + tmp[0] = tmp[1]; + tmp += 4; + } else { + tmp += _drv->_opnFxCmdLen[cmd - 240]; + } + } + + /*uint8 *src_b = _dataPtr; uint8 cmd = 0; - while (loop) { + + for (int loop = 1; loop; ) { if (loop == 1) { cmd = *src_b++; if (cmd < 0xf0) { @@ -1882,11 +1901,12 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) { src_b += _drv->_opnFxCmdLen[cmd - 240]; loop = 1; } else if (loop == 3) { + // reset repeat section countdown src_b[0] = src_b[1]; src_b += 4; loop = 1; } - } + }*/ } void TownsPC98_OpnChannel::processEvents() { @@ -2498,6 +2518,22 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { _dataPtr = data; _ssgTl = 0xff; _algorithm = 0x80; + + uint8 *tmp = _dataPtr; + for (bool loop = true; loop; ) { + uint8 cmd = *tmp++; + if (cmd < 0xf0) { + tmp++; + } else if (cmd == 0xff && !*tmp) { + loop = false; + } else if (cmd == 0xf6) { + // reset repeat section countdown + tmp[0] = tmp[1]; + tmp += 4; + } else { + tmp += _drv->_opnFxCmdLen[cmd - 240]; + } + } } TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, @@ -2750,15 +2786,15 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; else finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; - } - finOut /= 3; + if ((1 << ii) & _volMaskA) + finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; - if ((1 << i) & _volMaskA) - finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + if ((1 << ii) & _volMaskB) + finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + } - if ((1 << i) & _volMaskB) - finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + finOut /= 3; buffer[i << 1] += finOut; buffer[(i << 1) + 1] += finOut; @@ -3764,21 +3800,21 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { } void TownsPC98_OpnDriver::startSoundEffect() { - _updateSfxFlag = 0; + int volFlags = 0; for (int i = 0; i < 2; i++) { if (_sfxOffsets[i]) { _ssgChannels[i + 1]->protect(); _sfxChannels[i]->reset(); _sfxChannels[i]->loadData(_sfxData + _sfxOffsets[i]); _updateSfxFlag |= _sfxChannels[i]->_idFlag; + volFlags |= (_sfxChannels[i]->_idFlag << _numChan); + } else { + _ssgChannels[i + 1]->restore(); + _updateSfxFlag &= ~_sfxChannels[i]->_idFlag; } } - - int volFlags = 0; - for (int i = 0; i < (_numChan + _numSSG - 2); i++) - volFlags |= (1 << i); - setVolumeChannelMasks(volFlags, ~volFlags); - + + setVolumeChannelMasks(~volFlags, volFlags); _sfxData = 0; } -- cgit v1.2.3 From 022808fda6ac5419fd16fbd3d47dff16b812c50d Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 2 Jul 2010 19:47:14 +0000 Subject: KYRA/PC98: cleanup svn-id: r50603 --- engines/kyra/sound_towns.cpp | 38 ++++---------------------------------- 1 file changed, 4 insertions(+), 34 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 57ed3402c5..530a473fcc 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1498,7 +1498,7 @@ public: uint8 chanEnable() const { return _chanEnable; } private: - void updatesRegs(); + void updateRegs(); uint8 _updateRequestBuf[64]; int _updateRequest; @@ -1876,37 +1876,6 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) { tmp += _drv->_opnFxCmdLen[cmd - 240]; } } - - /*uint8 *src_b = _dataPtr; - uint8 cmd = 0; - - for (int loop = 1; loop; ) { - if (loop == 1) { - cmd = *src_b++; - if (cmd < 0xf0) { - src_b++; - loop = 1; - } else { - if (cmd == 0xff) { - loop = *src_b ? 2 : 0; - if (READ_LE_UINT16(src_b)) - _drv->_looping |= _idFlag; - } else if (cmd == 0xf6) { - loop = 3; - } else { - loop = 2; - } - } - } else if (loop == 2) { - src_b += _drv->_opnFxCmdLen[cmd - 240]; - loop = 1; - } else if (loop == 3) { - // reset repeat section countdown - src_b[0] = src_b[1]; - src_b += 4; - loop = 1; - } - }*/ } void TownsPC98_OpnChannel::processEvents() { @@ -2777,7 +2746,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { } } _pReslt = _evpTimer ^ _attack; - updatesRegs(); + updateRegs(); } int32 finOut = 0; @@ -2801,7 +2770,7 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { } } -void TownsPC98_OpnSquareSineSource::updatesRegs() { +void TownsPC98_OpnSquareSineSource::updateRegs() { for (int i = 0; i < _updateRequest;) { uint8 b = _updateRequestBuf[i++]; uint8 a = _updateRequestBuf[i++]; @@ -3801,6 +3770,7 @@ void TownsPC98_OpnDriver::setSfxTempo(uint16 tempo) { void TownsPC98_OpnDriver::startSoundEffect() { int volFlags = 0; + for (int i = 0; i < 2; i++) { if (_sfxOffsets[i]) { _ssgChannels[i + 1]->protect(); -- cgit v1.2.3 From a6e07f01bb7699162be879abae1d01ab6980f768 Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 2 Jul 2010 21:27:36 +0000 Subject: KYRA/PC98: fix long standing bug were certain sound effects would bring each other out of tune svn-id: r50604 --- engines/kyra/sound_towns.cpp | 44 ++++++++++++++++++++++++++++++++++++++++---- 1 file changed, 40 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index 530a473fcc..e8c8365f85 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1358,7 +1358,7 @@ public: void setOutputLevel(); virtual void fadeStep(); - void reset(); + virtual void reset(); const uint8 _idFlag; @@ -1435,13 +1435,14 @@ public: void protect(); void restore(); + virtual void reset(); void fadeStep(); protected: void setOutputLevel(uint8 lvl); - bool control_f0_setInstr(uint8 para); + bool control_f0_setPatch(uint8 para); bool control_f1_setTotalLevel(uint8 para); bool control_f4_setAlgorithm(uint8 para); bool control_f9_loadCustomPatch(uint8 para); @@ -1461,6 +1462,7 @@ public: ~TownsPC98_OpnSfxChannel() {} void loadData(uint8 *data); + void reset(); }; class TownsPC98_OpnChannelPCM : public TownsPC98_OpnChannel { @@ -2202,7 +2204,7 @@ void TownsPC98_OpnChannelSSG::init() { #define Control(x) &TownsPC98_OpnChannelSSG::control_##x static const ControlEventFunc ctrlEventsSSG[] = { - Control(f0_setInstr), + Control(f0_setPatch), Control(f1_setTotalLevel), Control(f2_setKeyOffTime), Control(f3_setFreqLSB), @@ -2396,6 +2398,23 @@ void TownsPC98_OpnChannelSSG::setOutputLevel(uint8 lvl) { _drv->writeReg(_part, 8 + _regOffset, _ssgTl); } +void TownsPC98_OpnChannelSSG::reset() { + TownsPC98_OpnChannel::reset(); + + // Unlike the original we restore the default patch data. This fixes a bug + // where certain sound effects would bring each other out of tune (e.g. the + // dragon's fire in Darm's house in Kyra 1 would sound different each time + // you triggered another sfx by dropping an item etc.) + uint8 i = (10 + _regOffset) << 4; + const uint8 *src = &_drv->_drvTables[156]; + _drv->_ssgPatches[i] = src[i]; + _drv->_ssgPatches[i + 3] = src[i + 3]; + _drv->_ssgPatches[i + 4] = src[i + 4]; + _drv->_ssgPatches[i + 6] = src[i + 6]; + _drv->_ssgPatches[i + 8] = src[i + 8]; + _drv->_ssgPatches[i + 12] = src[i + 12]; +} + void TownsPC98_OpnChannelSSG::fadeStep() { _totalLevel--; if ((int8)_totalLevel < 0) @@ -2403,7 +2422,7 @@ void TownsPC98_OpnChannelSSG::fadeStep() { setOutputLevel(_ssgStartLvl); } -bool TownsPC98_OpnChannelSSG::control_f0_setInstr(uint8 para) { +bool TownsPC98_OpnChannelSSG::control_f0_setPatch(uint8 para) { _instr = para << 4; para = (para >> 3) & 0x1e; if (para) @@ -2505,6 +2524,23 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { } } +void TownsPC98_OpnSfxChannel::reset() { + TownsPC98_OpnChannel::reset(); + + // Unlike the original we restore the default patch data. This fixes a bug + // where certain sound effects would bring each other out of tune (e.g. the + // dragon's fire in Darm's house in Kyra 1 would sound different each time + // you triggered another sfx by dropping an item etc.) + uint8 i = (13 + _regOffset) << 4; + const uint8 *src = &_drv->_drvTables[156]; + _drv->_ssgPatches[i] = src[i]; + _drv->_ssgPatches[i + 3] = src[i + 3]; + _drv->_ssgPatches[i + 4] = src[i + 4]; + _drv->_ssgPatches[i + 6] = src[i + 6]; + _drv->_ssgPatches[i + 8] = src[i + 8]; + _drv->_ssgPatches[i + 12] = src[i + 12]; +} + TownsPC98_OpnChannelPCM::TownsPC98_OpnChannelPCM(TownsPC98_OpnDriver *driver, uint8 regOffs, uint8 flgs, uint8 num, uint8 key, uint8 prt, uint8 id) : TownsPC98_OpnChannel(driver, regOffs, flgs, num, key, prt, id), controlEvents(0) { -- cgit v1.2.3 From 188f8d9a1199f60a1b0ca5a63b45e24813923d92 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 22:55:56 +0000 Subject: AGI: Fixed bug #3017905 - "AGI: GR - Crash on start". A free() was done on an already freed reference svn-id: r50606 --- engines/agi/loader_v3.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/agi/loader_v3.cpp b/engines/agi/loader_v3.cpp index 4ee35d73eb..f145140768 100644 --- a/engines/agi/loader_v3.cpp +++ b/engines/agi/loader_v3.cpp @@ -229,7 +229,7 @@ uint8 *AgiLoader_v3::loadVolRes(AgiDir *agid) { if (x[2] & 0x80) { // compressed pic data = _vm->_picture->convertV3Pic(compBuffer, agid->clen); - free(compBuffer); + // compBuffer has been freed inside convertV3Pic() } else if (agid->len == agid->clen) { // do not decompress data = compBuffer; -- cgit v1.2.3 From 4304a414ab6ab3a46c10ddcd89ff9070caca96d9 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Fri, 2 Jul 2010 23:12:17 +0000 Subject: AGI: Removed the deprecated (and confusing) getGameId() function inside the AgiEngine class, and fixed a related bug, too svn-id: r50607 --- engines/agi/agi.cpp | 7 ------- engines/agi/agi.h | 5 ----- engines/agi/view.cpp | 2 +- 3 files changed, 1 insertion(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/agi/agi.cpp b/engines/agi/agi.cpp index a39725a973..4a994b731a 100644 --- a/engines/agi/agi.cpp +++ b/engines/agi/agi.cpp @@ -505,13 +505,6 @@ AgiEngine::AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBas _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - const GameSettings *g; - - const char *gameid = ConfMan.get("gameid").c_str(); - for (g = agiSettings; g->gameid; ++g) - if (!scumm_stricmp(g->gameid, gameid)) - _gameId = g->id; - parseFeatures(); _rnd = new Common::RandomSource(); diff --git a/engines/agi/agi.h b/engines/agi/agi.h index 166470e6e4..507e7f7a11 100644 --- a/engines/agi/agi.h +++ b/engines/agi/agi.h @@ -792,8 +792,6 @@ public: }; class AgiEngine : public AgiBase { - int _gameId; - protected: // Engine APIs virtual Common::Error go(); @@ -806,9 +804,6 @@ protected: public: AgiEngine(OSystem *syst, const AGIGameDescription *gameDesc); virtual ~AgiEngine(); - int getGameId() { - return _gameId; - } Common::Error loadGameState(int slot); Common::Error saveGameState(int slot, const char *desc); diff --git a/engines/agi/view.cpp b/engines/agi/view.cpp index 03509e81f9..45244bb292 100644 --- a/engines/agi/view.cpp +++ b/engines/agi/view.cpp @@ -368,7 +368,7 @@ void AgiEngine::updateViewtable() { break; default: // for KQ4 - if (getVersion() == 0x3086 || getGameId() == GID_KQ4) + if (getVersion() == 0x3086 || getGameID() == GID_KQ4) loop = loopTable4[v->direction]; break; } -- cgit v1.2.3 From aefc42ab0e066b6cd2fa6eaab2471a908d7bb1fb Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Sat, 3 Jul 2010 00:06:54 +0000 Subject: KYRA/PC98 Audio: fix invalid mem access svn-id: r50608 --- engines/kyra/sound_towns.cpp | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index e8c8365f85..f6d71f8549 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -1866,9 +1866,10 @@ void TownsPC98_OpnChannel::loadData(uint8 *data) { if (cmd < 0xf0) { tmp++; } else if (cmd == 0xff) { - if (READ_LE_UINT16(tmp)) + if (READ_LE_UINT16(tmp)) { _drv->_looping |= _idFlag; - else + tmp += _drv->_opnFxCmdLen[cmd - 240]; + } else loop = false; } else if (cmd == 0xf6) { // reset repeat section countdown @@ -2512,7 +2513,7 @@ void TownsPC98_OpnSfxChannel::loadData(uint8 *data) { uint8 cmd = *tmp++; if (cmd < 0xf0) { tmp++; - } else if (cmd == 0xff && !*tmp) { + } else if (cmd == 0xff) { loop = false; } else if (cmd == 0xf6) { // reset repeat section countdown @@ -3080,7 +3081,7 @@ void TownsPC98_OpnCore::reset() { for (int i = 0; i < _numChan; i++) { for (int ii = 0; ii < 4; ii++) _chanInternal[i].opr[ii]->reset(); - memset(&_chanInternal[i].feedbuf, 0, 3); + memset(_chanInternal[i].feedbuf, 0, 3); _chanInternal[i].algorithm = 0; _chanInternal[i].frqTemp = 0; _chanInternal[i].enableLeft = _chanInternal[i].enableRight = true; -- cgit v1.2.3 From 8d26e7c2d26c0a7c6521631bf861f8613a307dce Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Sat, 3 Jul 2010 03:48:26 +0000 Subject: Dragon History tries uses compressed dubbing when available Timing of speaking is not fixed yet. svn-id: r50614 --- engines/draci/barchive.cpp | 5 ++--- engines/draci/draci.cpp | 37 +++++++++++++++++++++++++++++++++++-- engines/draci/sound.cpp | 20 ++++++++++++-------- 3 files changed, 49 insertions(+), 13 deletions(-) (limited to 'engines') diff --git a/engines/draci/barchive.cpp b/engines/draci/barchive.cpp index 2ed2a9b591..8f9e836ba3 100644 --- a/engines/draci/barchive.cpp +++ b/engines/draci/barchive.cpp @@ -283,8 +283,7 @@ BAFile *BArchive::loadFileBAR(uint i) { tmp ^= _files[i]._data[j]; } - debugC(3, kDraciArchiverDebugLevel, "Cached file %d from archive %s", - i, _path.c_str()); + debugC(2, kDraciArchiverDebugLevel, "Read %d bytes", _files[i]._length); assert(tmp == _files[i]._crc && "CRC checksum mismatch"); return _files + i; @@ -385,7 +384,7 @@ const BAFile *BArchive::getFile(uint i) { // Check if file has already been opened and return that if (_files[i]._data) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(2, kDraciArchiverDebugLevel, "Cached"); return _files + i; } diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index 202bf6d187..cd3920b30d 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -71,7 +71,7 @@ const char *dubbingPath = "CD.SAM"; const char *musicPathMask = "HUDBA%d.MID"; const uint kSoundsFrequency = 13000; -const uint kDubbingFrequency = 22000; +const uint kDubbingFrequency = 22050; DraciEngine::DraciEngine(OSystem *syst, const ADGameDescription *gameDesc) : Engine(syst) { @@ -105,6 +105,39 @@ bool DraciEngine::hasFeature(EngineFeature f) const { (f == kSupportsSavingDuringRuntime); } +static SoundArchive* openAnyPossibleDubbing() { + debugC(1, kDraciGeneralDebugLevel, "Trying to find original dubbing"); + LegacySoundArchive *legacy = new LegacySoundArchive(dubbingPath, kDubbingFrequency); + if (legacy->isOpen() && legacy->size()) { + debugC(1, kDraciGeneralDebugLevel, "Found original dubbing"); + return legacy; + } + delete legacy; + + // The original uncompressed dubbing cannot be found. Try to open the + // newer compressed version. + debugC(1, kDraciGeneralDebugLevel, "Trying to find compressed dubbing"); + ZipSoundArchive *zip = new ZipSoundArchive(); + + zip->openArchive("dub-raw.zzz", "buf", RAW80, kDubbingFrequency); + if (zip->isOpen() && zip->size()) return zip; +#ifdef USE_FLAC + zip->openArchive("dub-flac.zzz", "flac", FLAC); + if (zip->isOpen() && zip->size()) return zip; +#endif +#ifdef USE_VORBIS + zip->openArchive("dub-ogg.zzz", "ogg", OGG); + if (zip->isOpen() && zip->size()) return zip; +#endif +#ifdef USE_MAD + zip->openArchive("dub-mp3.zzz", "mp3", MP3); + if (zip->isOpen() && zip->size()) return zip; +#endif + + // Return an empty (but initialized) archive anyway. + return zip; +} + int DraciEngine::init() { // Initialize graphics using following: initGraphics(kScreenWidth, kScreenHeight, false); @@ -124,7 +157,7 @@ int DraciEngine::init() { _stringsArchive = new BArchive(stringsPath); _soundsArchive = new LegacySoundArchive(soundsPath, kSoundsFrequency); - _dubbingArchive = new LegacySoundArchive(dubbingPath, kDubbingFrequency); + _dubbingArchive = openAnyPossibleDubbing(); _sound = new Sound(_mixer); MidiDriver::DeviceHandle dev = MidiDriver::detectDevice(MDT_MIDI | MDT_ADLIB | MDT_PREFER_GM); diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index aa696832bb..5000ceac74 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -48,14 +48,14 @@ void LegacySoundArchive::openArchive(const char *path) { // Close previously opened archive (if any) closeArchive(); - debugCN(2, kDraciArchiverDebugLevel, "Loading samples %s: ", path); + debugCN(1, kDraciArchiverDebugLevel, "Loading samples %s: ", path); _f = new Common::File(); _f->open(path); if (_f->isOpen()) { - debugC(2, kDraciArchiverDebugLevel, "Success"); + debugC(1, kDraciArchiverDebugLevel, "Success"); } else { - debugC(2, kDraciArchiverDebugLevel, "Error"); + debugC(1, kDraciArchiverDebugLevel, "Error"); delete _f; _f = NULL; return; @@ -65,7 +65,7 @@ void LegacySoundArchive::openArchive(const char *path) { _path = path; // Read archive header - debugC(2, kDraciArchiverDebugLevel, "Loading header"); + debugC(1, kDraciArchiverDebugLevel, "Loading header"); uint totalLength = _f->readUint32LE(); const uint kMaxSamples = 4095; // The no-sound file is exactly 16K bytes long, so don't fail on short reads @@ -81,7 +81,7 @@ void LegacySoundArchive::openArchive(const char *path) { break; } if (_sampleCount > 0) { - debugC(2, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length", + debugC(1, kDraciArchiverDebugLevel, "Archive info: %d samples, %d total length", _sampleCount, totalLength); _samples = new SoundSample[_sampleCount]; for (uint i = 0; i < _sampleCount; ++i) { @@ -92,14 +92,14 @@ void LegacySoundArchive::openArchive(const char *path) { if (_samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length != totalLength && _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length - _samples[0]._offset != totalLength) { // WORKAROUND: the stored length is stored with the header for sounds and without the hader for dubbing. Crazy. - debugC(2, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d", + debugC(1, kDraciArchiverDebugLevel, "Broken sound archive: %d != %d", _samples[_sampleCount-1]._offset + _samples[_sampleCount-1]._length, totalLength); closeArchive(); return; } } else { - debugC(2, kDraciArchiverDebugLevel, "Archive info: empty"); + debugC(1, kDraciArchiverDebugLevel, "Archive info: empty"); } // Indicate that the archive has been successfully opened @@ -170,7 +170,7 @@ SoundSample *LegacySoundArchive::getSample(int i, uint freq) { _f->seek(_samples[i]._offset); _f->read(_samples[i]._data, _samples[i]._length); - debugC(3, kDraciArchiverDebugLevel, "Read sample %d from archive %s", + debugC(2, kDraciArchiverDebugLevel, "Read sample %d from archive %s", i, _path); } _samples[i]._frequency = freq ? freq : _defaultFreq; @@ -185,6 +185,7 @@ void ZipSoundArchive::openArchive(const char *path, const char *extension, Sound return; } + debugCN(1, kDraciArchiverDebugLevel, "Trying to open ZIP archive %s: ", path); _archive = Common::makeZipArchive(path); _path = path; _extension = extension; @@ -195,6 +196,9 @@ void ZipSoundArchive::openArchive(const char *path, const char *extension, Sound Common::ArchiveMemberList files; _archive->listMembers(files); _sampleCount = files.size(); + debugC(1, kDraciArchiverDebugLevel, "Capacity %d", _sampleCount); + } else { + debugC(1, kDraciArchiverDebugLevel, "Failed"); } } -- cgit v1.2.3 From 0fd3558986e7c0a0c08f3df18d6c8ce59da79110 Mon Sep 17 00:00:00 2001 From: Robert Å palek Date: Sat, 3 Jul 2010 05:05:28 +0000 Subject: Finish support of compressed dubbing Now even the length of a compressed stream is measured precisely and the dubbing sounds exactly like the original. svn-id: r50618 --- engines/draci/animation.cpp | 6 +++--- engines/draci/script.cpp | 4 ++-- engines/draci/sound.cpp | 20 +++++++++++--------- engines/draci/sound.h | 7 ++++--- 4 files changed, 20 insertions(+), 17 deletions(-) (limited to 'engines') diff --git a/engines/draci/animation.cpp b/engines/draci/animation.cpp index e46582487c..2bedbe1801 100644 --- a/engines/draci/animation.cpp +++ b/engines/draci/animation.cpp @@ -166,10 +166,10 @@ void Animation::drawFrame(Surface *surface) { const SoundSample *sample = _samples[_currentFrame]; if (_hasChangedFrame && sample) { + uint duration = _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false); debugC(3, kDraciSoundDebugLevel, - "Playing sample on animation %d, frame %d: %d+%d at %dHz", - _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency); - _vm->_sound->playSound(sample, Audio::Mixer::kMaxChannelVolume, false); + "Playing sample on animation %d, frame %d: %d+%d at %dHz: %dms", + _id, _currentFrame, sample->_offset, sample->_length, sample->_frequency, duration); } _hasChangedFrame = false; } diff --git a/engines/draci/script.cpp b/engines/draci/script.cpp index 0572eb7a81..7a6a68618d 100644 --- a/engines/draci/script.cpp +++ b/engines/draci/script.cpp @@ -729,10 +729,10 @@ void Script::talk(const Common::Array ¶ms) { // Speak the dubbing if possible uint dubbingDuration = 0; if (sample) { - dubbingDuration = (uint) (1000.0 * sample->_length / sample->_frequency + 500.0); + dubbingDuration = _vm->_sound->playVoice(sample); debugC(3, kDraciSoundDebugLevel, "Playing sentence %d: %d+%d with duration %dms", sentenceID, sample->_offset, sample->_length, dubbingDuration); - _vm->_sound->playVoice(sample); + dubbingDuration += 500; } // Record time diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index 5000ceac74..c9244d7eac 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -285,11 +285,11 @@ SndHandle *Sound::getHandle() { return NULL; // for compilers that don't support NORETURN } -void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, +uint Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, sndHandleType handleType, bool loop) { if (!buffer._stream && !buffer._data) { warning("Empty stream"); - return; + return 0; } // Create a new SeekableReadStream which will be automatically disposed // after the sample stops playing. Do not dispose the original @@ -335,22 +335,24 @@ void Sound::playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffe default: error("Unsupported compression format %d", static_cast (buffer._format)); delete stream; - return; + return 0; } + const uint length = reader->getLength().msecs(); const Audio::Mixer::SoundType soundType = (handleType == kVoiceHandle) ? Audio::Mixer::kSpeechSoundType : Audio::Mixer::kSFXSoundType; Audio::AudioStream *audio_stream = Audio::makeLoopingAudioStream(reader, loop ? 0 : 1); _mixer->playStream(soundType, handle, audio_stream, -1, volume); + return length; } -void Sound::playSound(const SoundSample *buffer, int volume, bool loop) { +uint Sound::playSound(const SoundSample *buffer, int volume, bool loop) { if (!buffer || _muteSound) - return; + return 0; SndHandle *handle = getHandle(); handle->type = kEffectHandle; - playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop); + return playSoundBuffer(&handle->handle, *buffer, 2 * volume, handle->type, loop); } void Sound::pauseSound() { @@ -374,13 +376,13 @@ void Sound::stopSound() { } } -void Sound::playVoice(const SoundSample *buffer) { +uint Sound::playVoice(const SoundSample *buffer) { if (!buffer || _muteVoice) - return; + return 0; SndHandle *handle = getHandle(); handle->type = kVoiceHandle; - playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false); + return playSoundBuffer(&handle->handle, *buffer, Audio::Mixer::kMaxChannelVolume, handle->type, false); } void Sound::pauseVoice() { diff --git a/engines/draci/sound.h b/engines/draci/sound.h index 2fade6de0b..6e9aae1b6e 100644 --- a/engines/draci/sound.h +++ b/engines/draci/sound.h @@ -189,13 +189,13 @@ public: Sound(Audio::Mixer *mixer); ~Sound() {} - void playSound(const SoundSample *buffer, int volume, bool loop); + uint playSound(const SoundSample *buffer, int volume, bool loop); void pauseSound(); void resumeSound(); void stopSound(); bool isMutedSound() const { return _muteSound; } - void playVoice(const SoundSample *buffer); + uint playVoice(const SoundSample *buffer); void pauseVoice(); void resumeVoice(); void stopVoice(); @@ -209,7 +209,8 @@ public: int talkSpeed() const { return _talkSpeed; } private: - void playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, + // Returns the length of the sound sample in miliseconds. + uint playSoundBuffer(Audio::SoundHandle *handle, const SoundSample &buffer, int volume, sndHandleType handleType, bool loop); SndHandle *getHandle(); -- cgit v1.2.3 From 42dfdea5df648cbf1a7778ac8848d752d0f144bb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 3 Jul 2010 06:55:10 +0000 Subject: SCI: added resetting of SoundCommandParser, so that error()s before that one got initialized wont crash svn-id: r50619 --- engines/sci/sci.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index e9e16c8262..91eeac3a21 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -187,6 +187,9 @@ Common::Error SciEngine::run() { } */ + // Reset, so that error()s before SoundCommandParser is initialized wont cause a crash + _soundCmd = NULL; + // Add the after market GM patches for the specified game, if they exist _resMan->addNewGMPatch(_gameId); _gameObj = _resMan->findGameObject(); -- cgit v1.2.3 From 99939109d75816e434f51479bafdc48a987fb008 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Jul 2010 11:50:42 +0000 Subject: Adding the beginnings of a player control class, as well as various changes to the other classes to support it svn-id: r50620 --- engines/m4/globals.h | 1 + engines/m4/m4.h | 2 + engines/m4/mads_logic.cpp | 73 +++++++++++++++-- engines/m4/mads_logic.h | 2 + engines/m4/mads_player.cpp | 193 +++++++++++++++++++++++++++++++++++++++++++++ engines/m4/mads_player.h | 66 ++++++++++++++++ engines/m4/mads_scene.cpp | 123 ++++++++++++++++++----------- engines/m4/mads_scene.h | 32 ++++---- engines/m4/mads_views.cpp | 8 +- engines/m4/mads_views.h | 2 +- engines/m4/module.mk | 1 + 11 files changed, 433 insertions(+), 70 deletions(-) create mode 100644 engines/m4/mads_player.cpp create mode 100644 engines/m4/mads_player.h (limited to 'engines') diff --git a/engines/m4/globals.h b/engines/m4/globals.h index 0217a96777..5ab1ccd9a6 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -252,6 +252,7 @@ public: MadsDialogType dialogType; int sceneNumber; int previousScene; + int16 _nextSceneId; uint16 actionNouns[3]; IntStorage _dataMap; diff --git a/engines/m4/m4.h b/engines/m4/m4.h index f5ddcc28be..3174c886d5 100644 --- a/engines/m4/m4.h +++ b/engines/m4/m4.h @@ -42,6 +42,7 @@ #include "m4/events.h" #include "m4/font.h" #include "m4/scene.h" +#include "m4/mads_player.h" #include "m4/mads_scene.h" #include "m4/m4_scene.h" #include "m4/actor.h" @@ -213,6 +214,7 @@ private: public: MadsConversation _converse; uint32 _currentTimer; + MadsPlayer _player; public: MadsEngine(OSystem *syst, const M4GameDescription *gameDesc); virtual ~MadsEngine(); diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 72c5fde40b..2e3198029b 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -54,7 +54,7 @@ void MadsSceneLogic::getSceneSpriteSet() { strcpy(prefix, ""); _madsVm->globals()->playerSpriteChanged = true; - _madsVm->scene()->loadPlayerSprites(prefix); + _madsVm->_player.loadSprites(prefix); // if ((_sceneNumber == 105) ((_sceneNumber == 109) && (word_84800 != 0))) // _madsVm->globals()->playerSpriteChanged = true; @@ -150,6 +150,59 @@ void MadsSceneLogic::lowRoomsEntrySound() { } } +void MadsSceneLogic::getPlayerSpritesPrefix() { + _madsVm->_sound->playSound(5); + + char oldName[80]; + strcpy(oldName, _madsVm->_player._spritesPrefix); + + if ((_madsVm->globals()->_nextSceneId <= 103) || (_madsVm->globals()->_nextSceneId == 111)) + strcpy(_madsVm->_player._spritesPrefix, (_madsVm->globals()->_globals[0] == SEX_FEMALE) ? "ROX" : "RXM"); + else if (_madsVm->globals()->_nextSceneId <= 110) + strcpy(_madsVm->_player._spritesPrefix, "RXSM"); + else if (_madsVm->globals()->_nextSceneId == 112) + strcpy(_madsVm->_player._spritesPrefix, ""); + + if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) + _madsVm->_player._spritesChanged = true; + + if ((_madsVm->globals()->_nextSceneId == 105) || + ((_madsVm->globals()->_nextSceneId == 109) && (_madsVm->globals()->_globals[15] != 0))) { + // TODO: unknown flag setting + _madsVm->_player._spritesChanged = true; + } + + _madsVm->_palette->setEntry(16, 40, 255, 255); + _madsVm->_palette->setEntry(17, 40, 180, 180); + +} + +void MadsSceneLogic::getPlayerSpritesPrefix2() { + _madsVm->_sound->playSound(5); + + char oldName[80]; + strcpy(oldName, _madsVm->_player._spritesPrefix); + + if ((_madsVm->globals()->_nextSceneId == 213) || (_madsVm->globals()->_nextSceneId == 216)) + strcpy(_madsVm->_player._spritesPrefix, ""); + else if (_madsVm->globals()->_globals[0] == SEX_MALE) + strcpy(_madsVm->_player._spritesPrefix, "RXM"); + else + strcpy(_madsVm->_player._spritesPrefix, "ROX"); + + // TODO: unknown flag setting for next scene Id > 212 + + if (strcmp(oldName, _madsVm->_player._spritesPrefix) != 0) + _madsVm->_player._spritesChanged = true; + +/* if ((_madsVm->globals()->_nextSceneId == 203) && (_madsVm->globals()->_nextSceneId == 204) && + (_madsVm->globals()->_globals[0x22] == 0)) + // TODO: unknown flag set +*/ + _madsVm->_palette->setEntry(16, 40, 255, 255); + _madsVm->_palette->setEntry(17, 40, 180, 180); +} + /*--------------------------------------------------------------------------*/ @@ -175,7 +228,9 @@ void MadsSceneLogic::setupScene() { // sub_1e754(animName, 3); if ((_sceneNumber >= 101) && (_sceneNumber <= 112)) - getSceneSpriteSet(); + getPlayerSpritesPrefix(); + else + getPlayerSpritesPrefix2(); getAnimName(); } @@ -212,15 +267,15 @@ void MadsSceneLogic::enterScene() { if (_madsVm->globals()->previousScene != -1) _madsVm->globals()->_globals[10] = 0; if (_madsVm->globals()->previousScene != -2) { - _madsVm->scene()->getSceneResources().playerPos = Common::Point(100, 152); + _madsVm->_player._playerPos = Common::Point(100, 152); } if ((_madsVm->globals()->previousScene == 112) || ((_madsVm->globals()->previousScene != -2) && (_spriteIndexes[29] != 0))) { // Returning from probe cutscene? _spriteIndexes[29] = -1; - _madsVm->scene()->getSceneResources().playerPos = Common::Point(161, 123); - _madsVm->scene()->getSceneResources().playerDir = 9; + _madsVm->_player._playerPos = Common::Point(161, 123); + _madsVm->_player._direction = 9; // TODO: Extra flags setting _spriteIndexes[25] = startCycledSpriteSequence(_spriteIndexes[10], 0, 3, 0, 0, 0); @@ -241,8 +296,9 @@ void MadsSceneLogic::enterScene() { const char *animName = MADSResourceManager::getResourceName('S', 'e', EXTTYPE_AA, NULL, -1); _madsVm->scene()->loadAnimation(animName, 0x47); - _madsVm->scene()->getSceneResources().playerPos = Common::Point(68, 140); - _madsVm->scene()->getSceneResources().playerDir = 4; + _madsVm->_player._playerPos = Common::Point(68, 140); + _madsVm->_player._direction = 4; + _madsVm->_player._visible = false; dataMap()[0x56FC] = 0; dataMap()[0x5482] = 0; @@ -258,6 +314,9 @@ void MadsSceneLogic::doAction() { } void MadsSceneLogic::sceneStep() { + // TODO: Sound handling + + // Wake up message sequence Animation *anim = _madsVm->scene()->activeAnimation(); if (anim) { diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h index 299464f62b..3c6cb8edf1 100644 --- a/engines/m4/mads_logic.h +++ b/engines/m4/mads_logic.h @@ -42,6 +42,8 @@ private: uint16 startSpriteSequence3(uint16 srcSpriteIdx, int v0, int numTicks, int triggerCountdown, int timeoutTicks, int extraTicks); void activateHotspot(int idx, bool active); void lowRoomsEntrySound(); + void getPlayerSpritesPrefix(); + void getPlayerSpritesPrefix2(); private: int _sceneNumber; int16 _spriteIndexes[50]; diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp new file mode 100644 index 0000000000..53ee857093 --- /dev/null +++ b/engines/m4/mads_player.cpp @@ -0,0 +1,193 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#include "m4/m4.h" +#include "m4/mads_player.h" +#include "m4/mads_scene.h" + +namespace M4 { + +MadsPlayer::MadsPlayer() { + _playerPos = Common::Point(160, 78); + _direction = 0; + _direction2 = 0; + _forceRefresh = true; + _visible = true; + _priorVisible = false; + _visible3 = false; + _yScale = 0; + _moving = false; + _spriteListIdx = 0; + _spriteListIdx2 = 0; + _spritesChanged = true; + _currentScale = 0; + strcpy(_spritesPrefix, ""); + for (int idx = 0; idx < 8; ++idx) + _spriteSetIndexes[idx] = 0; + _frameNum = 0; + _frameOffset = 0; +} + +/** + * Loads the sprite set for the player + */ +bool MadsPlayer::loadSprites(const char *prefix) { + const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; + char setName[80]; + bool result = true; + + if (prefix) + strcpy(_spritesPrefix, prefix); + + _spriteSetCount = 0; + int prefixLen = strlen(_spritesPrefix); + + if (prefixLen == 0) { + // No player sprites at at all + for (int idx = 0; idx < 8; ++idx) + _spriteSetIndexes[idx] = 0; + } else { + strcpy(setName, "*"); + strcat(setName, _spritesPrefix); + strcat(setName, "_0.SS"); + + char *digitP = strchr(setName, '_') + 1; + + for (int idx = 0; idx < 8; ++idx) { + *digitP = suffixList[idx]; + _spriteSetIndexes[idx] = -1; + + int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true); + if (setIndex < 0) { + if (idx < 7) + break; + _spriteSetIndexes[idx] = 0; + } else { + ++_spriteSetCount; + } + + if (idx == 0) + _spriteListIdx = setIndex; + } + + result = 0; + // TODO: Unknown flag + _spritesChanged = false; + } + + return result; +} + +/** + * Called each frame to update the display of the player + */ +void MadsPlayer::update() { + if (_forceRefresh || (_visible != _priorVisible)) { + // If there's an existing player sprite visible, flag it for expiry + int slotIndex = getSpriteSlot(); + if (slotIndex >= 0) + _madsVm->scene()->_spriteSlots[slotIndex].spriteType = EXPIRED_SPRITE; + + // Figure out the depth for the sprite + int newDepth = 1; + int yp = MIN(_playerPos.y, (int16)155); + + for (int idx = 1; idx < 15; ++idx) { + if (_madsVm->scene()->getSceneResources().depthTable[newDepth] >= yp) + newDepth = idx + 1; + } + _currentDepth = newDepth; + + // Get the scale + int newScale = getScale(_playerPos.y); + _currentScale = MIN(newScale, 100); + + if (_visible) { + // Player sprite needs to be rendered + MadsSpriteSlot slot; + slot.spriteType = FOREGROUND_SPRITE; + slot.seqIndex = PLAYER_SEQ_INDEX; + slot.spriteListIndex = _spriteListIdx + _spriteListIdx2; + slot.frameNumber = _frameOffset + _frameNum; + slot.xp = _playerPos.x; + slot.yp = _playerPos.y + (_yScale * newScale) / 100; + slot.depth = newDepth; + slot.scale = newScale; + + if (slotIndex >= 0) { + // Check if the existing player slot has the same details, and can be re-used + MadsSpriteSlot &s2 = _madsVm->scene()->_spriteSlots[slotIndex]; + bool equal = (s2.seqIndex == slot.seqIndex) && (s2.spriteListIndex == slot.spriteListIndex) + && (s2.frameNumber == slot.frameNumber) && (s2.xp == slot.xp) && (s2.yp == slot.yp) + && (s2.depth == slot.depth) && (s2.scale == slot.scale); + + if (equal) + // Undo the prior expiry of the player sprite + slot.spriteType = SPRITE_ZERO; + else + slotIndex = -1; + } + + if (slotIndex < 0) { + // New slot needed, so allocate one and copy the slot data + slotIndex = _madsVm->scene()->_spriteSlots.getIndex(); + _madsVm->scene()->_spriteSlots[slotIndex] = slot; + } + + // TODO: Meaning of word_844c0 block + + } + } + + _visible3 = _priorVisible = _visible; + _forceRefresh = false; +} + +void MadsPlayer::idle() { + +} + +int MadsPlayer::getScale(int yp) { + MadsSceneResources &r = _madsVm->scene()->getSceneResources(); + + int scale = (r.bandsRange() == 0) ? r._maxScale : (yp - r._yBandsStart) * r.scaleRange() / r.bandsRange() + + r._minScale; + + return MIN(scale, 100); +} + +/** + * Scans through the scene's sprite slot list to find any sprite displaying the player + */ +int MadsPlayer::getSpriteSlot() { + MadsSpriteSlots &slots = _madsVm->scene()->_spriteSlots; + for (int i = 0; i < slots.startIndex; ++i) { + if ((slots[i].seqIndex == PLAYER_SEQ_INDEX) && (slots[i].spriteType >= SPRITE_ZERO)) + return i; + } + return -1; +} + +} // End of namespace M4 diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h new file mode 100644 index 0000000000..c84c1d0c60 --- /dev/null +++ b/engines/m4/mads_player.h @@ -0,0 +1,66 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + * $URL$ + * $Id$ + * + */ + +#ifndef M4_MADS_PLAYER_H +#define M4_MADS_PLAYER_H + +#include "common/scummsys.h" + +namespace M4 { + +#define PLAYER_SEQ_INDEX -2 + +class MadsPlayer { +private: + int getScale(int yp); + int getSpriteSlot(); +public: + char _spritesPrefix[16]; + int _spriteSetCount; + int _spriteSetIndexes[8]; + Common::Point _playerPos; + Common::Point _destPos; + int16 _direction, _direction2; + bool _visible, _priorVisible; + bool _visible3; + bool _forceRefresh; + int16 _currentScale; + int16 _yScale; + int16 _currentDepth; + int16 _spriteListIdx, _spriteListIdx2; + bool _spritesChanged; + int16 _frameOffset, _frameNum; + bool _moving; +public: + MadsPlayer(); + + bool loadSprites(const char *prefix); + void update(); + void idle(); +}; + +} // End of namespace M4 + +#endif diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index f4581ed629..c34216aa34 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -67,8 +67,10 @@ MadsScene::~MadsScene() { /** * Secondary scene loading code */ -void MadsScene::loadScene2(const char *aaName) { +void MadsScene::loadScene2(const char *aaName, int sceneNumber) { // TODO: Completely finish + _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber; + _madsVm->globals()->sceneNumber = sceneNumber; _spriteSlots.clear(); _sequenceList.clear(); @@ -115,27 +117,41 @@ void MadsScene::loadScene(int sceneNumber) { // Handle common scene setting Scene::loadScene(sceneNumber); - - _madsVm->globals()->previousScene = _madsVm->globals()->sceneNumber; - _madsVm->globals()->sceneNumber = sceneNumber; + _madsVm->globals()->_nextSceneId = sceneNumber; // Existing ScummVM code that needs to be eventually replaced with MADS code loadSceneTemporary(); + _madsVm->_player._spritesChanged = true; + _madsVm->globals()->clearQuotes(); + _dynamicHotspots.reset(); + // Signal the script engine what scene is to be active _sceneLogic.selectScene(sceneNumber); - _sceneLogic.setupScene(); // Add the scene if necessary to the list of scenes that have been visited _vm->globals()->addVisitedScene(sceneNumber); - if (_vm->getGameType() == GType_RexNebular) { + if (_vm->getGameType() == GType_RexNebular) + _sceneLogic.setupScene(); + + // TODO: Unknown code + + // Secondary scene load routine + if (_vm->getGameType() == GType_RexNebular) // Secondary scene load routine - loadScene2("*I0.AA"); + loadScene2("*I0.AA", sceneNumber); - // Do any scene specific setup + _madsVm->_player.loadSprites(NULL); + + // Do any scene specific setup + if (_vm->getGameType() == GType_RexNebular) _sceneLogic.enterScene(); - } + + // Miscellaneous player setup + _madsVm->_player._destPos = _madsVm->_player._destPos; + _madsVm->_player._direction2 = _madsVm->_player._direction; + _madsVm->_player.idle(); // Purge resources _vm->res()->purge(); @@ -300,6 +316,8 @@ void MadsScene::update() { } void MadsScene::updateState() { + _madsVm->_player.update(); + _sceneLogic.sceneStep(); if ((_activeAnimation) && !_abortTimers) { @@ -311,8 +329,36 @@ void MadsScene::updateState() { } MadsView::update(); + + // Remove the animation if it's been completed + if ((_activeAnimation) && ((MadsAnimation *)_activeAnimation)->freeFlag()) + freeAnimation(); +} + +/** + * Does extra work at cleaning up the animation, and then deletes it + */ +void MadsScene::freeAnimation() { + if (!_activeAnimation) + return; + + MadsAnimation *anim = (MadsAnimation *)_activeAnimation; + if (anim->freeFlag()) { + _madsVm->scene()->_spriteSlots.clear(); + _madsVm->scene()->_spriteSlots.fullRefresh(); + _madsVm->scene()->_sequenceList.scan(); + } + + if (_madsVm->_player._visible) { + _madsVm->_player._forceRefresh = true; + _madsVm->_player.update(); + } + + delete _activeAnimation; + _activeAnimation = NULL; } + int MadsScene::loadSceneSpriteSet(const char *setName) { char resName[100]; strcpy(resName, setName); @@ -324,28 +370,6 @@ int MadsScene::loadSceneSpriteSet(const char *setName) { return _spriteSlots.addSprites(resName); } -void MadsScene::loadPlayerSprites(const char *prefix) { - const char suffixList[8] = { '8', '9', '6', '3', '2', '7', '4', '1' }; - char setName[80]; - - strcpy(setName, "*"); - strcat(setName, prefix); - strcat(setName, "_0.SS"); - char *digitP = strchr(setName, '_') + 1; - - for (int idx = 0; idx < 8; ++idx) { - *digitP = suffixList[idx]; - - if (_vm->res()->resourceExists(setName)) { - loadSceneSpriteSet(setName); - return; - } - } - - // Phantom/Dragon - warning("Couldn't find player sprites"); -} - enum boxSprites { topLeft = 0, topRight = 1, @@ -665,22 +689,27 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su } // TODO: The following is wrong for Phantom/Dragon - artFileNum = stream->readUint16LE(); - depthStyle = stream->readUint16LE(); - width = stream->readUint16LE(); - height = stream->readUint16LE(); + _artFileNum = stream->readUint16LE(); + _depthStyle = stream->readUint16LE(); + _width = stream->readUint16LE(); + _height = stream->readUint16LE(); stream->skip(24); int objectCount = stream->readUint16LE(); - - stream->skip(40); + _yBandsEnd = stream->readUint16LE(); + _yBandsStart = stream->readUint16LE(); + _maxScale = stream->readSint16LE(); + _minScale = stream->readSint16LE(); + for (int i = 0; i < DEPTH_BANDS_SIZE; ++i) + _depthBands[i] = stream->readUint16LE(); + stream->skip(2); // Load in any scene objects for (int i = 0; i < objectCount; ++i) { MadsObject rec; rec.load(stream); - objects.push_back(rec); + _objects.push_back(rec); } for (int i = 0; i < 20 - objectCount; ++i) stream->skip(48); @@ -690,7 +719,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su for (int i = 0; i < setCount; ++i) { char buffer2[64]; Common::String s(buffer2, 64); - setNames.push_back(s); + _setNames.push_back(s); } delete stream; @@ -698,16 +727,16 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su // Initialise a copy of the surfaces if they weren't provided bool dsFlag = false, ssFlag = false; if (!surface) { - surface = new M4Surface(width, height); + surface = new M4Surface(_width, _height); ssFlag = true; - } else if ((width != surface->width()) || (height != surface->height())) - surface->setSize(width, height); + } else if ((_width != surface->width()) || (_height != surface->height())) + surface->setSize(_width, _height); if (!depthSurface) { - depthSurface = new M4Surface(width, height); + depthSurface = new M4Surface(_width, _height); dsFlag = true; - } else if ((width != depthSurface->width()) || (height != depthSurface->height())) - depthSurface->setSize(width, height); + } else if ((_width != depthSurface->width()) || (_height != depthSurface->height())) + depthSurface->setSize(_width, _height); // For Rex Nebular, read in the scene's compressed walk surface information @@ -724,7 +753,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su // Run length encoded depth data while ((runLength = *srcP++) != 0) { - if (depthStyle == 2) { + if (_depthStyle == 2) { // 2-bit depth pixels byte byteVal = *srcP++; for (int byteCtr = 0; byteCtr < runLength; ++byteCtr) { @@ -746,7 +775,7 @@ void MadsSceneResources::load(int sceneNumber, const char *resName, int v0, M4Su _vm->_resourceManager->toss(sceneName); // Load the surface artwork - surface->loadBackground(artFileNum); + surface->loadBackground(_artFileNum); // Final cleanup if (ssFlag) diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index c5fe6f01cd..66b50d809f 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -35,22 +35,26 @@ namespace M4 { #define INTERFACE_HEIGHT 106 class MadsInterfaceView; +#define DEPTH_BANDS_SIZE 15 + class MadsSceneResources: public SceneResources { public: - int sceneId; - int artFileNum; - int depthStyle; - int width; - int height; - Common::Array objects; - Common::Array setNames; - - Common::Point playerPos; - int playerDir; - - MadsSceneResources() { playerDir = 0; } + int _sceneId; + int _artFileNum; + int _depthStyle; + int _width; + int _height; + Common::Array _objects; + Common::Array _setNames; + int _yBandsStart, _yBandsEnd; + int _maxScale, _minScale; + int _depthBands[DEPTH_BANDS_SIZE]; + + MadsSceneResources() {} ~MadsSceneResources() {} void load(int sceneId, const char *resName, int v0, M4Surface *depthSurface, M4Surface *surface); + int bandsRange() const { return _yBandsEnd - _yBandsStart; } + int scaleRange() const { return _maxScale - _minScale; } }; enum MadsActionMode {ACTMODE_NONE = 0, ACTMODE_VERB = 1, ACTMODE_OBJECT = 3, ACTMODE_TALK = 6}; @@ -99,7 +103,7 @@ private: SpriteAsset *_playerSprites; void drawElements(); - void loadScene2(const char *aaName); + void loadScene2(const char *aaName, int sceneNumber); void loadSceneTemporary(); void loadSceneHotspots(int sceneNumber); void clearAction(); @@ -125,10 +129,10 @@ public: virtual void updateState(); int loadSceneSpriteSet(const char *setName); - void loadPlayerSprites(const char *prefix); void showMADSV2TextBox(char *text, int x, int y, char *faceName); void loadAnimation(const Common::String &animName, int v0); Animation *activeAnimation() const { return _activeAnimation; } + void freeAnimation(); MadsInterfaceView *getInterface() { return (MadsInterfaceView *)_interfaceSurface; } MadsSceneResources &getSceneResources() { return _sceneResources; } diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 21ea3a75cb..9241774d16 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -86,7 +86,13 @@ int MadsSpriteSlots::getIndex() { return startIndex++; } -int MadsSpriteSlots::addSprites(const char *resName) { +int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors) { + // If errors are suppressed, first check if the resource exists + if (suppressErrors) { + if (!_vm->res()->resourceExists(resName)) + return -1; + } + // Get the sprite set Common::SeekableReadStream *data = _vm->res()->get(resName); SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName); diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index e3344bc8a4..38c7ed0712 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -92,7 +92,7 @@ public: } int getIndex(); - int addSprites(const char *resName); + int addSprites(const char *resName, bool suppressErrors = false); void deleteSprites(int listIndex); void clear(); void deleteTimer(int seqIndex); diff --git a/engines/m4/module.mk b/engines/m4/module.mk index 1b08ea2188..f60757ba3b 100644 --- a/engines/m4/module.mk +++ b/engines/m4/module.mk @@ -22,6 +22,7 @@ MODULE_OBJS = \ mads_anim.o \ mads_logic.o \ mads_menus.o \ + mads_player.o \ mads_scene.o \ mads_views.o \ midi.o \ -- cgit v1.2.3 From 6b152e803967770d3419642b07fbf3a27333e865 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 3 Jul 2010 12:33:49 +0000 Subject: SCI: fixing #define SIGFOR_ALL, so that amiga games work again :P svn-id: r50621 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 47f7ac3bc8..1fd80d2cf7 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -230,7 +230,7 @@ struct SciKernelMapEntry { #define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 #define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE -#define SIGFOR_ALL 0x4f +#define SIGFOR_ALL 0x3f #define SIGFOR_DOS 1 << 0 #define SIGFOR_PC98 1 << 1 #define SIGFOR_WIN 1 << 2 -- cgit v1.2.3 From 88d1155c5e0b265c39466536f572a8aebfef8259 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sat, 3 Jul 2010 12:49:42 +0000 Subject: Implemented necessary logic for the abort timer/action code, which allows the player manager to be correctly activated when the 'getting up' animation finishes svn-id: r50622 --- engines/m4/mads_logic.cpp | 23 +++++++++++++++++++++-- engines/m4/mads_scene.cpp | 23 +++++++++++++++++++++-- engines/m4/mads_scene.h | 2 +- 3 files changed, 43 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 2e3198029b..c90fb11c11 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -251,7 +251,7 @@ void MadsSceneLogic::enterScene() { _spriteIndexes[16] = startCycledSpriteSequence(_spriteIndexes[1], 0, 4, 0, 1, 0); _spriteIndexes[17] = startCycledSpriteSequence(_spriteIndexes[2], 0, 4, 0, 1, 0); -// _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70); + _madsVm->scene()->_sequenceList.addSubEntry(_spriteIndexes[17], SM_FRAME_INDEX, 7, 70); _spriteIndexes[18] = startReversibleSpriteSequence(_spriteIndexes[3], 0, 10, 0, 0, 60); _spriteIndexes[19] = startCycledSpriteSequence(_spriteIndexes[4], 0, 5, 0, 1, 0); @@ -294,7 +294,7 @@ void MadsSceneLogic::enterScene() { if (_madsVm->globals()->_globals[10]) { const char *animName = MADSResourceManager::getResourceName('S', 'e', EXTTYPE_AA, NULL, -1); - _madsVm->scene()->loadAnimation(animName, 0x47); + _madsVm->scene()->loadAnimation(animName, 71); _madsVm->_player._playerPos = Common::Point(68, 140); _madsVm->_player._direction = 4; @@ -316,6 +316,25 @@ void MadsSceneLogic::doAction() { void MadsSceneLogic::sceneStep() { // TODO: Sound handling + switch (_madsVm->scene()->_abortTimers) { + case 70: + _madsVm->_sound->playSound(9); + break; + case 71: + _madsVm->globals()->_globals[10] = 0; + _madsVm->_player._visible = true; + dataMap()[0x56FC] = 0; + + _madsVm->scene()->_newTimeout = _madsVm->_currentTimer - _madsVm->scene()->_ticksAmount; + break; + case 72: + case 73: + // TODO: Method that should be scripted + break; + + default: + break; + } // Wake up message sequence Animation *anim = _madsVm->scene()->activeAnimation(); diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index c34216aa34..d22ca02475 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -144,6 +144,21 @@ void MadsScene::loadScene(int sceneNumber) { _madsVm->_player.loadSprites(NULL); + switch (_madsVm->globals()->_config.screenFades) { + case 0: + _abortTimers2 = 2; + break; + case 2: + _abortTimers2 = 21; + break; + default: + _abortTimers2 = 20; + break; + } + _abortTimers = 0; + _abortTimersMode2 = ABORTMODE_1; + + // Do any scene specific setup if (_vm->getGameType() == GType_RexNebular) _sceneLogic.enterScene(); @@ -318,8 +333,12 @@ void MadsScene::update() { void MadsScene::updateState() { _madsVm->_player.update(); + // Step through the scene _sceneLogic.sceneStep(); + if (_abortTimersMode == ABORTMODE_1) + _abortTimers = 0; + if ((_activeAnimation) && !_abortTimers) { _activeAnimation->update(); if (((MadsAnimation *) _activeAnimation)->freeFlag()) { @@ -468,12 +487,12 @@ void MadsScene::showMADSV2TextBox(char *text, int x, int y, char *faceName) { boxSprites->getFrame(bottomRight)->copyTo(_backgroundSurface, curX, curY + 1); } -void MadsScene::loadAnimation(const Common::String &animName, int v0) { +void MadsScene::loadAnimation(const Common::String &animName, int abortTimers) { if (_activeAnimation) error("Multiple active animations are not allowed"); MadsAnimation *anim = new MadsAnimation(_vm, this); - anim->load(animName.c_str(), 0); + anim->load(animName.c_str(), abortTimers); _activeAnimation = anim; } diff --git a/engines/m4/mads_scene.h b/engines/m4/mads_scene.h index 66b50d809f..e671dfb194 100644 --- a/engines/m4/mads_scene.h +++ b/engines/m4/mads_scene.h @@ -130,7 +130,7 @@ public: int loadSceneSpriteSet(const char *setName); void showMADSV2TextBox(char *text, int x, int y, char *faceName); - void loadAnimation(const Common::String &animName, int v0); + void loadAnimation(const Common::String &animName, int abortTimers); Animation *activeAnimation() const { return _activeAnimation; } void freeAnimation(); -- cgit v1.2.3 From 5872f5bb1fac5a8d4b8ddecf777e22ca23ecca39 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 3 Jul 2010 18:44:44 +0000 Subject: SCI: adding support to identify uninitialized values, when doing debug output for kernel signatures svn-id: r50626 --- engines/sci/engine/kernel.cpp | 18 +++++++++++------- engines/sci/engine/kernel.h | 17 +++++++++-------- 2 files changed, 20 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 1fd80d2cf7..fb2c60cdb6 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -685,6 +685,9 @@ int Kernel::findRegType(reg_t reg) { if (!reg.segment) return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL; + if (reg.segment == 0xFFFF) + return KSIG_UNINITIALIZED; + // Otherwise it's an object SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); if (!mobj) @@ -728,13 +731,14 @@ struct SignatureDebugType { }; static const SignatureDebugType signatureDebugTypeList[] = { - { KSIG_NULL, "null" }, - { KSIG_ARITHMETIC, "value" }, - { KSIG_OBJECT, "object" }, - { KSIG_REF, "reference" }, - { KSIG_LIST, "list" }, - { KSIG_NODE, "node" }, - { 0, NULL } + { KSIG_NULL, "null" }, + { KSIG_ARITHMETIC, "value" }, + { KSIG_UNINITIALIZED, "uninitialized" }, + { KSIG_OBJECT, "object" }, + { KSIG_REF, "reference" }, + { KSIG_LIST, "list" }, + { KSIG_NODE, "node" }, + { 0, NULL } }; static void kernelSignatureDebugType(const char type) { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index cb66aa9f4d..9b4a11f132 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -99,14 +99,15 @@ struct SelectorCache; // from selector.h // Compiled signatures enum { - KSIG_LIST = 0x01, - KSIG_NODE = 0x02, - KSIG_OBJECT = 0x04, - KSIG_REF = 0x08, - KSIG_ARITHMETIC = 0x10, - KSIG_NULL = 0x40, - KSIG_ANY = 0x5f, - KSIG_ELLIPSIS = 0x80 + KSIG_LIST = 0x01, + KSIG_NODE = 0x02, + KSIG_OBJECT = 0x04, + KSIG_REF = 0x08, + KSIG_ARITHMETIC = 0x10, + KSIG_UNINITIALIZED = 0x20, + KSIG_NULL = 0x40, + KSIG_ANY = 0x5f, + KSIG_ELLIPSIS = 0x80 }; // ---------------------------------------------------------------------------- -- cgit v1.2.3 From 10e7581fe1a281f69875a6d76c9c1bf5aafa939c Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Jul 2010 00:38:16 +0000 Subject: Added support for horizontally flipped foreground sprites, which are indicated by setting the high bit of frame numbers svn-id: r50638 --- engines/m4/graphics.cpp | 24 ++++++++++++++++++++++++ engines/m4/graphics.h | 2 ++ engines/m4/mads_views.cpp | 24 ++++++++++++++++++------ 3 files changed, 44 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/m4/graphics.cpp b/engines/m4/graphics.cpp index 107bcbc6f9..c10ea6c9f6 100644 --- a/engines/m4/graphics.cpp +++ b/engines/m4/graphics.cpp @@ -65,6 +65,15 @@ void RGBList::setRange(int start, int count, const RGB8 *src) { Common::copy(&src[0], &src[count], &_data[start]); } +/** + * Creates a duplicate of the given rgb list + */ +RGBList *RGBList::clone() const { + RGBList *dest = new RGBList(_size, _data, false); + _madsVm->_palette->addRange(dest); + return dest; +} + //-------------------------------------------------------------------------- #define VGA_COLOR_TRANS(x) (x == 0x3f ? 255 : x << 2) @@ -931,6 +940,21 @@ void M4Surface::translate(RGBList *list, bool isTransparent) { freeData(); } +M4Surface *M4Surface::flipHorizontal() const { + M4Surface *dest = new M4Surface(width(), height()); + dest->_rgbList = (this->_rgbList == NULL) ? NULL : this->_rgbList->clone(); + + byte *destP = dest->getBasePtr(); + + for (int y = 0; y < height(); ++y) { + const byte *srcP = getBasePtr(width() - 1, y); + for (int x = 0; x < width(); ++x) + *destP++ = *srcP--; + } + + return dest; +} + //-------------------------------------------------------------------------- // Palette class // diff --git a/engines/m4/graphics.h b/engines/m4/graphics.h index c2eb11c575..ecb5048b26 100644 --- a/engines/m4/graphics.h +++ b/engines/m4/graphics.h @@ -75,6 +75,7 @@ public: int size() { return _size; } RGB8 &operator[](int idx) { return _data[idx]; } void setRange(int start, int count, const RGB8 *src); + RGBList *clone() const; }; // M4Surface @@ -203,6 +204,7 @@ public: void scrollY(int yAmount); void translate(RGBList *list, bool isTransparent = false); + M4Surface *flipHorizontal() const; }; enum FadeType {FT_TO_GREY, FT_TO_COLOR, FT_TO_BLOCK}; diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 9241774d16..9845db7203 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -201,15 +201,23 @@ void MadsSpriteSlots::drawForeground(M4Surface *viewport) { assert(slot.spriteListIndex < (int)_sprites.size()); SpriteAsset &spriteSet = *_sprites[slot.spriteListIndex]; + // Get the sprite frame + int frameNumber = slot.frameNumber & 0x7fff; + bool flipped = (slot.frameNumber & 0x8000) != 0; + M4Sprite *sprite = spriteSet.getFrame(frameNumber - 1); + + M4Surface *spr = sprite; + if (flipped) { + // Create a flipped copy of the sprite temporarily + spr = sprite->flipHorizontal(); + } + if ((slot.scale < 100) && (slot.scale != -1)) { // Minimalised drawing - assert(slot.spriteListIndex < (int)_sprites.size()); - M4Sprite *spr = spriteSet.getFrame((slot.frameNumber & 0x7fff) - 1); viewport->copyFrom(spr, slot.xp, slot.yp, slot.depth, _owner._depthSurface, slot.scale, - spr->getTransparencyIndex()); + sprite->getTransparencyIndex()); } else { int xp, yp; - M4Sprite *spr = spriteSet.getFrame(slot.frameNumber - 1); if (slot.scale == -1) { xp = slot.xp - _owner._posAdjust.x; @@ -221,12 +229,16 @@ void MadsSpriteSlots::drawForeground(M4Surface *viewport) { if (slot.depth > 1) { // Draw the frame with depth processing - viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, spr->getTransparencyIndex()); + viewport->copyFrom(spr, xp, yp, slot.depth, _owner._depthSurface, 100, sprite->getTransparencyIndex()); } else { // No depth, so simply draw the image - spr->copyTo(viewport, xp, yp, spr->getTransparencyIndex()); + spr->copyTo(viewport, xp, yp, sprite->getTransparencyIndex()); } } + + // Free sprite if it was a flipped one + if (flipped) + delete spr; } } -- cgit v1.2.3 From dde6dabac9d6ae6f86cec11607ac15cb748aaf73 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sun, 4 Jul 2010 07:32:12 +0000 Subject: Cleanup: Treat booleans as booleans, not integers. (I hope I didn't mess up, because that would cause some nasty regressions...) svn-id: r50643 --- engines/agos/agos.cpp | 32 +++++++++++++++++--------------- engines/agos/agos.h | 2 +- engines/agos/cursor.cpp | 18 +++++++++--------- engines/agos/draw.cpp | 8 ++++---- engines/agos/event.cpp | 8 ++++---- engines/agos/gfx.cpp | 6 +++--- engines/agos/input.cpp | 16 +++++++++------- engines/agos/verb.cpp | 6 +++--- 8 files changed, 50 insertions(+), 46 deletions(-) (limited to 'engines') diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index 3ccf6fc18f..8f0e69ffdb 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -202,19 +202,19 @@ AGOSEngine::AGOSEngine(OSystem *syst) _scanFlag = false; _scriptVar2 = 0; - _runScriptReturn1 = 0; - _skipVgaWait = 0; - _noParentNotify = 0; - _beardLoaded = 0; - _litBoxFlag = 0; - _mortalFlag = 0; + _runScriptReturn1 = false; + _skipVgaWait = false; + _noParentNotify = false; + _beardLoaded = false; + _litBoxFlag = false; + _mortalFlag = false; _displayFlag = 0; - _syncFlag2 = 0; - _inCallBack = 0; - _cepeFlag = 0; - _fastMode = 0; + _syncFlag2 = false; + _inCallBack = false; + _cepeFlag = false; + _fastMode = false; - _backFlag = 0; + _backFlag = false; _debugMode = 0; _dumpScripts = false; @@ -631,9 +631,11 @@ Common::Error AGOSEngine::init() { if (ConfMan.hasKey("sfx_mute") && ConfMan.getBool("sfx_mute") == 1) { if (getGameId() == GID_SIMON1DOS) - _midi._enable_sfx ^= 1; - else - _sound->effectsPause(_effectsPaused ^= 1); + _midi._enable_sfx = !_midi._enable_sfx; + else { + _effectsPaused = !_effectsPaused; + _sound->effectsPause(_effectsPaused); + } } _copyProtection = ConfMan.getBool("copy_protection"); @@ -648,7 +650,7 @@ Common::Error AGOSEngine::init() { if (getGameType() == GType_SIMON1) { // English and German versions don't have full subtitles - if (_language == Common::EN_ANY || _language == Common::DE_DEU) + if (_language == Common::EN_ANY || _language == Common::DE_DEU) _subtitles = false; // Other versions require speech to be enabled else diff --git a/engines/agos/agos.h b/engines/agos/agos.h index ab1009e02a..b12bf09d62 100644 --- a/engines/agos/agos.h +++ b/engines/agos/agos.h @@ -393,7 +393,7 @@ protected: Common::Point _mouseOld; byte *_mouseData; - byte _animatePointer; + bool _animatePointer; byte _maxCursorWidth, _maxCursorHeight; byte _mouseAnim, _mouseAnimMax, _mouseCursor; byte _currentMouseAnim, _currentMouseCursor; diff --git a/engines/agos/cursor.cpp b/engines/agos/cursor.cpp index 109184e9c7..5ff2f014a6 100644 --- a/engines/agos/cursor.cpp +++ b/engines/agos/cursor.cpp @@ -459,7 +459,7 @@ void AGOSEngine_Simon1::handleMouseMoved() { _leftButtonDown = false; x = 1; } else { - if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) + if (!_litBoxFlag && _needHitAreaRecalc == 0) goto get_out; } @@ -473,7 +473,7 @@ get_out: drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine_PN::handleMouseMoved() { @@ -538,7 +538,7 @@ void AGOSEngine_PN::handleMouseMoved() { drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine::handleMouseMoved() { @@ -610,7 +610,7 @@ void AGOSEngine::handleMouseMoved() { _oneClick = 0; x = 1; } else { - if (_litBoxFlag == 0 && _needHitAreaRecalc == 0) + if (!_litBoxFlag && _needHitAreaRecalc == 0) goto get_out; } @@ -622,7 +622,7 @@ get_out: drawMousePointer(); _needHitAreaRecalc = 0; - _litBoxFlag = 0; + _litBoxFlag = false; } void AGOSEngine::mouseOff() { @@ -706,10 +706,10 @@ void AGOSEngine_Feeble::drawMousePointer() { uint cursor; int image, offs; - if (_animatePointer != 0) { + if (_animatePointer) { if (getBitFlag(99)) { - _mouseToggle ^= 1; - if (_mouseToggle != 0) + _mouseToggle = !_mouseToggle; + if (_mouseToggle) _mouseAnim++; } else { _mouseAnim++; @@ -720,7 +720,7 @@ void AGOSEngine_Feeble::drawMousePointer() { cursor = _mouseCursor; - if (_animatePointer == 0 && getBitFlag(99)) { + if (!_animatePointer && getBitFlag(99)) { _mouseAnim = 1; cursor = 6; } else if (_mouseCursor != 5 && getBitFlag(72)) { diff --git a/engines/agos/draw.cpp b/engines/agos/draw.cpp index 300ed4c52b..4d32b4521d 100644 --- a/engines/agos/draw.cpp +++ b/engines/agos/draw.cpp @@ -176,9 +176,9 @@ void AGOSEngine::animateSprites() { _windowNum = 4; - _backFlag = 1; + _backFlag = true; drawImage(&state); - _backFlag = 0; + _backFlag = false; _vgaSpriteChanged++; } @@ -451,14 +451,14 @@ void AGOSEngine::restoreBackGround() { state.paletteMod = 0; state.flags = kDFNonTrans; - _backFlag = 1; + _backFlag = true; drawImage(&state); if (getGameType() != GType_SIMON1 && getGameType() != GType_SIMON2) { animTable->srcPtr = 0; } } - _backFlag = 0; + _backFlag = false; if (getGameType() == GType_SIMON1 || getGameType() == GType_SIMON2) { AnimTable *animTableTmp; diff --git a/engines/agos/event.cpp b/engines/agos/event.cpp index 1340d85236..ac552ec285 100644 --- a/engines/agos/event.cpp +++ b/engines/agos/event.cpp @@ -481,7 +481,7 @@ void AGOSEngine::delay(uint amount) { _aboutDialog = new GUI::AboutDialog(); _aboutDialog->runModal(); } else if (event.kbd.keycode == Common::KEYCODE_f) { - _fastMode ^= 1; + _fastMode = !_fastMode; } else if (event.kbd.keycode == Common::KEYCODE_d) { _debugger->attach(); } else if (event.kbd.keycode == Common::KEYCODE_s) { @@ -568,7 +568,7 @@ void AGOSEngine_Feeble::timerProc() { _videoLockOut |= 2; if (!(_videoLockOut & 0x10)) { - _syncFlag2 ^= 1; + _syncFlag2 = !_syncFlag2; if (!_syncFlag2) { processVgaEvents(); } else { @@ -637,7 +637,7 @@ void AGOSEngine_PN::timerProc() { processVgaEvents(); processVgaEvents(); - _cepeFlag ^= 1; + _cepeFlag = !_cepeFlag; if (!_cepeFlag) processVgaEvents(); } @@ -663,7 +663,7 @@ void AGOSEngine::timerProc() { if (!(_videoLockOut & 0x10)) { processVgaEvents(); processVgaEvents(); - _cepeFlag ^= 1; + _cepeFlag = !_cepeFlag; if (!_cepeFlag) processVgaEvents(); } diff --git a/engines/agos/gfx.cpp b/engines/agos/gfx.cpp index e2c634007c..82a4cb714b 100644 --- a/engines/agos/gfx.cpp +++ b/engines/agos/gfx.cpp @@ -730,7 +730,7 @@ void AGOSEngine_Simon1::drawImage(VC10_state *state) { state->paletteMod = 208; } - if (_backFlag == 1) { + if (_backFlag) { drawBackGroundImage(state); } else if (state->flags & kDFMasked) { drawMaskedImage(state); @@ -947,7 +947,7 @@ void AGOSEngine::drawImage(VC10_state *state) { if (getGameType() == GType_ELVIRA2 && getPlatform() == Common::kPlatformAtariST && yoffs > 133) state->palette = 208; - if (_backFlag == 1) { + if (_backFlag) { drawBackGroundImage(state); } else { drawVertImage(state); @@ -1351,7 +1351,7 @@ void AGOSEngine::setWindowImage(uint16 mode, uint16 vgaSpriteId, bool specialCas if (getGameType() == GType_FF || getGameType() == GType_PP) { fillBackGroundFromBack(); - _syncFlag2 = 1; + _syncFlag2 = true; } else { _copyScnFlag = 2; _vgaSpriteChanged++; diff --git a/engines/agos/input.cpp b/engines/agos/input.cpp index 35ed045675..5fc2a64416 100644 --- a/engines/agos/input.cpp +++ b/engines/agos/input.cpp @@ -99,7 +99,7 @@ void AGOSEngine::setup_cond_c_helper() { animMax = 9; } - _animatePointer = 0; + _animatePointer = false; _mouseCursor = cursor; _mouseAnimMax = animMax; _mouseAnim = 1; @@ -574,13 +574,13 @@ bool AGOSEngine::processSpecialKeys() { if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE)) || ((getFeatures() & GF_TALKIE) && _language != Common::EN_ANY && _language != Common::DE_DEU)) { if (_speech) - _subtitles ^= 1; + _subtitles = !_subtitles; } break; case 'v': if (getGameType() == GType_FF || (getGameType() == GType_SIMON2 && (getFeatures() & GF_TALKIE))) { if (_subtitles) - _speech ^= 1; + _speech = !_speech; } break; case '+': @@ -598,7 +598,7 @@ bool AGOSEngine::processSpecialKeys() { syncSoundSettings(); break; case 'm': - _musicPaused ^= 1; + _musicPaused = !_musicPaused; if (_midiEnabled) { _midi.pause(_musicPaused); } @@ -606,14 +606,16 @@ bool AGOSEngine::processSpecialKeys() { break; case 's': if (getGameId() == GID_SIMON1DOS) { - _midi._enable_sfx ^= 1; + _midi._enable_sfx = !_midi._enable_sfx; } else { - _sound->effectsPause(_effectsPaused ^= 1); + _effectsPaused = !_effectsPaused; + _sound->effectsPause(_effectsPaused); } break; case 'b': if (getGameType() == GType_SIMON2) { - _sound->ambientPause(_ambientPaused ^= 1); + _ambientPaused = !_ambientPaused; + _sound->ambientPause(_ambientPaused); } break; default: diff --git a/engines/agos/verb.cpp b/engines/agos/verb.cpp index a85c1627bf..b05bac1e57 100644 --- a/engines/agos/verb.cpp +++ b/engines/agos/verb.cpp @@ -207,7 +207,7 @@ static const char *const czech_verb_prep_names[] = { void AGOSEngine_Feeble::clearName() { stopAnimateSimon2(2, 6); _lastNameOn = NULL; - _animatePointer = 0; + _animatePointer = false; _mouseAnim = 1; return; } @@ -898,7 +898,7 @@ void AGOSEngine::displayName(HitArea *ha) { if (getBitFlag(99)) _animatePointer = ((ha->flags & kBFTextBox) == 0); else - _animatePointer = 1; + _animatePointer = true; if (!getBitFlag(73)) return; @@ -933,7 +933,7 @@ void AGOSEngine_Feeble::invertBox(HitArea *ha, bool state) { _mouseCursor = _oldMouseCursor; } else if (_mouseCursor != 18) { _oldMouseCursor = _mouseCursor; - _animatePointer = 0; + _animatePointer = false; _oldMouseAnimMax = _mouseAnimMax; _mouseAnimMax = 2; _mouseCursor = 18; -- cgit v1.2.3 From 587ba8a90ee1d85cab07107293d96311fcc00c50 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 4 Jul 2010 12:45:33 +0000 Subject: Implemented more of the support methods for player display svn-id: r50644 --- engines/m4/assets.cpp | 37 ++++++++++++++--- engines/m4/assets.h | 23 ++++++++++- engines/m4/mads_player.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++- engines/m4/mads_player.h | 17 +++++++- engines/m4/mads_views.cpp | 10 ++++- engines/m4/mads_views.h | 3 +- 6 files changed, 178 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 0c0bf330a7..9cfb7afc4c 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -98,7 +98,8 @@ long *DataAsset::getRow(int index) { return &_data[_recSize * index]; } -SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : +SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, + bool asStream, int flags) : BaseAsset(vm) { _stream = stream; _palInterface = NULL; @@ -107,7 +108,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, i if (_vm->isM4()) { loadM4SpriteAsset(vm, stream, asStream); } else { - loadMadsSpriteAsset(vm, stream); + loadMadsSpriteAsset(vm, stream, flags); } } @@ -119,7 +120,7 @@ SpriteAsset::SpriteAsset(MadsM4Engine *vm, const char *name): BaseAsset(vm) { if (_vm->isM4()) { loadM4SpriteAsset(vm, _stream, true); } else { - loadMadsSpriteAsset(vm, _stream); + loadMadsSpriteAsset(vm, _stream, 0); } vm->res()->toss(name); @@ -136,6 +137,8 @@ SpriteAsset::~SpriteAsset() { for (Common::Array::iterator it = _frames.begin(); it != _frames.end(); ++it) { delete (*it).frame; } + + delete _charInfo; } void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream) { @@ -200,7 +203,7 @@ void SpriteAsset::loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream } -void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream) { +void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags) { int curFrame = 0; uint32 frameOffset = 0; MadsPack sprite(stream); @@ -217,7 +220,12 @@ void SpriteAsset::loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStre _isBackground = (type1 != 0) && (type2 < 4); spriteStream->skip(32); _frameCount = spriteStream->readUint16LE(); - // we skip the rest of the data + + if (_vm->isM4() || ((flags & SPRITE_SET_CHAR_INFO) == 0)) + _charInfo = NULL; + else + _charInfo = new MadsSpriteSetCharInfo(spriteStream); + delete spriteStream; // Get the palette data @@ -621,4 +629,23 @@ int32 AssetManager::getSpriteFrameCount(int32 hash) { return _CELS[hash]->getCount(); } +//-------------------------------------------------------------------------- + +MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) { + _frameNumber = s->readByte(); + s->skip(1); + _hasIdling = s->readUint16LE() != 0; + + for (int i = 0; i < 16; ++i) + _frameList[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _frameList2[i] = s->readUint16LE(); + for (int i = 0; i < 16; ++i) + _ticksList[i] = s->readUint16LE(); + + _unk1 = s->readUint16LE(); + _ticksAmount = s->readByte(); + _yScale = s->readByte(); +} + } // End of namespace M4 diff --git a/engines/m4/assets.h b/engines/m4/assets.h index e5beffbcae..e9902d8aa6 100644 --- a/engines/m4/assets.h +++ b/engines/m4/assets.h @@ -44,6 +44,8 @@ namespace M4 { #define CELS__PAL MKID_BE(' PAL') //' PAL' #define CELS___SS MKID_BE(' SS') //' SS' +#define SPRITE_SET_CHAR_INFO 4 + class MadsM4Engine; class Palette; @@ -100,13 +102,28 @@ struct SpriteAssetFrame { M4Sprite *frame; }; +class MadsSpriteSetCharInfo { +public: + MadsSpriteSetCharInfo(Common::SeekableReadStream *s); + + int _frameNumber; + int _hasIdling; + int _frameList2[16]; + int _frameList[16]; + int _ticksList[16]; + int _unk1; + int _ticksAmount; + int _yScale; +}; + class SpriteAsset : public BaseAsset { public: - SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false); + SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, + bool asStream = false, int flags = 0); SpriteAsset(MadsM4Engine *vm, const char *name); ~SpriteAsset(); void loadM4SpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, bool asStream); - void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream); + void loadMadsSpriteAsset(MadsM4Engine *vm, Common::SeekableReadStream* stream, int flags); int32 getCount() { return _frameCount; } int32 getFrameRate() const { return _frameRate; } int32 getPixelSpeed() const { return _pixelSpeed; } @@ -124,6 +141,8 @@ public: void translate(Palette *palette); int32 getFrameSize(int index); M4Sprite *operator[](int index) { return getFrame(index); } +public: + MadsSpriteSetCharInfo *_charInfo; protected: Common::SeekableReadStream *_stream; RGB8 _palette[256]; diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp index 53ee857093..2ba009459e 100644 --- a/engines/m4/mads_player.cpp +++ b/engines/m4/mads_player.cpp @@ -29,6 +29,10 @@ namespace M4 { +const int MadsPlayer::_directionListIndexes[32] = { + 0, 7, 4, 3, 6, 0, 2, 5, 0, 1, 9, 4, 1, 2, 7, 9, 3, 8, 9, 6, 7, 2, 3, 6, 1, 7, 9, 4, 7, 8, 0, 0 +}; + MadsPlayer::MadsPlayer() { _playerPos = Common::Point(160, 78); _direction = 0; @@ -48,6 +52,11 @@ MadsPlayer::MadsPlayer() { _spriteSetIndexes[idx] = 0; _frameNum = 0; _frameOffset = 0; + _unk1 = 0; + _newFrame = 0; + _frameListIndex = 0; + _actionIndex = 0; + resetActionList(); } /** @@ -79,7 +88,7 @@ bool MadsPlayer::loadSprites(const char *prefix) { *digitP = suffixList[idx]; _spriteSetIndexes[idx] = -1; - int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true); + int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); if (setIndex < 0) { if (idx < 7) break; @@ -165,7 +174,66 @@ void MadsPlayer::update() { _forceRefresh = false; } +/** + * Idling animation for player + */ void MadsPlayer::idle() { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + assert(spriteSet._charInfo); + + if (!spriteSet._charInfo->_hasIdling) { + _frameNum = 1; + } else { + _frameListIndex = _actionList[_actionIndex]; + + if (!_visible) { + _unk2 = 0; + } else { + _unk2 = _actionList2[_actionIndex]; + + if (_actionIndex > 0) + --_actionIndex; + } + + // Set the player frame number + int frameIndex = ABS(_frameListIndex); + _frameNum = (_frameListIndex <= 0) ? spriteSet._charInfo->_frameList[frameIndex] : + spriteSet._charInfo->_frameList2[frameIndex]; + + // Set next waiting period in ticks + if (frameIndex == 0) + setTicksAmount(); + else + _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; + } +} + +void MadsPlayer::setupFrame() { + resetActionList(); + _frameOffset = 0; + _spriteListIdx2 = _directionListIndexes[_direction]; + if (_spriteSetIndexes[_spriteListIdx2] == 0) { + _spriteListIdx2 = 4; + _frameOffset = 0x8000; + } + + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + assert(spriteSet._charInfo); + _unk1 = MAX(spriteSet._charInfo->_unk1, 100); + setTicksAmount(); + + _newFrame = spriteSet._charInfo->_frameNumber; + if (_newFrame == 0) + _newFrame = spriteSet.getCount(); + + _yScale = spriteSet._charInfo->_yScale; + + if ((_frameNum <= 0) || (_frameNum > _newFrame)) + _frameNum = 1; + _forceRefresh = true; +} + +void MadsPlayer::step() { } @@ -190,4 +258,34 @@ int MadsPlayer::getSpriteSlot() { return -1; } +void MadsPlayer::setTicksAmount() { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + assert(spriteSet._charInfo); + _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksAmount; + if (_madsVm->scene()->_ticksAmount == 0) + _madsVm->scene()->_ticksAmount = 6; +} + +void MadsPlayer::resetActionList() { + _actionList[0] = 0; + _actionList2[0] = 0; + _actionIndex = 0; + _unk2 = 0; + _unk3 = 0; +} + +int MadsPlayer::queueAction(int action1, int action2) { + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + assert(spriteSet._charInfo); + + if ((spriteSet._charInfo->_hasIdling) && (_actionIndex < 11)) { + ++_actionIndex; + _actionList[_actionIndex] = action1; + _actionList2[_actionIndex] = action2; + return false; + } + + return true; +} + } // End of namespace M4 diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h index c84c1d0c60..0a746575f1 100644 --- a/engines/m4/mads_player.h +++ b/engines/m4/mads_player.h @@ -36,6 +36,9 @@ class MadsPlayer { private: int getScale(int yp); int getSpriteSlot(); + void setTicksAmount(); + void resetActionList(); + int queueAction(int v0, int v1); public: char _spritesPrefix[16]; int _spriteSetCount; @@ -51,14 +54,26 @@ public: int16 _currentDepth; int16 _spriteListIdx, _spriteListIdx2; bool _spritesChanged; - int16 _frameOffset, _frameNum; + uint16 _frameOffset, _frameNum; bool _moving; + int _unk1; + int _newFrame; + int _frameListIndex; + int _actionIndex; + int _actionList[12]; + int _actionList2[12]; + int _unk2; + int _unk3; + + static const int _directionListIndexes[32]; public: MadsPlayer(); bool loadSprites(const char *prefix); void update(); void idle(); + void setupFrame(); + void step(); }; } // End of namespace M4 diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 9845db7203..d6d71c8eee 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -86,7 +86,7 @@ int MadsSpriteSlots::getIndex() { return startIndex++; } -int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors) { +int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors, int flags) { // If errors are suppressed, first check if the resource exists if (suppressErrors) { if (!_vm->res()->resourceExists(resName)) @@ -95,7 +95,7 @@ int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors) { // Get the sprite set Common::SeekableReadStream *data = _vm->res()->get(resName); - SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName); + SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName, flags); spriteSet->translate(_madsVm->_palette); assert(spriteSet != NULL); @@ -105,6 +105,12 @@ int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors) { return _sprites.size() - 1; } +int MadsSpriteSlots::addSprites(SpriteAsset *spriteSet) { + _sprites.push_back(spriteSet); + + return _sprites.size() - 1; +} + void MadsSpriteSlots::deleteSprites(int listIndex) { if (listIndex < 0) return; diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index 38c7ed0712..ead6ae94bf 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -92,7 +92,8 @@ public: } int getIndex(); - int addSprites(const char *resName, bool suppressErrors = false); + int addSprites(const char *resName, bool suppressErrors = false, int flags = 0); + int addSprites(SpriteAsset *spriteSet); void deleteSprites(int listIndex); void clear(); void deleteTimer(int seqIndex); -- cgit v1.2.3 From 7d64f3e34369ef43d6a9e03d9b8cb3752c300afe Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 4 Jul 2010 14:55:28 +0000 Subject: SCI: Added a short description for all opcodes, so that it's easier to understand what they do without cross referencing the wiki, and removed some obsolete and unused code svn-id: r50645 --- engines/sci/engine/vm.cpp | 101 +++++++++++++++++++++++++++++++++------------- 1 file changed, 73 insertions(+), 28 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 45cb117bcf..fa970b88e2 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -1046,6 +1046,7 @@ void run_vm(EngineState *s, bool restoring) { switch (opcode) { case op_bnot: // 0x00 (00) + // Binary not s->r_acc = ACC_ARITHMETIC_L(0xffff ^ /*acc*/); break; @@ -1129,10 +1130,12 @@ void run_vm(EngineState *s, bool restoring) { break; case op_shr: // 0x06 (06) + // Shift right logical s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) >> /*acc*/); break; case op_shl: // 0x07 (07) + // Shift left logical s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) << /*acc*/); break; @@ -1158,6 +1161,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_eq_: // 0x0d (13) + // == s->r_prev = s->r_acc; r_temp = POP32(); s->r_acc = make_reg(0, r_temp == s->r_acc); @@ -1165,6 +1169,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ne_: // 0x0e (14) + // != s->r_prev = s->r_acc; r_temp = POP32(); s->r_acc = make_reg(0, r_temp != s->r_acc); @@ -1172,6 +1177,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_gt_: // 0x0f (15) + // > s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -1190,6 +1196,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ge_: // 0x10 (16) + // >= s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -1201,6 +1208,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_lt_: // 0x11 (17) + // < s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -1218,6 +1226,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_le_: // 0x12 (18) + // <= s->r_prev = s->r_acc; r_temp = POP32(); if (r_temp.segment && s->r_acc.segment) { @@ -1229,6 +1238,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ugt_: // 0x13 (19) + // > (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1251,6 +1261,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_uge_: // 0x14 (20) + // >= (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1264,6 +1275,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ult_: // 0x15 (21) + // < (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1277,6 +1289,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ule_: // 0x16 (22) + // <= (unsigned) s->r_prev = s->r_acc; r_temp = POP32(); @@ -1290,11 +1303,13 @@ void run_vm(EngineState *s, bool restoring) { break; case op_bt: // 0x17 (23) + // Branch relative if true if (s->r_acc.offset || s->r_acc.segment) s->xs->addr.pc.offset += opparams[0]; break; case op_bnt: // 0x18 (24) + // Branch relative if not true if (!(s->r_acc.offset || s->r_acc.segment)) s->xs->addr.pc.offset += opparams[0]; break; @@ -1304,22 +1319,27 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ldi: // 0x1a (26) + // Load data immediate s->r_acc = make_reg(0, opparams[0]); break; case op_push: // 0x1b (27) + // Push to stack PUSH32(s->r_acc); break; case op_pushi: // 0x1c (28) + // Push immediate PUSH(opparams[0]); break; case op_toss: // 0x1d (29) + // TOS (Top Of Stack) subtract s->xs->sp--; break; case op_dup: // 0x1e (30) + // Duplicate TOD (Top Of Stack) element r_temp = s->xs->sp[-1]; PUSH32(r_temp); break; @@ -1329,22 +1349,12 @@ void run_vm(EngineState *s, bool restoring) { // We put special segment 0xFFFF in there, so that uninitialized reads can get detected for (int i = 0; i < opparams[0]; i++) s->xs->sp[i] = make_reg(0xffff, 0); -// for (int i = 0; i < opparams[0]; i++) -// s->xs->sp[i] = make_reg(0, 'ss'); - - //if (local_script->getScriptNumber() == 140 && isIslandOfDrBrain) { - // // WORKAROUND for The Island of Dr. Brain, room 140. - // // Script 140 runs in an endless loop if we set its - // // variables to 0 here. - //} else { - // for (int i = 0; i < opparams[0]; i++) - // s->xs->sp[i] = NULL_REG; - //} s->xs->sp += opparams[0]; break; case op_call: { // 0x20 (32) + // Call a script subroutine int argc = (opparams[1] >> 1) // Given as offset, but we need count + 1 + s->restAdjust; StackPtr call_base = s->xs->sp - argc; @@ -1366,6 +1376,7 @@ void run_vm(EngineState *s, bool restoring) { } case op_callk: { // 0x21 (33) + // Call kernel function gcCountDown(s); s->xs->sp -= (opparams[1] >> 1) + 1; @@ -1398,6 +1409,7 @@ void run_vm(EngineState *s, bool restoring) { } case op_callb: // 0x22 (34) + // Call base script temp = ((opparams[1] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; @@ -1411,6 +1423,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_calle: // 0x23 (35) + // Call external script temp = ((opparams[2] >> 1) + s->restAdjust + 1); s_temp = s->xs->sp; s->xs->sp -= temp; @@ -1425,6 +1438,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_ret: // 0x24 (36) + // Return from an execution loop started by call, calle, callb, send, self or super do { StackPtr old_sp2 = s->xs->sp; StackPtr old_fp = s->xs->fp; @@ -1467,6 +1481,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_send: // 0x25 (37) + // Send for one or more selectors s_temp = s->xs->sp; s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack @@ -1487,6 +1502,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_class: // 0x28 (40) + // Get class address s->r_acc = s->_segMan->getClassAddress((unsigned)opparams[0], SCRIPT_GET_LOCK, s->xs->addr.pc); break; @@ -1496,6 +1512,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_self: // 0x2a (42) + // Send to self s_temp = s->xs->sp; s->xs->sp -= ((opparams[0] >> 1) + s->restAdjust); // Adjust stack @@ -1511,6 +1528,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_super: // 0x2b (43) + // Send to any class r_temp = s->_segMan->getClassAddress(opparams[0], SCRIPT_GET_LOAD, s->xs->addr.pc); if (!r_temp.segment) @@ -1533,6 +1551,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_rest: // 0x2c (44) + // Pushes all or part of the parameter variable list on the stack temp = (uint16) opparams[0]; // First argument s->restAdjust = MAX(s->xs->argc - temp + 1, 0); // +1 because temp counts the paramcount while argc doesn't @@ -1542,6 +1561,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_lea: // 0x2d (45) + // Load Effective Address temp = (uint16) opparams[0] >> 1; var_number = temp & 0x03; // Get variable type @@ -1560,6 +1580,7 @@ void run_vm(EngineState *s, bool restoring) { case op_selfID: // 0x2e (46) + // Get 'self' identity s->r_acc = s->xs->objp; break; @@ -1568,66 +1589,60 @@ void run_vm(EngineState *s, bool restoring) { break; case op_pprev: // 0x30 (48) + // Pushes the value of the prev register, set by the last comparison + // bytecode (eq?, lt?, etc.), on the stack PUSH32(s->r_prev); break; case op_pToa: // 0x31 (49) + // Property To Accumulator s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); break; case op_aTop: // 0x32 (50) + // Accumulator To Property OBJ_PROPERTY(obj, (opparams[0] >> 1)) = s->r_acc; break; case op_pTos: // 0x33 (51) + // Property To Stack PUSH32(OBJ_PROPERTY(obj, opparams[0] >> 1)); break; case op_sTop: // 0x34 (52) + // Stack To Property OBJ_PROPERTY(obj, (opparams[0] >> 1)) = POP32(); break; case op_ipToa: // 0x35 (53) + // Incement Property and copy To Accumulator s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/); break; case op_dpToa: { // 0x36 (54) + // Decrement Property and copy To Accumulator s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); -#if 0 - // Speed throttling is possible here as well - // although this opens other issues like mud wrestling in lsl5 uses another local variable for delays - Object *var_container = obj; - if (!(obj->getInfoSelector().offset & SCRIPT_INFO_CLASS)) - var_container = s->_segMan->getObject(obj->getSuperClassSelector()); - uint16 varSelector = var_container->getVarSelector(opparams[0] >> 1); -// printf("%X\n", varSelector); -// printf("%s\n", g_sci->getKernel()->getSelectorName(varSelector).c_str()); - if ((varSelector == 0x84) || (varSelector == 0x92))) { - // selectors cycles, cycleCnt from lsl5 hardcoded - uint32 curTime = g_system->getMillis(); - if (s->_lastAnimateTime + 30 > curTime) - break; - s->_lastAnimateTime = curTime; - } -#endif s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/); break; } case op_ipTos: // 0x37 (55) + // Increment Property and push to Stack validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); temp = ++OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; case op_dpTos: // 0x38 (56) + // Decrement Property and push to Stack validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); temp = --OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; case op_lofsa: // 0x39 (57) + // Load Offset to Accumulator s->r_acc.segment = s->xs->addr.pc.segment; switch (g_sci->_features->detectLofsType()) { @@ -1648,6 +1663,7 @@ void run_vm(EngineState *s, bool restoring) { break; case op_lofss: // 0x3a (58) + // Load Offset to Stack r_temp.segment = s->xs->addr.pc.segment; switch (g_sci->_features->detectLofsType()) { @@ -1697,6 +1713,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lal: // 0x41 (65) case op_lat: // 0x42 (66) case op_lap: // 0x43 (67) + // Load global, local, temp or param variable into the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; s->r_acc = READ_VAR(var_type, var_number); @@ -1706,6 +1723,7 @@ void run_vm(EngineState *s, bool restoring) { case op_lsl: // 0x45 (69) case op_lst: // 0x46 (70) case op_lsp: // 0x47 (71) + // Load global, local, temp or param variable into the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; PUSH32(READ_VAR(var_type, var_number)); @@ -1715,6 +1733,8 @@ void run_vm(EngineState *s, bool restoring) { case op_lali: // 0x49 (73) case op_lati: // 0x4a (74) case op_lapi: // 0x4b (75) + // Load global, local, temp or param variable into the accumulator, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); s->r_acc = READ_VAR(var_type, var_number); @@ -1724,6 +1744,8 @@ void run_vm(EngineState *s, bool restoring) { case op_lsli: // 0x4d (77) case op_lsti: // 0x4e (78) case op_lspi: // 0x4f (79) + // Load global, local, temp or param variable into the stack, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); PUSH32(READ_VAR(var_type, var_number)); @@ -1733,6 +1755,7 @@ void run_vm(EngineState *s, bool restoring) { case op_sal: // 0x51 (81) case op_sat: // 0x52 (82) case op_sap: // 0x53 (83) + // Save the accumulator into the global, local, temp or param variable var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; WRITE_VAR(var_type, var_number, s->r_acc); @@ -1742,6 +1765,7 @@ void run_vm(EngineState *s, bool restoring) { case op_ssl: // 0x55 (85) case op_sst: // 0x56 (86) case op_ssp: // 0x57 (87) + // Save the stack into the global, local, temp or param variable var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; WRITE_VAR(var_type, var_number, POP32()); @@ -1751,6 +1775,9 @@ void run_vm(EngineState *s, bool restoring) { case op_sali: // 0x59 (89) case op_sati: // 0x5a (90) case op_sapi: // 0x5b (91) + // Save the accumulator into the global, local, temp or param variable, + // using the accumulator as an additional index + // Special semantics because it wouldn't really make a whole lot // of sense otherwise, with acc being used for two things // simultaneously... @@ -1764,6 +1791,8 @@ void run_vm(EngineState *s, bool restoring) { case op_ssli: // 0x5d (93) case op_ssti: // 0x5e (94) case op_sspi: // 0x5f (95) + // Save the stack into the global, local, temp or param variable, + // using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); WRITE_VAR(var_type, var_number, POP32()); @@ -1773,6 +1802,8 @@ void run_vm(EngineState *s, bool restoring) { case op_plusal: // 0x61 (97) case op_plusat: // 0x62 (98) case op_plusap: // 0x63 (99) + // Increment the global, local, temp or param variable and save it + // to the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; r_temp = READ_VAR(var_type, var_number); @@ -1788,6 +1819,8 @@ void run_vm(EngineState *s, bool restoring) { case op_plussl: // 0x65 (101) case op_plusst: // 0x66 (102) case op_plussp: // 0x67 (103) + // Increment the global, local, temp or param variable and save it + // to the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; r_temp = READ_VAR(var_type, var_number); @@ -1804,6 +1837,8 @@ void run_vm(EngineState *s, bool restoring) { case op_plusali: // 0x69 (105) case op_plusati: // 0x6a (106) case op_plusapi: // 0x6b (107) + // Increment the global, local, temp or param variable and save it + // to the accumulator, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); r_temp = READ_VAR(var_type, var_number); @@ -1819,6 +1854,8 @@ void run_vm(EngineState *s, bool restoring) { case op_plussli: // 0x6d (109) case op_plussti: // 0x6e (110) case op_plusspi: // 0x6f (111) + // Increment the global, local, temp or param variable and save it + // to the stack, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); r_temp = READ_VAR(var_type, var_number); @@ -1835,6 +1872,8 @@ void run_vm(EngineState *s, bool restoring) { case op_minusal: // 0x71 (113) case op_minusat: // 0x72 (114) case op_minusap: // 0x73 (115) + // Decrement the global, local, temp or param variable and save it + // to the accumulator var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; r_temp = READ_VAR(var_type, var_number); @@ -1850,6 +1889,8 @@ void run_vm(EngineState *s, bool restoring) { case op_minussl: // 0x75 (117) case op_minusst: // 0x76 (118) case op_minussp: // 0x77 (119) + // Decrement the global, local, temp or param variable and save it + // to the stack var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0]; r_temp = READ_VAR(var_type, var_number); @@ -1866,6 +1907,8 @@ void run_vm(EngineState *s, bool restoring) { case op_minusali: // 0x79 (121) case op_minusati: // 0x7a (122) case op_minusapi: // 0x7b (123) + // Decrement the global, local, temp or param variable and save it + // to the accumulator, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); r_temp = READ_VAR(var_type, var_number); @@ -1881,6 +1924,8 @@ void run_vm(EngineState *s, bool restoring) { case op_minussli: // 0x7d (125) case op_minussti: // 0x7e (126) case op_minusspi: // 0x7f (127) + // Decrement the global, local, temp or param variable and save it + // to the stack, using the accumulator as an additional index var_type = opcode & 0x3; // Gets the variable type: g, l, t or p var_number = opparams[0] + signed_validate_arithmetic(s->r_acc); r_temp = READ_VAR(var_type, var_number); -- cgit v1.2.3 From 6219ffe52f2f38dfcdf000227554eaa8d9d3098c Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Sun, 4 Jul 2010 21:31:09 +0000 Subject: SCI: Removed the unused line number parameter from validate_variable() and related functions svn-id: r50654 --- engines/sci/engine/vm.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index fa970b88e2..83bcae9673 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -228,7 +228,7 @@ static int signed_validate_arithmetic(reg_t reg) { return (int16)validate_arithmetic(reg); } -static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index, int line) { +static bool validate_variable(reg_t *r, reg_t *stack_base, int type, int max, int index) { const char *names[4] = {"global", "local", "temp", "param"}; if (index < 0 || index >= max) { @@ -364,8 +364,8 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t default_value) { - if (validate_variable(r, stack_base, type, max, index, line)) { +static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) { + if (validate_variable(r, stack_base, type, max, index)) { if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually @@ -380,8 +380,8 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i return default_value; } -static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, int line, reg_t value, SegManager *segMan, Kernel *kernel) { - if (validate_variable(r, stack_base, type, max, index, line)) { +static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t value, SegManager *segMan, Kernel *kernel) { + if (validate_variable(r, stack_base, type, max, index)) { // WORKAROUND: This code is needed to work around a probable script bug, or a // limitation of the original SCI engine, which can be observed in LSL5. @@ -423,8 +423,8 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i } } -#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, s->r_acc) -#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, __LINE__, value, s->_segMan, g_sci->getKernel()) +#define READ_VAR(type, index) validate_read_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, s->r_acc) +#define WRITE_VAR(type, index, value) validate_write_var(s->variables[type], s->stack_base, type, s->variablesMax[type], index, value, s->_segMan, g_sci->getKernel()) #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) -- cgit v1.2.3 From 18b449d4fdcf9651f325259fb7ba1d81135143ff Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Sun, 4 Jul 2010 23:38:08 +0000 Subject: Add a hexDumpReg function to view references that are not raw and fix SCI32 strings/arrays in segmentInfo. svn-id: r50660 --- engines/sci/console.cpp | 74 +++++++++++++++++++++++++++++++++++++++++++++++-- engines/sci/console.h | 1 + 2 files changed, 72 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index b83ffee0e7..bb79fc145a 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1558,6 +1558,15 @@ bool Console::segmentInfo(int nr) { break; } +#ifdef ENABLE_SCI32 + case SEG_TYPE_STRING: + DebugPrintf("SCI32 strings\n"); + break; + case SEG_TYPE_ARRAY: + DebugPrintf("SCI32 arrays\n"); + break; +#endif + default : DebugPrintf("Invalid type %d\n", mobj->getType()); break; @@ -2112,7 +2121,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { return true; } - if (reg_end.segment != reg.segment) { + if (reg_end.segment != reg.segment && reg_end != NULL_REG) { DebugPrintf("Ending segment different from starting segment. Assuming no bound on dump.\n"); reg_end = NULL_REG; } @@ -2151,13 +2160,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { + DebugPrintf("SCI32 string\n"); const SciString *str = _engine->_gamestate->_segMan->lookupString(reg); Common::hexdump((const byte *) str->getRawData(), str->getSize(), 16, 0); break; } case SEG_TYPE_ARRAY: { + DebugPrintf("SCI32 array:\n"); const SciArray *array = _engine->_gamestate->_segMan->lookupArray(reg); - Common::hexdump((const byte *) array->getRawData(), array->getSize(), 16, 0); + hexDumpReg(array->getRawData(), array->getSize(), 4, 0, true); break; } #endif @@ -2179,7 +2190,10 @@ bool Console::cmdViewReference(int argc, const char **argv) { if (reg_end.segment != 0) DebugPrintf("Block size less than or equal to %d\n", size); - Common::hexdump(block.raw, size, 16, 0); + if (block.isRaw) + Common::hexdump(block.raw, size, 16, 0); + else + hexDumpReg(block.reg, size / 2, 4, 0); } } break; @@ -3284,4 +3298,58 @@ int Console::printObject(reg_t pos) { return 0; } +void Console::hexDumpReg(const reg_t *data, int len, int regsPerLine, int startOffset, bool isArray) { + // reg_t version of Common::hexdump + assert(1 <= regsPerLine && regsPerLine <= 8); + int i; + byte c; + int offset = startOffset; + while (len >= regsPerLine) { + printf("%06x: ", offset); + for (i = 0; i < regsPerLine; i++) { + printf("%04x:%04x ", PRINT_REG(data[i])); + } + printf(" |"); + for (i = 0; i < regsPerLine; i++) { + c = data[i].toUint16() >> 8; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + c = data[i].toUint16() & 0xff; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + } + printf("|\n"); + data += regsPerLine; + len -= regsPerLine; + offset += regsPerLine * (isArray ? 1 : 2); + } + + if (len <= 0) + return; + + printf("%06x: ", offset); + for (i = 0; i < regsPerLine; i++) { + if (i < len) + printf("%04x:%04x ", PRINT_REG(data[i])); + else + printf(" "); + } + printf(" |"); + for (i = 0; i < len; i++) { + c = data[i].toUint16() >> 8; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + c = data[i].toUint16() & 0xff; + if (c < 32 || c >= 127) + c = '.'; + printf("%c", c); + } + for (; i < regsPerLine; i++) + printf(" "); + printf("|\n"); +} + } // End of namespace Sci diff --git a/engines/sci/console.h b/engines/sci/console.h index 2948e348d8..7e7b30ea58 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -151,6 +151,7 @@ private: bool segmentInfo(int nr); void printList(List *list); int printNode(reg_t addr); + void hexDumpReg(const reg_t *data, int len, int regsPerLine = 4, int startOffset = 0, bool isArray = false); private: SciEngine *_engine; -- cgit v1.2.3 From 660ffc194d217bdeb61479e5b101e7642319ecb5 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Mon, 5 Jul 2010 09:53:10 +0000 Subject: Bugfixes for new player code - Rex is now correctly positioned when the player manager takes over from the wakeup animation sequence svn-id: r50669 --- engines/m4/mads_player.cpp | 13 +++++++------ engines/m4/mads_player.h | 2 +- engines/m4/mads_scene.cpp | 1 + engines/m4/mads_views.cpp | 2 +- 4 files changed, 10 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp index 2ba009459e..57cb9eefd3 100644 --- a/engines/m4/mads_player.cpp +++ b/engines/m4/mads_player.cpp @@ -49,7 +49,7 @@ MadsPlayer::MadsPlayer() { _currentScale = 0; strcpy(_spritesPrefix, ""); for (int idx = 0; idx < 8; ++idx) - _spriteSetIndexes[idx] = 0; + _spriteSetsPresent[idx] = false; _frameNum = 0; _frameOffset = 0; _unk1 = 0; @@ -76,7 +76,7 @@ bool MadsPlayer::loadSprites(const char *prefix) { if (prefixLen == 0) { // No player sprites at at all for (int idx = 0; idx < 8; ++idx) - _spriteSetIndexes[idx] = 0; + _spriteSetsPresent[idx] = false; } else { strcpy(setName, "*"); strcat(setName, _spritesPrefix); @@ -86,13 +86,13 @@ bool MadsPlayer::loadSprites(const char *prefix) { for (int idx = 0; idx < 8; ++idx) { *digitP = suffixList[idx]; - _spriteSetIndexes[idx] = -1; + _spriteSetsPresent[idx] = true; int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); if (setIndex < 0) { if (idx < 7) break; - _spriteSetIndexes[idx] = 0; + _spriteSetsPresent[idx] = false; } else { ++_spriteSetCount; } @@ -212,8 +212,9 @@ void MadsPlayer::setupFrame() { resetActionList(); _frameOffset = 0; _spriteListIdx2 = _directionListIndexes[_direction]; - if (_spriteSetIndexes[_spriteListIdx2] == 0) { - _spriteListIdx2 = 4; + if (!_spriteSetsPresent[_spriteListIdx2]) { + // Direction isn't present, so use alternate direction, with entries flipped + _spriteListIdx2 -= 4; _frameOffset = 0x8000; } diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h index 0a746575f1..7285796309 100644 --- a/engines/m4/mads_player.h +++ b/engines/m4/mads_player.h @@ -42,7 +42,7 @@ private: public: char _spritesPrefix[16]; int _spriteSetCount; - int _spriteSetIndexes[8]; + bool _spriteSetsPresent[8]; Common::Point _playerPos; Common::Point _destPos; int16 _direction, _direction2; diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index d22ca02475..66883dd13c 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -166,6 +166,7 @@ void MadsScene::loadScene(int sceneNumber) { // Miscellaneous player setup _madsVm->_player._destPos = _madsVm->_player._destPos; _madsVm->_player._direction2 = _madsVm->_player._direction; + _madsVm->_player.setupFrame(); _madsVm->_player.idle(); // Purge resources diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index d6d71c8eee..580f54b1c0 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -95,7 +95,7 @@ int MadsSpriteSlots::addSprites(const char *resName, bool suppressErrors, int fl // Get the sprite set Common::SeekableReadStream *data = _vm->res()->get(resName); - SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName, flags); + SpriteAsset *spriteSet = new SpriteAsset(_vm, data, data->size(), resName, false, flags); spriteSet->translate(_madsVm->_palette); assert(spriteSet != NULL); -- cgit v1.2.3 From 5527882daa02eb98f86f7a9904c588ba93821fe1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 5 Jul 2010 14:36:31 +0000 Subject: SCI: implemented new kernel call signature format svn-id: r50678 --- engines/sci/console.cpp | 37 ++- engines/sci/engine/kernel.cpp | 719 +++++++++++++++++++++++++----------------- engines/sci/engine/kernel.h | 32 +- 3 files changed, 465 insertions(+), 323 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index bb79fc145a..7e5d77d99a 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -2042,18 +2042,18 @@ bool Console::cmdValueType(int argc, const char **argv) { int t = g_sci->getKernel()->findRegType(val); switch (t) { - case KSIG_LIST: + case SIG_TYPE_LIST: DebugPrintf("List"); break; - case KSIG_OBJECT: + case SIG_TYPE_OBJECT: DebugPrintf("Object"); break; - case KSIG_REF: + case SIG_TYPE_REFERENCE: DebugPrintf("Reference"); break; - case KSIG_ARITHMETIC: - DebugPrintf("Arithmetic"); - case KSIG_ARITHMETIC | KSIG_NULL: + case SIG_TYPE_INTEGER: + DebugPrintf("Integer"); + case SIG_TYPE_INTEGER | SIG_TYPE_NULL: DebugPrintf("Null"); break; default: @@ -2137,7 +2137,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { switch (type) { case 0: break; - case KSIG_LIST: { + case SIG_TYPE_LIST: { List *list = _engine->_gamestate->_segMan->lookupList(reg); DebugPrintf("list\n"); @@ -2148,15 +2148,15 @@ bool Console::cmdViewReference(int argc, const char **argv) { DebugPrintf("Invalid list.\n"); } break; - case KSIG_NODE: + case SIG_TYPE_NODE: DebugPrintf("list node\n"); printNode(reg); break; - case KSIG_OBJECT: + case SIG_TYPE_OBJECT: DebugPrintf("object\n"); printObject(reg); break; - case KSIG_REF: { + case SIG_TYPE_REFERENCE: { switch (_engine->_gamestate->_segMan->getSegmentType(reg.segment)) { #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: { @@ -2198,7 +2198,7 @@ bool Console::cmdViewReference(int argc, const char **argv) { } break; } - case KSIG_ARITHMETIC: + case SIG_TYPE_INTEGER: DebugPrintf("arithmetic value\n %d (%04x)\n", (int16) reg.offset, reg.offset); break; default: @@ -3149,27 +3149,30 @@ void Console::printBasicVarInfo(reg_t variable) { int segType = g_sci->getKernel()->findRegType(variable); SegManager *segMan = g_sci->getEngineState()->_segMan; - segType &= KSIG_ARITHMETIC | KSIG_OBJECT | KSIG_REF | KSIG_NODE | KSIG_LIST; + segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED; switch (segType) { - case KSIG_ARITHMETIC: { + case SIG_TYPE_INTEGER: { uint16 content = variable.toUint16(); if (content >= 10) DebugPrintf(" (%dd)", content); break; } - case KSIG_OBJECT: + case SIG_TYPE_OBJECT: DebugPrintf(" (object '%s')", segMan->getObjectName(variable)); break; - case KSIG_REF: + case SIG_TYPE_REFERENCE: DebugPrintf(" (reference)"); break; - case KSIG_NODE: + case SIG_TYPE_NODE: DebugPrintf(" (node)"); break; - case KSIG_LIST: + case SIG_TYPE_LIST: DebugPrintf(" (list)"); break; + case SIG_TYPE_UNINITIALIZED: + DebugPrintf(" (uninitialized)"); + break; default: DebugPrintf(" (??\?)"); } diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index fb2c60cdb6..4c6fb4cf83 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -206,7 +206,7 @@ static const char *s_defaultKernelNames[] = { // i* -> optional multiple integers // .* -> any parameters afterwards (or none) -// gameID, scriptNr,lvl, object-name, method-name, call,index,replace +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard SCI_WORKAROUNDENTRY_TERMINATOR @@ -226,6 +226,8 @@ struct SciKernelMapEntry { }; #define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE +#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01 +#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE #define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1 #define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 #define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE @@ -245,129 +247,133 @@ struct SciKernelMapEntry { // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { - { MAP_CALL(Load), SIG_EVERYWHERE, "iii*", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "iRi*", NULL, NULL }, + { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, NULL }, // ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?) - { MAP_CALL(ScriptID), SIG_EVERYWHERE, "Ioi*", NULL, NULL }, - { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "ii*", NULL, kDisposeScript_workarounds }, + { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds }, { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, - { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i*", NULL, NULL }, - { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "i*", NULL, NULL }, - { MAP_CALL(Animate), SIG_EVERYWHERE, "LI*", NULL, NULL }, - // ^^ FIXME - More like (li?)? - { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "oi*", NULL, NULL }, - // ^^ FIXME - The second parameter is ignored + { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL }, + { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(CelWide), SIG_EVERYWHERE, "iOi*", NULL, NULL }, - { MAP_CALL(CelHigh), SIG_EVERYWHERE, "iOi*", NULL, NULL }, - { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiiii*i*r*", NULL, NULL }, - { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiiii*i*", NULL, NULL }, - { MAP_CALL(AddToPic), SIG_EVERYWHERE, "Il*", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, "*.", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_EVERYWHERE, "iiiiZRi*", NULL, NULL }, + { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r)", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, + { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, NULL }, { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(SetPort), SIG_EVERYWHERE, "ii*", NULL, NULL }, - { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iii)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL }, { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(EditControl), SIG_EVERYWHERE, "ZoZo", NULL, NULL }, - { MAP_CALL(TextSize), SIG_EVERYWHERE, "rZrii*r*", NULL, NULL }, - { MAP_CALL(Display), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "ioi*", NULL, NULL }, + { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL }, + { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL }, + { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir]*)", NULL, NULL }, // subop + { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL }, { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL }, - { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "oo*", NULL, NULL }, - { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "oo*", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "oi*", NULL, NULL }, + { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL }, { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, - { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "Zri*", NULL, NULL }, + { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL }, { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, - { MAP_CALL(Said), SIG_EVERYWHERE, "Zr", NULL, NULL }, + { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rirr*", NULL, NULL }, - { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir*", NULL, NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL }, + { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL }, { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "i*", NULL, NULL }, - { MAP_CALL(DoSound), SIG_EVERYWHERE, "iIo*", NULL, NULL }, + { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(iii)(i)", NULL, NULL }, // subop { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, - { MAP_CALL(FirstNode), SIG_EVERYWHERE, "Zl", NULL, NULL }, + { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL }, { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL }, { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, - { MAP_CALL(NodeValue), SIG_EVERYWHERE, "Zn", NULL, NULL }, + { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL }, { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL }, { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL }, { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, - { MAP_CALL(Random), SIG_EVERYWHERE, "i*", NULL, NULL }, - { MAP_CALL(Abs), SIG_EVERYWHERE, "Oi", NULL, NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(Abs), SIG_EVERYWHERE, "[io]", NULL, NULL }, + // ^^ FIXME hoyle { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiiii*", NULL, NULL }, + { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, NULL }, // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake - { MAP_CALL(GetDistance), SIG_EVERYWHERE, "iiiii*", NULL, NULL }, + { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL }, { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(GetTime), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL }, - { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rri*", NULL, NULL }, - { MAP_CALL(StrLen), SIG_EVERYWHERE, "Zr", NULL, NULL }, - { MAP_CALL(StrCpy), SIG_EVERYWHERE, "rZri*", NULL, NULL }, - { MAP_CALL(Format), SIG_EVERYWHERE, "r.*", NULL, NULL }, - { MAP_CALL(GetFarText), SIG_EVERYWHERE, "iiZr", NULL, NULL }, + { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL }, + { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL }, + { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(i)", NULL, NULL }, + { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL }, + { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL }, { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, - { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL }, - { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "ol*", NULL, NULL }, - { MAP_CALL(OnControl), SIG_EVERYWHERE, "i*", NULL, NULL }, - { MAP_CALL(InitBresen), SIG_EVERYWHERE, "oi*", NULL, NULL }, + { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, + { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, - { MAP_CALL(SetDebug), SIG_EVERYWHERE, "i*", NULL, NULL }, + { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL }, { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL }, - { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r.*", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(CoordPri), SIG_EVERYWHERE, "ii*", NULL, NULL }, - { MAP_CALL(StrAt), SIG_EVERYWHERE, "rii*", NULL, NULL }, - { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i.*", NULL, NULL }, - { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "r*", NULL, NULL }, + { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL }, + { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, NULL }, + { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop + { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL }, { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL }, { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(Joystick), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(FileIO), SIG_EVERYWHERE, "i.*", NULL, NULL }, - { MAP_CALL(Memory), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, - { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii.*", NULL, NULL }, - { MAP_CALL(Lock), SIG_EVERYWHERE, "iii*", NULL, NULL }, - { MAP_CALL(Palette), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL }, + { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL }, - { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rrZr", NULL, NULL }, + { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL }, { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL }, { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, @@ -375,31 +381,31 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Message), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL }, - { MAP_CALL(DoAudio), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(DoSync), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "iri*", NULL, NULL }, + { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL }, { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL }, - { MAP_CALL(ResCheck), SIG_EVERYWHERE, "iii*", NULL, NULL }, + { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL }, { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(ShowMovie), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(Platform), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(TextColors), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(TextFonts), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(Portrait), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(PalVary), SIG_EVERYWHERE, "ii*", NULL, NULL }, + { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, // subop { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(Empty), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL }, #ifdef ENABLE_SCI32 // SCI2 Kernel Functions { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(Array), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL }, - { MAP_CALL(String), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, @@ -409,23 +415,23 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li.*", NULL, NULL }, - { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li.*", NULL, NULL }, - { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li.*", NULL, NULL }, - { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "lZo", NULL, NULL }, - { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL }, + { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL }, + { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, - { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i.*", NULL, NULL }, + { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // SCI2.1 Kernel Functions - { MAP_CALL(Save), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(List), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(Robot), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(PlayVMD), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio.*", NULL, NULL }, + { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(List), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, - { MAP_CALL(Text), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(CD), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } #endif }; @@ -514,77 +520,349 @@ void Kernel::loadSelectorNames() { } } -static char *compileKernelSignature(const char *s) { - const char *src = s; - char *result; - bool ellipsis = false; - int index = 0; - - if (!src) - return 0; // NULL signature: Nothing to do +// this parses a written kernel signature into an internal memory format +// [io] -> either integer or object +// (io) -> optionally integer AND an object +// (i) -> optional integer +// . -> any type +// i* -> optional multiple integers +// .* -> any parameters afterwards (or none) +static uint16 *parseKernelSignature(const char *kernelName, const char *writtenSig) { + const char *curPos; + char curChar; + uint16 *result = NULL; + uint16 *writePos = NULL; + int size = 0; + bool validType = false; + bool optionalType = false; + bool eitherOr = false; + bool optional = false; + bool hadOptional = false; + + // First, we check how many bytes the result will be + // we also check, if the written signature makes any sense + curPos = writtenSig; + while (*curPos) { + switch (*curPos) { + case '[': // either or + if (eitherOr) + error("signature for k%s: '[' used within '[]'", kernelName); + eitherOr = true; + validType = false; + break; + case ']': // either or end + if (!eitherOr) + error("signature for k%s: ']' used without leading '['", kernelName); + if (!validType) + error("signature for k%s: '[]' does not surround valid type(s)", kernelName); + eitherOr = false; + validType = false; + size++; + break; + case '(': // optional + if (optional) + error("signature for k%s: '(' used within '()' brackets", kernelName); + if (eitherOr) + error("signature for k%s: '(' used within '[]' brackets", kernelName); + optional = true; + validType = false; + optionalType = false; + break; + case ')': // optional end + if (!optional) + error("signature for k%s: ')' used without leading '('", kernelName); + if (!optionalType) + error("signature for k%s: '()' does not to surround valid type(s)", kernelName); + optional = false; + validType = false; + hadOptional = true; + break; + case '0': // allowed types + case 'i': + case 'o': + case 'r': + case 'l': + case 'n': + case '.': + if ((hadOptional) & (!optional)) + error("signature for k%s: non-optional type may not follow optional type", kernelName); + validType = true; + if (optional) + optionalType = true; + if (!eitherOr) + size++; + break; + case '*': // accepts more of the same parameter (must be last char) + if (!validType) { + if ((writtenSig == curPos) || (*(curPos - 1) != ']')) + error("signature for k%s: a valid type must be in front of '*'", kernelName); + } + if (eitherOr) + error("signature for k%s: '*' may not be inside '[]'", kernelName); + if (optional) { + if ((*(curPos + 1) != ')') || (*(curPos + 2) != 0)) + error("signature for k%s: '*' may only be used for last type", kernelName); + } else { + if (*(curPos + 1) != 0) + error("signature for k%s: '*' may only be used for last type", kernelName); + } + break; + default: + error("signature for k%s: '%c' unknown", kernelName, *curPos); + } + curPos++; + } - result = (char *)malloc(strlen(s) + 1); + uint16 signature = 0; + + // Now we allocate buffer with required size and fill it + result = new uint16[size + 1]; + writePos = result; + curPos = writtenSig; + do { + curChar = *curPos; + if (!eitherOr) { + // not within either-or, check if next character forces output + switch (curChar) { + case 0: + case '[': + case '(': + case ')': + case 'i': + case 'o': + case 'r': + case 'l': + case 'n': + case '.': + // and we also got some signature pending? + if (signature) { + if (optional) { + signature |= SIG_IS_OPTIONAL; + if (curChar != ')') + signature |= SIG_NEEDS_MORE; + } + *writePos = signature; + writePos++; + signature = 0; + } + } + } + switch (curChar) { + case '[': // either or + eitherOr = true; + break; + case ']': // either or end + eitherOr = false; + break; + case '(': // optional + optional = true; + break; + case ')': // optional end + optional = false; + break; + case '0': + if (signature & SIG_TYPE_NULL) + error("signature for k%s: NULL specified more than once", kernelName); + signature |= SIG_TYPE_NULL; + break; + case 'i': + if (signature & SIG_TYPE_INTEGER) + error("signature for k%s: integer specified more than once", kernelName); + signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL; + break; + case 'o': + if (signature & SIG_TYPE_OBJECT) + error("signature for k%s: object specified more than once", kernelName); + signature |= SIG_TYPE_OBJECT; + break; + case 'r': + if (signature & SIG_TYPE_REFERENCE) + error("signature for k%s: reference specified more than once", kernelName); + signature |= SIG_TYPE_REFERENCE; + break; + case 'l': + if (signature & SIG_TYPE_LIST) + error("signature for k%s: list specified more than once", kernelName); + signature |= SIG_TYPE_LIST; + break; + case 'n': + if (signature & SIG_TYPE_NODE) + error("signature for k%s: node specified more than once", kernelName); + signature |= SIG_TYPE_NODE; + break; + case '.': + signature |= SIG_MAYBE_ANY; + break; + case '*': // accepts more of the same parameter + signature |= SIG_MORE_MAY_FOLLOW; + break; + default: + break; + } + curPos++; + } while (curChar); - while (*src) { - char c; - char v = 0; + // Write terminator + *writePos = 0; - if (ellipsis) { - error("Failed compiling kernel function signature '%s': non-terminal ellipsis '%c'", s, *src); - } + return result; +} - do { - char cc; - cc = c = *src++; - if (c >= 'A' || c <= 'Z') - cc = c | KSIG_SPEC_SUM_DONE; +int Kernel::findRegType(reg_t reg) { + // No segment? Must be integer + if (!reg.segment) + return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL); - switch (cc) { - case KSIG_SPEC_LIST: - v |= KSIG_LIST; - break; + if (reg.segment == 0xFFFF) + return SIG_TYPE_UNINITIALIZED; - case KSIG_SPEC_NODE: - v |= KSIG_NODE; - break; + // Otherwise it's an object + SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); + if (!mobj) + return 0; // Invalid - case KSIG_SPEC_REF: - v |= KSIG_REF; - break; + if (!mobj->isValidOffset(reg.offset)) + error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); - case KSIG_SPEC_OBJECT: - v |= KSIG_OBJECT; - break; + switch (mobj->getType()) { + case SEG_TYPE_SCRIPT: + if (reg.offset <= (*(Script *)mobj).getBufSize() && + reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && + RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { + return ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; + } else + return SIG_TYPE_REFERENCE; + case SEG_TYPE_CLONES: + return SIG_TYPE_OBJECT; + case SEG_TYPE_LOCALS: + case SEG_TYPE_STACK: + case SEG_TYPE_SYS_STRINGS: + case SEG_TYPE_DYNMEM: + case SEG_TYPE_HUNK: +#ifdef ENABLE_SCI32 + case SEG_TYPE_ARRAY: + case SEG_TYPE_STRING: +#endif + return SIG_TYPE_REFERENCE; + case SEG_TYPE_LISTS: + return SIG_TYPE_LIST; + case SEG_TYPE_NODES: + return SIG_TYPE_NODE; + default: + return 0; + } +} - case KSIG_SPEC_ARITHMETIC: - v |= KSIG_ARITHMETIC; - break; +struct SignatureDebugType { + uint16 typeCheck; + const char *text; +}; - case KSIG_SPEC_NULL: - v |= KSIG_NULL; - break; +static const SignatureDebugType signatureDebugTypeList[] = { + { SIG_TYPE_NULL, "null" }, + { SIG_TYPE_INTEGER, "integer" }, + { SIG_TYPE_UNINITIALIZED, "uninitialized" }, + { SIG_TYPE_OBJECT, "object" }, + { SIG_TYPE_REFERENCE, "reference" }, + { SIG_TYPE_LIST, "list" }, + { SIG_TYPE_NODE, "node" }, + { 0, NULL } +}; - case KSIG_SPEC_ANY: - v |= KSIG_ANY; - break; +static void kernelSignatureDebugType(const uint16 type) { + bool firstPrint = true; - case KSIG_SPEC_ELLIPSIS: - v |= KSIG_ELLIPSIS; - ellipsis = true; - break; + const SignatureDebugType *list = signatureDebugTypeList; + while (list->typeCheck) { + if (type & list->typeCheck) { + if (!firstPrint) + printf(", "); + printf("%s", list->text); + firstPrint = false; + } + list++; + } +} - default: - error("ERROR compiling kernel function signature '%s': (%02x / '%c') not understood", s, c, c); +// Shows kernel call signature and current arguments for debugging purposes +void Kernel::signatureDebug(const uint16 *sig, int argc, const reg_t *argv) { + int argnr = 0; + while (*sig || argc) { + printf("parameter %d: ", argnr++); + if (argc) { + reg_t parameter = *argv; + printf("%04x:%04x (", PRINT_REG(parameter)); + int regType = findRegType(parameter); + if (regType) + kernelSignatureDebugType(regType); + else + printf("unknown type of %04x:%04x", PRINT_REG(parameter)); + printf(")"); + argv++; + argc--; + } else { + printf("not passed"); + } + if (*sig) { + const uint16 signature = *sig; + if ((signature & SIG_MAYBE_ANY) == SIG_MAYBE_ANY) { + printf(", may be any"); + } else { + printf(", should be "); + kernelSignatureDebugType(signature); } - } while (*src && (*src == KSIG_SPEC_ELLIPSIS || (c < 'a' && c != KSIG_SPEC_ANY))); - - // To handle sum types - result[index++] = v; + if (signature & SIG_IS_OPTIONAL) + printf(" (optional)"); + if (signature & SIG_NEEDS_MORE) + printf(" (needs more)"); + if (signature & SIG_MORE_MAY_FOLLOW) + printf(" (more may follow)"); + sig++; + } + printf("\n"); } +} - result[index] = 0; +bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) { + uint16 nextSig = *sig; + uint16 curSig = nextSig; + while (nextSig && argc) { + curSig = nextSig; + int type = findRegType(*argv); + if (!type) + return false; // couldn't determine type - return result; + if (!(type & curSig)) + return false; // type mismatch + + if (!(curSig & SIG_MORE_MAY_FOLLOW)) { + sig++; + nextSig = *sig; + } else { + nextSig |= SIG_IS_OPTIONAL; // more may follow -> assumes followers are optional + } + argv++; + argc--; + } + + // Too many arguments? + if (argc) + return false; + // Signature end reached? + if (nextSig == 0) + return true; + // current parameter is optional? + if (curSig & SIG_IS_OPTIONAL) { + // yes, check if nothing more is required + if (!(curSig & SIG_NEEDS_MORE)) + return true; + } else { + // no, check if next parameter is optional + if (nextSig & SIG_IS_OPTIONAL) + return true; + } + // Too few arguments or more optional arguments required + return false; } void Kernel::mapFunctions() { @@ -645,8 +923,8 @@ void Kernel::mapFunctions() { bool nameMatch = false; while (kernelMap->name) { if (sought_name == kernelMap->name) { - if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion >= myVersion)) - if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion <= myVersion)) + if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion)) + if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion)) if (platformMask & kernelMap->forPlatform) break; nameMatch = true; @@ -658,7 +936,7 @@ void Kernel::mapFunctions() { // A match was found if (kernelMap->function) { _kernelFuncs[functNr].func = kernelMap->function; - _kernelFuncs[functNr].signature = compileKernelSignature(kernelMap->signature); + _kernelFuncs[functNr].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); _kernelFuncs[functNr].workarounds = kernelMap->workarounds; _kernelFuncs[functNr].isDummy = false; ++mapped; @@ -680,147 +958,6 @@ void Kernel::mapFunctions() { return; } -int Kernel::findRegType(reg_t reg) { - // No segment? Must be arithmetic - if (!reg.segment) - return reg.offset ? KSIG_ARITHMETIC : KSIG_ARITHMETIC | KSIG_NULL; - - if (reg.segment == 0xFFFF) - return KSIG_UNINITIALIZED; - - // Otherwise it's an object - SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); - if (!mobj) - return 0; // Invalid - - if (!mobj->isValidOffset(reg.offset)) - error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); - - switch (mobj->getType()) { - case SEG_TYPE_SCRIPT: - if (reg.offset <= (*(Script *)mobj).getBufSize() && - reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && - RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { - return ((Script *)mobj)->getObject(reg.offset) ? KSIG_OBJECT : KSIG_REF; - } else - return KSIG_REF; - case SEG_TYPE_CLONES: - return KSIG_OBJECT; - case SEG_TYPE_LOCALS: - case SEG_TYPE_STACK: - case SEG_TYPE_SYS_STRINGS: - case SEG_TYPE_DYNMEM: - case SEG_TYPE_HUNK: -#ifdef ENABLE_SCI32 - case SEG_TYPE_ARRAY: - case SEG_TYPE_STRING: -#endif - return KSIG_REF; - case SEG_TYPE_LISTS: - return KSIG_LIST; - case SEG_TYPE_NODES: - return KSIG_NODE; - default: - return 0; - } -} - -struct SignatureDebugType { - char typeCheck; - const char *text; -}; - -static const SignatureDebugType signatureDebugTypeList[] = { - { KSIG_NULL, "null" }, - { KSIG_ARITHMETIC, "value" }, - { KSIG_UNINITIALIZED, "uninitialized" }, - { KSIG_OBJECT, "object" }, - { KSIG_REF, "reference" }, - { KSIG_LIST, "list" }, - { KSIG_NODE, "node" }, - { 0, NULL } -}; - -static void kernelSignatureDebugType(const char type) { - bool firstPrint = true; - - const SignatureDebugType *list = signatureDebugTypeList; - while (list->typeCheck) { - if (type & list->typeCheck) { - if (!firstPrint) - printf(", "); - printf("%s", list->text); - firstPrint = false; - } - list++; - } -} - -// Shows kernel call signature and current arguments for debugging purposes -void Kernel::signatureDebug(const char *sig, int argc, const reg_t *argv) { - int argnr = 0; - while (*sig || argc) { - printf("parameter %d: ", argnr++); - if (argc) { - reg_t parameter = *argv; - printf("%04x:%04x (", PRINT_REG(parameter)); - int regType = findRegType(parameter); - if (regType) - kernelSignatureDebugType(regType); - else - printf("unknown type of %04x:%04x", PRINT_REG(parameter)); - printf(")"); - argv++; - argc--; - } else { - printf("not passed"); - } - if (*sig) { - const char signature = *sig; - if ((signature & KSIG_ANY) == KSIG_ANY) { - printf(", may be any"); - } else { - printf(", should be "); - kernelSignatureDebugType(signature); - } - if (signature & KSIG_ELLIPSIS) - printf(" (optional)"); - sig++; - } - printf("\n"); - } -} - -bool Kernel::signatureMatch(const char *sig, int argc, const reg_t *argv) { - // Always "match" if no signature is given - if (!sig) - return true; - - while (*sig && argc) { - if ((*sig & KSIG_ANY) != KSIG_ANY) { - int type = findRegType(*argv); - - if (!type) - return false; // couldn't determine type - - if (!(type & *sig)) - return false; // type mismatch - - } - if (!(*sig & KSIG_ELLIPSIS)) - ++sig; - ++argv; - --argc; - } - - if (argc) - return false; // Too many arguments - if (*sig == 0 || (*sig & KSIG_ELLIPSIS)) - return true; - - return false; // Too few arguments -} - void Kernel::setDefaultKernelNames() { _kernelNames = Common::StringArray(s_defaultKernelNames, ARRAYSIZE(s_defaultKernelNames)); diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 9b4a11f132..ef587194d6 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -96,20 +96,23 @@ struct SelectorCache; // from selector.h // ---- Kernel signatures ----------------------------------------------------- - -// Compiled signatures +// internal kernel signature data enum { - KSIG_LIST = 0x01, - KSIG_NODE = 0x02, - KSIG_OBJECT = 0x04, - KSIG_REF = 0x08, - KSIG_ARITHMETIC = 0x10, - KSIG_UNINITIALIZED = 0x20, - KSIG_NULL = 0x40, - KSIG_ANY = 0x5f, - KSIG_ELLIPSIS = 0x80 + SIG_TYPE_NULL = 0x01, // may be 0:0 [0] + SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null + SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparsion + SIG_TYPE_OBJECT = 0x10, // may be object [o] + SIG_TYPE_REFERENCE = 0x20, // may be reference [r] + SIG_TYPE_LIST = 0x40, // may be list [l] + SIG_TYPE_NODE = 0x80, // may be node [n] + SIG_IS_OPTIONAL = 0x100, // is optional + SIG_NEEDS_MORE = 0x200, // needs at least one additional parameter following + SIG_MORE_MAY_FOLLOW = 0x400, // may have more parameters of the same type following }; +// this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere +#define SIG_MAYBE_ANY (SIG_TYPE_NULL | SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_LIST | SIG_TYPE_NODE) + // ---------------------------------------------------------------------------- /* Generic description: */ @@ -132,7 +135,7 @@ struct KernelFuncWithSignature { KernelFunc *func; /**< The actual function */ Common::String origName; /**< Original name, in case we couldn't map it */ bool isDummy; - char *signature; + uint16 *signature; const SciWorkaroundEntry *workarounds; }; @@ -175,16 +178,15 @@ public: * If no signature is given (i.e., if sig is NULL), this is always * treated as a match. * - * @param segMan pointer to the segment manager * @param sig signature to test against * @param argc number of arguments to test * @param argv argument list * @return true if the signature was matched, false otherwise */ - bool signatureMatch(const char *sig, int argc, const reg_t *argv); + bool signatureMatch(const uint16 *sig, int argc, const reg_t *argv); // Prints out debug information in case a signature check fails - void signatureDebug(const char *sig, int argc, const reg_t *argv); + void signatureDebug(const uint16 *sig, int argc, const reg_t *argv); /** * Determines the type of the object indicated by reg. -- cgit v1.2.3 From 63c439a858b96adbfb439651047b293d66947f19 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 5 Jul 2010 14:46:09 +0000 Subject: SCI: fix compilation issues from r50678 svn-id: r50679 --- engines/sci/engine/kernel.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index ef587194d6..a0b91b8601 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -107,7 +107,7 @@ enum { SIG_TYPE_NODE = 0x80, // may be node [n] SIG_IS_OPTIONAL = 0x100, // is optional SIG_NEEDS_MORE = 0x200, // needs at least one additional parameter following - SIG_MORE_MAY_FOLLOW = 0x400, // may have more parameters of the same type following + SIG_MORE_MAY_FOLLOW = 0x400 // may have more parameters of the same type following }; // this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere -- cgit v1.2.3 From 00dfb4db2968d46ca8052f2020143254c8926805 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 5 Jul 2010 16:08:43 +0000 Subject: SAGA: Fix warning on systems where enum's are unsigned svn-id: r50685 --- engines/saga/font.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/saga/font.h b/engines/saga/font.h index f290384e87..d8b1da30b9 100644 --- a/engines/saga/font.h +++ b/engines/saga/font.h @@ -190,7 +190,7 @@ class Font { } } bool valid(FontId fontId) { - return ((fontId >= 0) && (fontId < _loadedFonts)); + return (fontId < _loadedFonts); } int getByteLen(int numBits) const { int byteLength = numBits / 8; -- cgit v1.2.3 From 0d317c40a2f2354438dff4b8560da24643283dde Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 5 Jul 2010 19:31:32 +0000 Subject: SCI: fixing kDrawCel signature for kq6 svn-id: r50703 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4c6fb4cf83..88a7e4026b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -264,7 +264,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, - { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r)", NULL, NULL }, + { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // for kq6 hires { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL }, { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL }, -- cgit v1.2.3 From 1443a2721c77e4336dd894e66a377950b4f23273 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 5 Jul 2010 20:10:56 +0000 Subject: Fix update of GUI options, which only differ in the language setting. svn-id: r50706 --- engines/advancedDetector.cpp | 2 +- engines/scumm/detection.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/advancedDetector.cpp b/engines/advancedDetector.cpp index 974970ff0f..315763a6da 100644 --- a/engines/advancedDetector.cpp +++ b/engines/advancedDetector.cpp @@ -306,7 +306,7 @@ Common::Error AdvancedMetaEngine::createInstance(OSystem *syst, Engine **engine) // If the GUI options were updated, we catch this here and update them in the users config // file transparently. - Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions); + Common::updateGameGUIOptions(agdDesc->guioptions | params.guioptions, getGameGUIOptionsDescriptionLanguage(agdDesc->language)); debug(2, "Running %s", toGameDescriptor(*agdDesc, params.list).description().c_str()); if (!createInstance(syst, engine, agdDesc)) diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index 407b139c7e..c3a9120093 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -1024,7 +1024,7 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co // If the GUI options were updated, we catch this here and update them in the users config // file transparently. - Common::updateGameGUIOptions(res.game.guioptions); + Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language)); // Finally, we have massaged the GameDescriptor to our satisfaction, and can // instantiate the appropriate game engine. Hooray! -- cgit v1.2.3 From cffcc3d9360dbbadec4a3e18c3b6ca64dfc27995 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 5 Jul 2010 20:25:33 +0000 Subject: SCI: fixing signature of kDoSound (fading related) thx to Ceriand svn-id: r50707 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 88a7e4026b..0d0b9a30d3 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -304,7 +304,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL }, { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(iii)(i)", NULL, NULL }, // subop + { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", NULL, NULL }, // subop { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, -- cgit v1.2.3 From 0c3cbcbfc57c6c355d7106aa6be3faa7dd2f8590 Mon Sep 17 00:00:00 2001 From: Johannes Schickel Date: Mon, 5 Jul 2010 21:18:25 +0000 Subject: Prevent SCUMM from adding gui options based on user flags into the config file (regression from r50706). svn-id: r50710 --- engines/scumm/detection.cpp | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index c3a9120093..9721c75677 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -1005,6 +1005,10 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co debug(1, "Using MD5 '%s'", res.md5.c_str()); } + // If the GUI options were updated, we catch this here and update them in the users config + // file transparently. + Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language)); + // Check for a user override of the platform. We allow the user to override // the platform, to make it possible to add games which are not yet in // our MD5 database but require a specific platform setting. @@ -1021,11 +1025,6 @@ Common::Error ScummMetaEngine::createInstance(OSystem *syst, Engine **engine) co // TODO: Maybe allow the null driver, too? if (res.game.platform == Common::kPlatformFMTowns && res.game.version == 3) res.game.midi = MDT_TOWNS; - - // If the GUI options were updated, we catch this here and update them in the users config - // file transparently. - Common::updateGameGUIOptions(res.game.guioptions, getGameGUIOptionsDescriptionLanguage(res.language)); - // Finally, we have massaged the GameDescriptor to our satisfaction, and can // instantiate the appropriate game engine. Hooray! switch (res.game.version) { -- cgit v1.2.3 From 0c411d66cef3c79f077df46882518e786ec811f2 Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Tue, 6 Jul 2010 07:42:25 +0000 Subject: SCI: Simplified op_div and op_mod, removed some variables and removed the pointless OBJ_PROPERTY wrapper svn-id: r50719 --- engines/sci/engine/vm.cpp | 75 ++++++++++++++++++++--------------------------- 1 file changed, 32 insertions(+), 43 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 83bcae9673..b1e6eead0e 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -428,10 +428,6 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define WRITE_VAR16(type, index, value) WRITE_VAR(type, index, make_reg(0, value)); #define ACC_ARITHMETIC_L(op) make_reg(0, (op validate_arithmetic(s->r_acc))) -#define ACC_AUX_LOAD() aux_acc = signed_validate_arithmetic(s->r_acc) -#define ACC_AUX_STORE() s->r_acc = make_reg(0, aux_acc) - -#define OBJ_PROPERTY(o, p) (validate_property(o, p)) // Operating on the stack // 16 bit: @@ -940,27 +936,23 @@ int readPMachineInstruction(const byte *src, byte &extOpcode, int16 opparams[4]) void run_vm(EngineState *s, bool restoring) { assert(s); - unsigned int code_buf_size = 0 ; // (Avoid spurious warning) int temp; - int16 aux_acc; // Auxiliary 16 bit accumulator reg_t r_temp; // Temporary register StackPtr s_temp; // Temporary stack pointer int16 opparams[4]; // opcode parameters - s->restAdjust = 0; - // &rest adjusts the parameter count by this value + s->restAdjust = 0; // &rest adjusts the parameter count by this value // Current execution data: s->xs = &(s->_executionStack.back()); ExecStack *xs_new = NULL; Object *obj = s->_segMan->getObject(s->xs->objp); + Script *scr = 0; Script *local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); int old_executionStackBase = s->executionStackBase; // Used to detect the stack bottom, for "physical" returns - const byte *code_buf = NULL; // (Avoid spurious warning) - if (!local_script) { + if (!local_script) error("run_vm(): program counter gone astray (local_script pointer is null)"); - } if (!restoring) s->executionStackBase = s->_executionStack.size() - 1; @@ -981,15 +973,13 @@ void run_vm(EngineState *s, bool restoring) { return; // Stop processing if (s->_executionStackPosChanged) { - Script *scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); + scr = s->_segMan->getScriptIfLoaded(s->xs->addr.pc.segment); if (!scr) error("No script in segment %d", s->xs->addr.pc.segment); s->xs = &(s->_executionStack.back()); s->_executionStackPosChanged = false; obj = s->_segMan->getObject(s->xs->objp); - code_buf = scr->getBuf(); - code_buf_size = scr->getBufSize(); local_script = s->_segMan->getScriptIfLoaded(s->xs->local_segment); if (!local_script) { // FIXME: Why does this happen? Is the script not loaded yet at this point? @@ -1034,13 +1024,13 @@ void run_vm(EngineState *s, bool restoring) { s->variablesMax[VAR_TEMP] = s->xs->sp - s->xs->fp; - if (s->xs->addr.pc.offset >= code_buf_size) + if (s->xs->addr.pc.offset >= scr->getBufSize()) error("run_vm(): program counter gone astray, addr: %d, code buffer size: %d", - s->xs->addr.pc.offset, code_buf_size); + s->xs->addr.pc.offset, scr->getBufSize()); // Get opcode byte extOpcode; - s->xs->addr.pc.offset += readPMachineInstruction(code_buf + s->xs->addr.pc.offset, extOpcode, opparams); + s->xs->addr.pc.offset += readPMachineInstruction(scr->getBuf() + s->xs->addr.pc.offset, extOpcode, opparams); const byte opcode = extOpcode >> 1; switch (opcode) { @@ -1117,18 +1107,16 @@ void run_vm(EngineState *s, bool restoring) { s->r_acc = ACC_ARITHMETIC_L(((int16)POP()) * (int16)/*acc*/); break; - case op_div: // 0x04 (04) - ACC_AUX_LOAD(); - aux_acc = aux_acc != 0 ? ((int16)POP()) / aux_acc : 0; - ACC_AUX_STORE(); + case op_div: { // 0x04 (04) + int16 divisor = signed_validate_arithmetic(s->r_acc); + s->r_acc = make_reg(0, (divisor != 0 ? ((int16)POP()) / divisor : 0)); break; - - case op_mod: // 0x05 (05) - ACC_AUX_LOAD(); - aux_acc = aux_acc != 0 ? ((int16)POP()) % aux_acc : 0; - ACC_AUX_STORE(); + } + case op_mod: { // 0x05 (05) + int16 modulo = signed_validate_arithmetic(s->r_acc); + s->r_acc = make_reg(0, (modulo != 0 ? ((int16)POP()) % modulo : 0)); break; - + } case op_shr: // 0x06 (06) // Shift right logical s->r_acc = ACC_ARITHMETIC_L(((uint16)POP()) >> /*acc*/); @@ -1596,48 +1584,48 @@ void run_vm(EngineState *s, bool restoring) { case op_pToa: // 0x31 (49) // Property To Accumulator - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); + s->r_acc = validate_property(obj, (opparams[0] >> 1)); break; case op_aTop: // 0x32 (50) // Accumulator To Property - OBJ_PROPERTY(obj, (opparams[0] >> 1)) = s->r_acc; + validate_property(obj, (opparams[0] >> 1)) = s->r_acc; break; case op_pTos: // 0x33 (51) // Property To Stack - PUSH32(OBJ_PROPERTY(obj, opparams[0] >> 1)); + PUSH32(validate_property(obj, opparams[0] >> 1)); break; case op_sTop: // 0x34 (52) // Stack To Property - OBJ_PROPERTY(obj, (opparams[0] >> 1)) = POP32(); + validate_property(obj, (opparams[0] >> 1)) = POP32(); break; case op_ipToa: // 0x35 (53) // Incement Property and copy To Accumulator - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/); + s->r_acc = validate_property(obj, (opparams[0] >> 1)); + s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(1 + /*acc*/); break; case op_dpToa: { // 0x36 (54) // Decrement Property and copy To Accumulator - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)); - s->r_acc = OBJ_PROPERTY(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/); + s->r_acc = validate_property(obj, (opparams[0] >> 1)); + s->r_acc = validate_property(obj, (opparams[0] >> 1)) = ACC_ARITHMETIC_L(-1 + /*acc*/); break; } case op_ipTos: // 0x37 (55) // Increment Property and push to Stack - validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); - temp = ++OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; + validate_arithmetic(validate_property(obj, (opparams[0] >> 1))); + temp = ++validate_property(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; case op_dpTos: // 0x38 (56) // Decrement Property and push to Stack - validate_arithmetic(OBJ_PROPERTY(obj, (opparams[0] >> 1))); - temp = --OBJ_PROPERTY(obj, (opparams[0] >> 1)).offset; + validate_arithmetic(validate_property(obj, (opparams[0] >> 1))); + temp = --validate_property(obj, (opparams[0] >> 1)).offset; PUSH(temp); break; @@ -1656,9 +1644,9 @@ void run_vm(EngineState *s, bool restoring) { s->r_acc.offset = s->xs->addr.pc.offset + opparams[0]; } - if (s->r_acc.offset >= code_buf_size) { + if (s->r_acc.offset >= scr->getBufSize()) { error("VM: lofsa operation overflowed: %04x:%04x beyond end" - " of script (at %04x)\n", PRINT_REG(s->r_acc), code_buf_size); + " of script (at %04x)\n", PRINT_REG(s->r_acc), scr->getBufSize()); } break; @@ -1677,9 +1665,9 @@ void run_vm(EngineState *s, bool restoring) { r_temp.offset = s->xs->addr.pc.offset + opparams[0]; } - if (r_temp.offset >= code_buf_size) { + if (r_temp.offset >= scr->getBufSize()) { error("VM: lofss operation overflowed: %04x:%04x beyond end" - " of script (at %04x)", PRINT_REG(r_temp), code_buf_size); + " of script (at %04x)", PRINT_REG(r_temp), scr->getBufSize()); } PUSH32(r_temp); break; @@ -1701,6 +1689,7 @@ void run_vm(EngineState *s, bool restoring) { PUSH32(s->xs->objp); } else { // Debug opcode op_file, skip null-terminated string (file name) + const byte *code_buf = scr->getBuf(); while (code_buf[s->xs->addr.pc.offset++]) ; } break; -- cgit v1.2.3 From f3a935351b7977517876e2342471c1330a5db7ff Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 6 Jul 2010 11:03:10 +0000 Subject: SCI: fix regression of r50599 - broken greyed font drawing svn-id: r50720 --- engines/sci/graphics/font.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/graphics/font.cpp b/engines/sci/graphics/font.cpp index ce4c1fafb3..852771d081 100644 --- a/engines/sci/graphics/font.cpp +++ b/engines/sci/graphics/font.cpp @@ -83,11 +83,12 @@ void GfxFontFromResource::draw(uint16 chr, int16 top, int16 left, byte color, bo int charHeight = MIN(getCharHeight(chr), _screen->getHeight() - top); byte b = 0, mask = 0xFF; int y = 0; + int16 greyedTop = top; byte *pIn = getCharData(chr); for (int i = 0; i < charHeight; i++, y++) { if (greyedOutput) - mask = top++ % 2 ? 0xAA : 0x55; + mask = greyedTop++ % 2 ? 0xAA : 0x55; for (int done = 0; done < charWidth; done++) { if ((done & 7) == 0) // fetching next data byte b = *(pIn++) & mask; -- cgit v1.2.3 From 2d5dabee30b842a6670f4d6e956c45e37389e344 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 6 Jul 2010 11:16:11 +0000 Subject: SCI: implemented pauseSound inside kMenuSelect svn-id: r50721 --- engines/sci/engine/kmenu.cpp | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 54543d783f..69ec07559e 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -90,10 +90,17 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) { reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) { reg_t eventObject = argv[0]; - //bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : false; + bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true; + reg_t result; - // TODO: pauseSound implementation - return g_sci->_gfxMenu->kernelSelect(eventObject); + if (pauseSound) + g_sci->_soundCmd->pauseAll(true); + + result = g_sci->_gfxMenu->kernelSelect(eventObject); + + if (pauseSound) + g_sci->_soundCmd->pauseAll(false); + return result; } } // End of namespace Sci -- cgit v1.2.3 From 3f7dc9e0e2e4d043b2234b7b66981e16eb8a84b1 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 6 Jul 2010 11:32:10 +0000 Subject: Added extra initialisation code for the game's global variables list svn-id: r50722 --- engines/m4/globals.cpp | 1 + engines/m4/globals.h | 10 +++- engines/m4/mads_logic.cpp | 113 +++++++++++++++++++++++++++++++++++++++++++++- engines/m4/mads_logic.h | 5 ++ 4 files changed, 125 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/m4/globals.cpp b/engines/m4/globals.cpp index fb95adf29f..a96229a0b3 100644 --- a/engines/m4/globals.cpp +++ b/engines/m4/globals.cpp @@ -284,6 +284,7 @@ MadsGlobals::MadsGlobals(MadsEngine *vm): Globals(vm) { sceneNumber = -1; for (int i = 0; i < 3; ++i) actionNouns[i] = 0; + _difficultyLevel = 0; } MadsGlobals::~MadsGlobals() { diff --git a/engines/m4/globals.h b/engines/m4/globals.h index 5ab1ccd9a6..3fc31b4ec2 100644 --- a/engines/m4/globals.h +++ b/engines/m4/globals.h @@ -150,7 +150,7 @@ public: void pauseGame(bool value); }; -#define TOTAL_NUM_VARIABLES 256 +#define TOTAL_NUM_VARIABLES 210 #define PLAYER_INVENTORY 2 @@ -224,6 +224,11 @@ struct MadsConfigData { int screenFades; }; +#define GET_GLOBAL(x) (_madsVm->globals()->_globals[x]) +#define GET_GLOBAL32(x) (((uint32)_madsVm->globals()->_globals[x + 1] << 16) | _madsVm->globals()->_globals[x]) +#define SET_GLOBAL(x,y) _madsVm->globals()->_globals[x] = y +#define SET_GLOBAL32(x,y) { _madsVm->globals()->_globals[x] = (y) & 0xffff; _madsVm->globals()->_globals[(x) + 1] = (y) >> 16; } + typedef Common::HashMap IntStorage; class MadsGlobals : public Globals { @@ -246,7 +251,7 @@ public: ~MadsGlobals(); // MADS variables - int _globals[TOTAL_NUM_VARIABLES]; + uint16 _globals[TOTAL_NUM_VARIABLES]; MadsConfigData _config; bool playerSpriteChanged; MadsDialogType dialogType; @@ -255,6 +260,7 @@ public: int16 _nextSceneId; uint16 actionNouns[3]; IntStorage _dataMap; + int _difficultyLevel; void loadMadsVocab(); uint32 getVocabSize() { return _madsVocab.size(); } diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index c90fb11c11..8561963208 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -29,6 +29,114 @@ namespace M4 { +void MadsGameLogic::initialiseGlobals() { + // Clear the entire globals list + Common::set_to(&_madsVm->globals()->_globals[0], &_madsVm->globals()->_globals[TOTAL_NUM_VARIABLES], 0); + + SET_GLOBAL(4, 8); + SET_GLOBAL(33, 1); + SET_GLOBAL(10, 0xFFFF); + SET_GLOBAL(13, 0xFFFF); + SET_GLOBAL(15, 0xFFFF); + SET_GLOBAL(19, 0xFFFF); + SET_GLOBAL(20, 0xFFFF); + SET_GLOBAL(21, 0xFFFF); + SET_GLOBAL(95, 0xFFFF); + + // TODO: unknown sub call + + // Put the values 0 through 3 in a random ordering in global slots 83 - 86 + for (int idx = 0; idx < 4; ) { + int randVal = _madsVm->_random->getRandomNumber(4); + SET_GLOBAL(83 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(83 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + // Put the values 0 through 3 in a random ordering in global slots 87 - 90 + for (int idx = 0; idx < 4; ) { + int randVal = _madsVm->_random->getRandomNumber(3); + SET_GLOBAL(87 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(87 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + // Miscellaneous global settings + SET_GLOBAL(120, 501); + SET_GLOBAL(121, 0xFFFF); + SET_GLOBAL(110, 0xFFFF); + SET_GLOBAL(119, 1); + SET_GLOBAL(134, 4); + SET_GLOBAL(190, 201); + SET_GLOBAL(191, 301); + SET_GLOBAL(192, 413); + SET_GLOBAL(193, 706); + SET_GLOBAL(194, 801); + SET_GLOBAL(195, 551); + SET_GLOBAL(196, 752); + + // Fill out the globals 200 - 209 with unique random number values less than 10000 + for (int idx = 0; idx < 10; ) { + int randVal = _madsVm->_random->getRandomNumber(9999); + SET_GLOBAL(200 + idx, randVal); + + // Check whether the given value has already been used + bool flag = false; + for (int idx2 = 0; idx2 < idx; ++idx2) { + if (randVal == GET_GLOBAL(87 + idx2)) + flag = true; + } + + if (!flag) + ++idx; + } + + switch (_madsVm->globals()->_difficultyLevel) { + case 1: + // Very hard + SET_GLOBAL(35, 0); + // TODO: object set room + SET_GLOBAL(137, 5); + SET_GLOBAL(136, 0); + break; + + case 2: + // Hard + SET_GLOBAL(35, 0); + // TODO: object set room + SET_GLOBAL(136, 0xFFFF); + SET_GLOBAL(137, 6); + break; + + case 3: + // Easy + SET_GLOBAL(35, 2); + // TODO: object set room + break; + } + + _madsVm->_player._direction = 8; + _madsVm->_player._direction2 = 8; + + // TODO: unknown processing routine getting called for 'RXM' and 'ROX' +} + /*--------------------------------------------------------------------------*/ const char *MadsSceneLogic::formAnimName(char sepChar, int16 suffixNum) { @@ -299,6 +407,7 @@ void MadsSceneLogic::enterScene() { _madsVm->_player._playerPos = Common::Point(68, 140); _madsVm->_player._direction = 4; _madsVm->_player._visible = false; + _madsVm->_player._stepEnabled = false; dataMap()[0x56FC] = 0; dataMap()[0x5482] = 0; @@ -323,9 +432,9 @@ void MadsSceneLogic::sceneStep() { case 71: _madsVm->globals()->_globals[10] = 0; _madsVm->_player._visible = true; - dataMap()[0x56FC] = 0; + _madsVm->_player._stepEnabled = true; - _madsVm->scene()->_newTimeout = _madsVm->_currentTimer - _madsVm->scene()->_ticksAmount; + _madsVm->_player._priorTimer = _madsVm->_currentTimer - _madsVm->_player._ticksAmount; break; case 72: case 73: diff --git a/engines/m4/mads_logic.h b/engines/m4/mads_logic.h index 3c6cb8edf1..98d6df6163 100644 --- a/engines/m4/mads_logic.h +++ b/engines/m4/mads_logic.h @@ -63,6 +63,11 @@ public: void sceneStep(); }; +class MadsGameLogic { +public: + static void initialiseGlobals(); +}; + } #endif -- cgit v1.2.3 From c89fe5f6d56b6d6e11b7d642e85633bc86098ce8 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Tue, 6 Jul 2010 11:33:09 +0000 Subject: Added support for idle character animations svn-id: r50723 --- engines/m4/assets.cpp | 4 +- engines/m4/assets.h | 4 +- engines/m4/m4.cpp | 2 + engines/m4/mads_player.cpp | 190 +++++++++++++++++++++++++++++++++++++++++---- engines/m4/mads_player.h | 11 ++- engines/m4/mads_scene.cpp | 8 +- engines/m4/mads_views.cpp | 13 ++-- engines/m4/mads_views.h | 3 +- 8 files changed, 205 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/m4/assets.cpp b/engines/m4/assets.cpp index 9cfb7afc4c..23122eb960 100644 --- a/engines/m4/assets.cpp +++ b/engines/m4/assets.cpp @@ -632,9 +632,9 @@ int32 AssetManager::getSpriteFrameCount(int32 hash) { //-------------------------------------------------------------------------- MadsSpriteSetCharInfo::MadsSpriteSetCharInfo(Common::SeekableReadStream *s) { - _frameNumber = s->readByte(); + _totalFrames = s->readByte(); s->skip(1); - _hasIdling = s->readUint16LE() != 0; + _numEntries = s->readUint16LE(); for (int i = 0; i < 16; ++i) _frameList[i] = s->readUint16LE(); diff --git a/engines/m4/assets.h b/engines/m4/assets.h index e9902d8aa6..3ae7fb2e22 100644 --- a/engines/m4/assets.h +++ b/engines/m4/assets.h @@ -106,8 +106,8 @@ class MadsSpriteSetCharInfo { public: MadsSpriteSetCharInfo(Common::SeekableReadStream *s); - int _frameNumber; - int _hasIdling; + int _totalFrames; + int _numEntries; int _frameList2[16]; int _frameList[16]; int _ticksList[16]; diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index f5c6d260a9..a999a6bd5a 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -538,6 +538,8 @@ Common::Error MadsEngine::run() { //printf("%s\n----------\n", _globals->loadMessage(i)); if (getGameType() == GType_RexNebular) { + MadsGameLogic::initialiseGlobals(); + _scene = NULL; loadMenu(MAIN_MENU); } else { diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp index 57cb9eefd3..bb7a1b406d 100644 --- a/engines/m4/mads_player.cpp +++ b/engines/m4/mads_player.cpp @@ -38,6 +38,9 @@ MadsPlayer::MadsPlayer() { _direction = 0; _direction2 = 0; _forceRefresh = true; + _stepEnabled = true; + _ticksAmount = 3; + _priorTimer = 0; _visible = true; _priorVisible = false; _visible3 = false; @@ -53,7 +56,7 @@ MadsPlayer::MadsPlayer() { _frameNum = 0; _frameOffset = 0; _unk1 = 0; - _newFrame = 0; + _frameCount = 0; _frameListIndex = 0; _actionIndex = 0; resetActionList(); @@ -154,7 +157,7 @@ void MadsPlayer::update() { if (equal) // Undo the prior expiry of the player sprite - slot.spriteType = SPRITE_ZERO; + s2.spriteType = SPRITE_ZERO; else slotIndex = -1; } @@ -175,13 +178,13 @@ void MadsPlayer::update() { } /** - * Idling animation for player + * Updates the animation frame for the player */ -void MadsPlayer::idle() { +void MadsPlayer::updateFrame() { SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); assert(spriteSet._charInfo); - if (!spriteSet._charInfo->_hasIdling) { + if (!spriteSet._charInfo->_numEntries) { _frameNum = 1; } else { _frameListIndex = _actionList[_actionIndex]; @@ -204,7 +207,7 @@ void MadsPlayer::idle() { if (frameIndex == 0) setTicksAmount(); else - _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; + _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksList[frameIndex]; } } @@ -223,19 +226,103 @@ void MadsPlayer::setupFrame() { _unk1 = MAX(spriteSet._charInfo->_unk1, 100); setTicksAmount(); - _newFrame = spriteSet._charInfo->_frameNumber; - if (_newFrame == 0) - _newFrame = spriteSet.getCount(); + _frameCount = spriteSet._charInfo->_totalFrames; + if (_frameCount == 0) + _frameCount = spriteSet.getCount(); _yScale = spriteSet._charInfo->_yScale; - if ((_frameNum <= 0) || (_frameNum > _newFrame)) + if ((_frameNum <= 0) || (_frameNum > _frameCount)) _frameNum = 1; _forceRefresh = true; } void MadsPlayer::step() { + if (_visible && _stepEnabled && !_moving && (_direction == _direction2) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { + if (_actionIndex == 0) { + int randVal = _vm->_random->getRandomNumber(29999); + + if (GET_GLOBAL(0) == SEX_MALE) { + switch (_direction) { + case 1: + case 3: + case 7: + case 9: + if (randVal < 200) { + queueAction(-1, 0); + queueAction(1, 0); + } + break; + + case 2: + if (randVal < 500) { + for (int i = 0; i < 10; ++i) + queueAction((randVal < 250) ? 1 : 2, 0); + } else if (randVal < 750) { + for (int i = 0; i < 5; ++i) + queueAction(1, 0); + queueAction(0, 0); + for (int i = 0; i < 5; ++i) + queueAction(2, 0); + } + break; + + case 4: + case 6: + if (randVal < 500) { + for (int i = 0; i < 10; ++i) + queueAction(1, 0); + } + break; + + case 5: + case 8: + if (randVal < 200) { + queueAction(-1, 0); + queueAction(1, 0); + } + break; + } + } + } + + SET_GLOBAL32(2, GET_GLOBAL32(2) + 6); + } + + if (GET_GLOBAL(138) == 1) { + uint32 diff = _madsVm->_currentTimer - GET_GLOBAL32(142); + if (diff > 60) { + SET_GLOBAL32(144, GET_GLOBAL32(144) + 1); + } else { + SET_GLOBAL32(144, GET_GLOBAL32(144) + diff); + } + + SET_GLOBAL32(142, _madsVm->_currentTimer); + } +} + +void MadsPlayer::nextFrame() { + if (_madsVm->_currentTimer >= (_priorTimer + _ticksAmount)) { + _priorTimer = _madsVm->_currentTimer; + + if (_moving) + move(); + else + idle(); + + // Post update logic + if (_moving) { + ++_frameNum; + if (_frameNum > _frameCount) + _frameNum = 1; + _forceRefresh = true; + } else if (!_forceRefresh) { + idle(); + } + // Final update + update(); + } } int MadsPlayer::getScale(int yp) { @@ -262,9 +349,9 @@ int MadsPlayer::getSpriteSlot() { void MadsPlayer::setTicksAmount() { SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); assert(spriteSet._charInfo); - _madsVm->scene()->_ticksAmount = spriteSet._charInfo->_ticksAmount; - if (_madsVm->scene()->_ticksAmount == 0) - _madsVm->scene()->_ticksAmount = 6; + _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount; + if (_madsVm->_player._ticksAmount == 0) + _madsVm->_player._ticksAmount = 6; } void MadsPlayer::resetActionList() { @@ -279,7 +366,7 @@ int MadsPlayer::queueAction(int action1, int action2) { SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); assert(spriteSet._charInfo); - if ((spriteSet._charInfo->_hasIdling) && (_actionIndex < 11)) { + if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) { ++_actionIndex; _actionList[_actionIndex] = action1; _actionList2[_actionIndex] = action2; @@ -289,4 +376,79 @@ int MadsPlayer::queueAction(int action1, int action2) { return true; } +void MadsPlayer::idle() { + if (_direction != _direction2) { + // The direction has changed, so reset for new direction + dirChanged(); + return; + } + + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + assert(spriteSet._charInfo); + if (spriteSet._charInfo->_numEntries == 0) + // No entries, so exit immediately + return; + + int frameIndex = ABS(_frameListIndex); + int direction = (_frameListIndex < 0) ? -1 : 1; + + if (frameIndex >= spriteSet._charInfo->_numEntries) + // Reset back to the start of the list + _frameListIndex = 0; + else { + _frameNum += direction; + _forceRefresh = true; + + if (spriteSet._charInfo->_frameList2[frameIndex] < _frameNum) { + _unk3 = _unk2; + updateFrame(); + } + if (spriteSet._charInfo->_frameList[frameIndex] < _frameNum) { + _unk3 = _unk2; + updateFrame(); + } + } +} + +void MadsPlayer::move() { + // TODO: Handle player movement +} + +void MadsPlayer::dirChanged() { + int dirIndex = 0, dirIndex2 = 0; + int newDir = 0, newDir2 = 0; + + if (_direction != _direction2) { + // Find the index for the given direction in the player direction list + int tempDir = _direction; + do { + ++dirIndex; + newDir += tempDir; + tempDir = _directionListIndexes[tempDir + 10]; + } while (tempDir != _direction2); + } + + + if (_direction != _direction2) { + // Find the index for the given direction in the player direction list + int tempDir = _direction; + do { + ++dirIndex2; + newDir2 += tempDir; + tempDir = _directionListIndexes[tempDir + 10]; + } while (tempDir != _direction2); + } + + int diff = dirIndex - dirIndex2; + if (diff == 0) + diff = newDir - newDir2; + + _direction = (diff >= 0) ? _directionListIndexes[_direction] : _directionListIndexes[_direction + 10]; + setupFrame(); + if ((_direction == _direction2) && !_moving) + updateFrame(); + + _priorTimer += 1; +} + } // End of namespace M4 diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h index 7285796309..7db45cae43 100644 --- a/engines/m4/mads_player.h +++ b/engines/m4/mads_player.h @@ -39,13 +39,19 @@ private: void setTicksAmount(); void resetActionList(); int queueAction(int v0, int v1); + void idle(); + void move(); + void dirChanged(); public: char _spritesPrefix[16]; int _spriteSetCount; bool _spriteSetsPresent[8]; Common::Point _playerPos; Common::Point _destPos; + uint32 _priorTimer; + uint _ticksAmount; int16 _direction, _direction2; + bool _stepEnabled; bool _visible, _priorVisible; bool _visible3; bool _forceRefresh; @@ -57,7 +63,7 @@ public: uint16 _frameOffset, _frameNum; bool _moving; int _unk1; - int _newFrame; + int _frameCount; int _frameListIndex; int _actionIndex; int _actionList[12]; @@ -71,9 +77,10 @@ public: bool loadSprites(const char *prefix); void update(); - void idle(); + void updateFrame(); void setupFrame(); void step(); + void nextFrame(); }; } // End of namespace M4 diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 66883dd13c..3e838fc1c0 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -167,7 +167,7 @@ void MadsScene::loadScene(int sceneNumber) { _madsVm->_player._destPos = _madsVm->_player._destPos; _madsVm->_player._direction2 = _madsVm->_player._direction; _madsVm->_player.setupFrame(); - _madsVm->_player.idle(); + _madsVm->_player.updateFrame(); // Purge resources _vm->res()->purge(); @@ -337,9 +337,15 @@ void MadsScene::updateState() { // Step through the scene _sceneLogic.sceneStep(); + _madsVm->_player.step(); + _madsVm->_player._unk3 = 0; + if (_abortTimersMode == ABORTMODE_1) _abortTimers = 0; + // Handle updating the player frame + _madsVm->_player.nextFrame(); + if ((_activeAnimation) && !_abortTimers) { _activeAnimation->update(); if (((MadsAnimation *) _activeAnimation)->freeFlag()) { diff --git a/engines/m4/mads_views.cpp b/engines/m4/mads_views.cpp index 580f54b1c0..d7e6435b14 100644 --- a/engines/m4/mads_views.cpp +++ b/engines/m4/mads_views.cpp @@ -426,15 +426,15 @@ int MadsKernelMessageList::add(const Common::Point &pt, uint fontColour, uint8 f for (int i = 0; i < 3; ++i) rec.actionNouns[i] = _madsVm->globals()->actionNouns[i]; - if (flags & KMSG_OWNER_TIMEOUT) - rec.frameTimer = _owner._ticksAmount + _owner._newTimeout; + if (flags & KMSG_PLAYER_TIMEOUT) + rec.frameTimer = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; return idx; } int MadsKernelMessageList::addQuote(int quoteId, int abortTimers, uint32 timeout) { const char *quoteStr = _madsVm->globals()->getQuote(quoteId); - return add(Common::Point(0, 0), 0x1110, KMSG_OWNER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr); + return add(Common::Point(0, 0), 0x1110, KMSG_PLAYER_TIMEOUT | KMSG_CENTER_ALIGN, abortTimers, timeout, quoteStr); } void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quoted) { @@ -450,8 +450,8 @@ void MadsKernelMessageList::scrollMessage(int msgIndex, int numTicks, bool quote _entries[msgIndex].asciiChar = *msgP; _entries[msgIndex].asciiChar2 = *(msgP + 1); - if (_entries[msgIndex].flags & KMSG_OWNER_TIMEOUT) - _entries[msgIndex].frameTimer2 = _owner._ticksAmount + _owner._newTimeout; + if (_entries[msgIndex].flags & KMSG_PLAYER_TIMEOUT) + _entries[msgIndex].frameTimer2 = _madsVm->_player._ticksAmount + _madsVm->_player._priorTimer; _entries[msgIndex].frameTimer = _entries[msgIndex].frameTimer2; } @@ -545,7 +545,7 @@ void MadsKernelMessageList::processText(int msgIndex) { } } - if (msg.flags & KMSG_OWNER_TIMEOUT) { + if (msg.flags & KMSG_PLAYER_TIMEOUT) { if (word_8469E != 0) { // TODO: Figure out various flags } else { @@ -1211,7 +1211,6 @@ MadsView::MadsView(View *view): _view(view), _dynamicHotspots(*this), _sequenceL _kernelMessages(*this), _spriteSlots(*this), _dirtyAreas(*this), _textDisplay(*this) { _textSpacing = -1; - _ticksAmount = 3; _newTimeout = 0; _abortTimers = 0; _abortTimers2 = 0; diff --git a/engines/m4/mads_views.h b/engines/m4/mads_views.h index ead6ae94bf..0604ae1ee1 100644 --- a/engines/m4/mads_views.h +++ b/engines/m4/mads_views.h @@ -149,7 +149,7 @@ public: #define TIMED_TEXT_SIZE 10 #define INDEFINITE_TIMEOUT 9999999 -enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_OWNER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10, +enum KernelMessageFlags {KMSG_QUOTED = 1, KMSG_PLAYER_TIMEOUT = 2, KMSG_SEQ_ENTRY = 4, KMSG_SCROLL = 8, KMSG_RIGHT_ALIGN = 0x10, KMSG_CENTER_ALIGN = 0x20, KMSG_EXPIRE = 0x40, KMSG_ACTIVE = 0x80}; class MadsKernelMessageEntry { @@ -395,7 +395,6 @@ public: MadsDirtyAreas _dirtyAreas; int _textSpacing; - int _ticksAmount; uint32 _newTimeout; int _abortTimers; int8 _abortTimers2; -- cgit v1.2.3 From a7cd1534c6d3a325e36db42314e22ff3d8bdc8dd Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 6 Jul 2010 14:10:09 +0000 Subject: SCI: fix regression of r50721 - pausing/resuming only on actual menu usage svn-id: r50724 --- engines/sci/engine/kmenu.cpp | 10 +--------- engines/sci/graphics/menu.cpp | 18 +++++++++++------- engines/sci/graphics/menu.h | 6 +++--- 3 files changed, 15 insertions(+), 19 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmenu.cpp b/engines/sci/engine/kmenu.cpp index 69ec07559e..c8a6e03556 100644 --- a/engines/sci/engine/kmenu.cpp +++ b/engines/sci/engine/kmenu.cpp @@ -91,16 +91,8 @@ reg_t kDrawMenuBar(EngineState *s, int argc, reg_t *argv) { reg_t kMenuSelect(EngineState *s, int argc, reg_t *argv) { reg_t eventObject = argv[0]; bool pauseSound = argc > 1 ? (argv[1].isNull() ? false : true) : true; - reg_t result; - if (pauseSound) - g_sci->_soundCmd->pauseAll(true); - - result = g_sci->_gfxMenu->kernelSelect(eventObject); - - if (pauseSound) - g_sci->_soundCmd->pauseAll(false); - return result; + return g_sci->_gfxMenu->kernelSelect(eventObject, pauseSound); } } // End of namespace Sci diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index d85d4456fc..f959ffb3a5 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -382,7 +382,7 @@ void GfxMenu::calculateMenuAndItemWidth() { } } -reg_t GfxMenu::kernelSelect(reg_t eventObject) { +reg_t GfxMenu::kernelSelect(reg_t eventObject, bool pauseSound) { int16 eventType = readSelectorValue(_segMan, eventObject, SELECTOR(type)); int16 keyPress, keyModifier; Common::Point mousePosition; @@ -407,9 +407,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case 0: break; case SCI_KEY_ESC: - interactiveShowMouse(); + interactiveStart(pauseSound); itemEntry = interactiveWithKeyboard(); - interactiveRestoreMouse(); + interactiveEnd(pauseSound); forceClaimed = true; break; default: @@ -445,9 +445,9 @@ reg_t GfxMenu::kernelSelect(reg_t eventObject) { case SCI_EVENT_MOUSE_PRESS: mousePosition = _cursor->getPosition(); if (mousePosition.y < 10) { - interactiveShowMouse(); + interactiveStart(pauseSound); itemEntry = interactiveWithMouse(); - interactiveRestoreMouse(); + interactiveEnd(pauseSound); forceClaimed = true; } break; @@ -632,12 +632,16 @@ void GfxMenu::invertMenuSelection(uint16 itemId) { _paint16->bitsShow(itemRect); } -void GfxMenu::interactiveShowMouse() { +void GfxMenu::interactiveStart(bool pauseSound) { _mouseOldState = _cursor->isVisible(); _cursor->kernelShow(); + if (pauseSound) + g_sci->_soundCmd->pauseAll(true); } -void GfxMenu::interactiveRestoreMouse() { +void GfxMenu::interactiveEnd(bool pauseSound) { + if (pauseSound) + g_sci->_soundCmd->pauseAll(false); if (!_mouseOldState) _cursor->kernelHide(); } diff --git a/engines/sci/graphics/menu.h b/engines/sci/graphics/menu.h index b72d518977..9a14d4c64a 100644 --- a/engines/sci/graphics/menu.h +++ b/engines/sci/graphics/menu.h @@ -92,7 +92,7 @@ public: reg_t kernelGetAttribute(uint16 menuId, uint16 itemId, uint16 attributeId); void drawBar(); - reg_t kernelSelect(reg_t eventObject); + reg_t kernelSelect(reg_t eventObject, bool pauseSound); void kernelDrawStatus(const char *text, int16 colorPen, int16 colorBack); void kernelDrawMenuBar(bool clear); @@ -103,8 +103,8 @@ private: void calculateMenuAndItemWidth(); void drawMenu(uint16 oldMenuId, uint16 newMenuId); void invertMenuSelection(uint16 itemId); - void interactiveShowMouse(); - void interactiveRestoreMouse(); + void interactiveStart(bool pauseSound); + void interactiveEnd(bool pauseSound); GuiMenuItemEntry *interactiveWithKeyboard(); GuiMenuItemEntry *interactiveWithMouse(); uint16 mouseFindMenuSelection(Common::Point mousePosition); -- cgit v1.2.3 From c349d7130c1716b5b87a5cb9f740f8467c16dde4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Tue, 6 Jul 2010 14:26:29 +0000 Subject: SCI: removing invalid reference error from signature checking, instead adding new type "invalid", so that full call parameter debug information is available svn-id: r50725 --- engines/sci/console.cpp | 5 ++++- engines/sci/engine/kernel.cpp | 5 +++-- engines/sci/engine/kernel.h | 1 + 3 files changed, 8 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 7e5d77d99a..e684532b08 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3149,7 +3149,7 @@ void Console::printBasicVarInfo(reg_t variable) { int segType = g_sci->getKernel()->findRegType(variable); SegManager *segMan = g_sci->getEngineState()->_segMan; - segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED; + segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_INVALID; switch (segType) { case SIG_TYPE_INTEGER: { @@ -3173,6 +3173,9 @@ void Console::printBasicVarInfo(reg_t variable) { case SIG_TYPE_UNINITIALIZED: DebugPrintf(" (uninitialized)"); break; + case SIG_TYPE_INVALID: + DebugPrintf(" (invalid)"); + break; default: DebugPrintf(" (??\?)"); } diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 0d0b9a30d3..2a378564bb 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -719,10 +719,10 @@ int Kernel::findRegType(reg_t reg) { // Otherwise it's an object SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); if (!mobj) - return 0; // Invalid + return SIG_TYPE_INVALID; if (!mobj->isValidOffset(reg.offset)) - error("[KERN] ref %04x:%04x is invalid", PRINT_REG(reg)); + return SIG_TYPE_INVALID; switch (mobj->getType()) { case SEG_TYPE_SCRIPT: @@ -762,6 +762,7 @@ static const SignatureDebugType signatureDebugTypeList[] = { { SIG_TYPE_NULL, "null" }, { SIG_TYPE_INTEGER, "integer" }, { SIG_TYPE_UNINITIALIZED, "uninitialized" }, + { SIG_TYPE_INVALID, "invalid" }, { SIG_TYPE_OBJECT, "object" }, { SIG_TYPE_REFERENCE, "reference" }, { SIG_TYPE_LIST, "list" }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a0b91b8601..719db41e8d 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -101,6 +101,7 @@ enum { SIG_TYPE_NULL = 0x01, // may be 0:0 [0] SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparsion + SIG_TYPE_INVALID = 0x08, // invalid segment or offset -> not allowable, only used for comparsion SIG_TYPE_OBJECT = 0x10, // may be object [o] SIG_TYPE_REFERENCE = 0x20, // may be reference [r] SIG_TYPE_LIST = 0x40, // may be list [l] -- cgit v1.2.3 From afd285005825926ee4f26b7ca5b20d2450efe211 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Tue, 6 Jul 2010 23:24:36 +0000 Subject: SCI: Add version to obsolete string This way, if we ever get rid of support for savegames with version <= 23, we can also get rid of this syncString() call. Without this change, it would have "infected" every new savegame version, forever. svn-id: r50730 --- engines/sci/engine/savegame.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index dd8c3ca31d..5d82786b9a 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -286,7 +286,7 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be savegame_version Common::String tmp; - s.syncString(tmp); // OBSOLETE: Used to be game_version + s.syncString(tmp, VER(9), VER(23)); // OBSOLETE: Used to be game_version s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be version // OBSOLETE: Saved menus. Skip all of the saved data @@ -746,7 +746,7 @@ void SegManager::reconstructClones() { if (!baseObj) error("Clone entry without a base class: %d", j); } // end for - } // end if + } // end if } // end for } -- cgit v1.2.3 From dd5f6f13e292e3ca8c63997fb1360fc39b5426e3 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Wed, 7 Jul 2010 11:02:11 +0000 Subject: Bugfixes and changed field names in the player class to be more explanatory. Implemented Ctrl-T to turn the player - the original game used Ctrl-U, but this is reserved by ScummVM for toggle Mute. svn-id: r50734 --- engines/m4/mads_logic.cpp | 2 +- engines/m4/mads_player.cpp | 44 ++++++++++++++++++++++---------------------- engines/m4/mads_player.h | 4 ++-- engines/m4/mads_scene.cpp | 8 ++++---- 4 files changed, 29 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/m4/mads_logic.cpp b/engines/m4/mads_logic.cpp index 8561963208..e451a306ef 100644 --- a/engines/m4/mads_logic.cpp +++ b/engines/m4/mads_logic.cpp @@ -132,7 +132,7 @@ void MadsGameLogic::initialiseGlobals() { } _madsVm->_player._direction = 8; - _madsVm->_player._direction2 = 8; + _madsVm->_player._newDirection = 8; // TODO: unknown processing routine getting called for 'RXM' and 'ROX' } diff --git a/engines/m4/mads_player.cpp b/engines/m4/mads_player.cpp index bb7a1b406d..8531a3ed44 100644 --- a/engines/m4/mads_player.cpp +++ b/engines/m4/mads_player.cpp @@ -36,7 +36,7 @@ const int MadsPlayer::_directionListIndexes[32] = { MadsPlayer::MadsPlayer() { _playerPos = Common::Point(160, 78); _direction = 0; - _direction2 = 0; + _newDirection = 0; _forceRefresh = true; _stepEnabled = true; _ticksAmount = 3; @@ -46,8 +46,8 @@ MadsPlayer::MadsPlayer() { _visible3 = false; _yScale = 0; _moving = false; + _spriteListStart = 0; _spriteListIdx = 0; - _spriteListIdx2 = 0; _spritesChanged = true; _currentScale = 0; strcpy(_spritesPrefix, ""); @@ -93,7 +93,7 @@ bool MadsPlayer::loadSprites(const char *prefix) { int setIndex = _madsVm->scene()->_spriteSlots.addSprites(setName, true, SPRITE_SET_CHAR_INFO); if (setIndex < 0) { - if (idx < 7) + if (idx < 5) break; _spriteSetsPresent[idx] = false; } else { @@ -101,7 +101,7 @@ bool MadsPlayer::loadSprites(const char *prefix) { } if (idx == 0) - _spriteListIdx = setIndex; + _spriteListStart = setIndex; } result = 0; @@ -141,7 +141,7 @@ void MadsPlayer::update() { MadsSpriteSlot slot; slot.spriteType = FOREGROUND_SPRITE; slot.seqIndex = PLAYER_SEQ_INDEX; - slot.spriteListIndex = _spriteListIdx + _spriteListIdx2; + slot.spriteListIndex = _spriteListStart + _spriteListIdx; slot.frameNumber = _frameOffset + _frameNum; slot.xp = _playerPos.x; slot.yp = _playerPos.y + (_yScale * newScale) / 100; @@ -181,7 +181,7 @@ void MadsPlayer::update() { * Updates the animation frame for the player */ void MadsPlayer::updateFrame() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); assert(spriteSet._charInfo); if (!spriteSet._charInfo->_numEntries) { @@ -214,14 +214,14 @@ void MadsPlayer::updateFrame() { void MadsPlayer::setupFrame() { resetActionList(); _frameOffset = 0; - _spriteListIdx2 = _directionListIndexes[_direction]; - if (!_spriteSetsPresent[_spriteListIdx2]) { + _spriteListIdx = _directionListIndexes[_direction]; + if (!_spriteSetsPresent[_spriteListIdx]) { // Direction isn't present, so use alternate direction, with entries flipped - _spriteListIdx2 -= 4; + _spriteListIdx -= 4; _frameOffset = 0x8000; } - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); assert(spriteSet._charInfo); _unk1 = MAX(spriteSet._charInfo->_unk1, 100); setTicksAmount(); @@ -238,7 +238,7 @@ void MadsPlayer::setupFrame() { } void MadsPlayer::step() { - if (_visible && _stepEnabled && !_moving && (_direction == _direction2) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { + if (_visible && _stepEnabled && !_moving && (_direction == _newDirection) && (_madsVm->_currentTimer >= GET_GLOBAL32(2))) { if (_actionIndex == 0) { int randVal = _vm->_random->getRandomNumber(29999); @@ -347,7 +347,7 @@ int MadsPlayer::getSpriteSlot() { } void MadsPlayer::setTicksAmount() { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); assert(spriteSet._charInfo); _madsVm->_player._ticksAmount = spriteSet._charInfo->_ticksAmount; if (_madsVm->_player._ticksAmount == 0) @@ -363,7 +363,7 @@ void MadsPlayer::resetActionList() { } int MadsPlayer::queueAction(int action1, int action2) { - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); assert(spriteSet._charInfo); if ((action1 < spriteSet._charInfo->_numEntries) && (_actionIndex < 11)) { @@ -377,13 +377,13 @@ int MadsPlayer::queueAction(int action1, int action2) { } void MadsPlayer::idle() { - if (_direction != _direction2) { + if (_direction != _newDirection) { // The direction has changed, so reset for new direction dirChanged(); return; } - SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListIdx + _spriteListIdx2); + SpriteAsset &spriteSet = _madsVm->scene()->_spriteSlots.getSprite(_spriteListStart + _spriteListIdx); assert(spriteSet._charInfo); if (spriteSet._charInfo->_numEntries == 0) // No entries, so exit immediately @@ -418,34 +418,34 @@ void MadsPlayer::dirChanged() { int dirIndex = 0, dirIndex2 = 0; int newDir = 0, newDir2 = 0; - if (_direction != _direction2) { + if (_direction != _newDirection) { // Find the index for the given direction in the player direction list int tempDir = _direction; do { ++dirIndex; newDir += tempDir; tempDir = _directionListIndexes[tempDir + 10]; - } while (tempDir != _direction2); + } while (tempDir != _newDirection); } - if (_direction != _direction2) { + if (_direction != _newDirection) { // Find the index for the given direction in the player direction list int tempDir = _direction; do { ++dirIndex2; newDir2 += tempDir; - tempDir = _directionListIndexes[tempDir + 10]; - } while (tempDir != _direction2); + tempDir = _directionListIndexes[tempDir + 20]; + } while (tempDir != _newDirection); } int diff = dirIndex - dirIndex2; if (diff == 0) diff = newDir - newDir2; - _direction = (diff >= 0) ? _directionListIndexes[_direction] : _directionListIndexes[_direction + 10]; + _direction = (diff >= 0) ? _directionListIndexes[_direction + 20] : _directionListIndexes[_direction + 10]; setupFrame(); - if ((_direction == _direction2) && !_moving) + if ((_direction == _newDirection) && !_moving) updateFrame(); _priorTimer += 1; diff --git a/engines/m4/mads_player.h b/engines/m4/mads_player.h index 7db45cae43..65ed9ef89c 100644 --- a/engines/m4/mads_player.h +++ b/engines/m4/mads_player.h @@ -50,7 +50,7 @@ public: Common::Point _destPos; uint32 _priorTimer; uint _ticksAmount; - int16 _direction, _direction2; + int16 _direction, _newDirection; bool _stepEnabled; bool _visible, _priorVisible; bool _visible3; @@ -58,7 +58,7 @@ public: int16 _currentScale; int16 _yScale; int16 _currentDepth; - int16 _spriteListIdx, _spriteListIdx2; + int16 _spriteListStart, _spriteListIdx; bool _spritesChanged; uint16 _frameOffset, _frameNum; bool _moving; diff --git a/engines/m4/mads_scene.cpp b/engines/m4/mads_scene.cpp index 3e838fc1c0..e4f84aeb5a 100644 --- a/engines/m4/mads_scene.cpp +++ b/engines/m4/mads_scene.cpp @@ -165,7 +165,7 @@ void MadsScene::loadScene(int sceneNumber) { // Miscellaneous player setup _madsVm->_player._destPos = _madsVm->_player._destPos; - _madsVm->_player._direction2 = _madsVm->_player._direction; + _madsVm->_player._newDirection = _madsVm->_player._direction; _madsVm->_player.setupFrame(); _madsVm->_player.updateFrame(); @@ -1192,9 +1192,9 @@ bool MadsInterfaceView::handleKeypress(int32 keycode) { warning("TODO: Activate sound"); break; - case Common::KEYCODE_u: - // Rotate player - warning("TODO: Rotate player"); + case Common::KEYCODE_t: + // Rotate player - This was Ctrl-U in the original, but in ScummVM Ctrl-U is a global mute key + _madsVm->_player._newDirection = _madsVm->_player._directionListIndexes[_madsVm->_player._newDirection + 10]; break; case Common::KEYCODE_v: { -- cgit v1.2.3 From 9b14164bfcd9e6fecaecaed3ee5e061d6086bac8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 7 Jul 2010 14:19:36 +0000 Subject: SCI: accepting decimal/hexadecimal input on segment_info & kill_segment debug command, cleanup svn-id: r50735 --- engines/sci/console.cpp | 69 ++++++++++++++++++++++++++++--------------------- engines/sci/console.h | 2 ++ 2 files changed, 42 insertions(+), 29 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index e684532b08..4465fc6619 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1581,7 +1581,7 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { DebugPrintf("Provides information on the specified segment(s)\n"); DebugPrintf("Usage: %s \n", argv[0]); DebugPrintf(" can be a number, which shows the information of the segment with\n"); - DebugPrintf("the specified number, or \"all\" to show information on all active segments"); + DebugPrintf("the specified number, or \"all\" to show information on all active segments\n"); return true; } @@ -1589,9 +1589,11 @@ bool Console::cmdSegmentInfo(int argc, const char **argv) { for (uint i = 0; i < _engine->_gamestate->_segMan->_heap.size(); i++) segmentInfo(i); } else { - int nr = atoi(argv[1]); - if (!segmentInfo(nr)) - DebugPrintf("Segment %04x does not exist\n", nr); + int segmentNr; + if (!parseInteger(argv[1], segmentNr)) + return true; + if (!segmentInfo(segmentNr)) + DebugPrintf("Segment %04xh does not exist\n", segmentNr); } return true; @@ -1604,21 +1606,23 @@ bool Console::cmdKillSegment(int argc, const char **argv) { DebugPrintf("Usage: %s \n", argv[0]); return true; } - - _engine->_gamestate->_segMan->getScript(atoi(argv[1]))->setLockers(0); + int segmentNumber; + if (!parseInteger(argv[1], segmentNumber)) + return true; + _engine->_gamestate->_segMan->getScript(segmentNumber)->setLockers(0); return true; } bool Console::cmdShowMap(int argc, const char **argv) { if (argc != 2) { - DebugPrintf("Shows one of the screen maps\n"); + DebugPrintf("Switches to one of the following screen maps\n"); DebugPrintf("Usage: %s \n", argv[0]); DebugPrintf("Screen maps:\n"); - DebugPrintf("- 0: visual map (back buffer)\n"); - DebugPrintf("- 1: priority map (back buffer)\n"); - DebugPrintf("- 2: control map (static buffer)\n"); - DebugPrintf("- 3: display screen (newgui only)\n"); + DebugPrintf("- 0: visual map\n"); + DebugPrintf("- 1: priority map\n"); + DebugPrintf("- 2: control map\n"); + DebugPrintf("- 3: display screen\n"); return true; } @@ -1929,25 +1933,9 @@ bool Console::cmdVMVars(int argc, const char **argv) { return true; } - char *endPtr = 0; - int idxLen = strlen(argv[2]); - const char *lastChar = argv[2] + idxLen - (idxLen == 0 ? 0 : 1); + if (!parseInteger(argv[2], varIndex)) + return true; - if ((strncmp(argv[2], "0x", 2) == 0) || (*lastChar == 'h')) { - // hexadecimal number - varIndex = strtol(argv[2], &endPtr, 16); - if ((*endPtr != 0) && (*endPtr != 'h')) { - DebugPrintf("Invalid hexadecimal number '%s'\n", argv[2]); - return true; - } - } else { - // decimal number - varIndex = strtol(argv[2], &endPtr, 10); - if (*endPtr != 0) { - DebugPrintf("Invalid decimal number '%s'\n", argv[2]); - return true; - } - } if (varIndex < 0) { DebugPrintf("Variable number may not be negative\n"); return true; @@ -3145,6 +3133,29 @@ static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeV return 0; } +bool Console::parseInteger(const char *argument, int &result) { + char *endPtr = 0; + int idxLen = strlen(argument); + const char *lastChar = argument + idxLen - (idxLen == 0 ? 0 : 1); + + if ((strncmp(argument, "0x", 2) == 0) || (*lastChar == 'h')) { + // hexadecimal number + result = strtol(argument, &endPtr, 16); + if ((*endPtr != 0) && (*endPtr != 'h')) { + DebugPrintf("Invalid hexadecimal number '%s'\n", argument); + return false; + } + } else { + // decimal number + result = strtol(argument, &endPtr, 10); + if (*endPtr != 0) { + DebugPrintf("Invalid decimal number '%s'\n", argument); + return false; + } + } + return true; +} + void Console::printBasicVarInfo(reg_t variable) { int segType = g_sci->getKernel()->findRegType(variable); SegManager *segMan = g_sci->getEngineState()->_segMan; diff --git a/engines/sci/console.h b/engines/sci/console.h index 7e7b30ea58..95947a00f3 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -146,6 +146,8 @@ private: bool cmdViewActiveObject(int argc, const char **argv); bool cmdViewAccumulatorObject(int argc, const char **argv); + bool parseInteger(const char *argument, int &result); + void printBasicVarInfo(reg_t variable); bool segmentInfo(int nr); -- cgit v1.2.3 From 322d57a1dd2f72bb9d5fb4e00ddf82acab637e36 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Wed, 7 Jul 2010 18:35:07 +0000 Subject: SCI: adding support to kernel signatures that invalid references may also get allowed - doing exactly this for kGraph(restoreBox) - fixes castle of dr. brain when quitting the game - maybe a game specific workaround would be better?!?! svn-id: r50737 --- engines/sci/console.cpp | 12 +++++--- engines/sci/engine/kernel.cpp | 69 +++++++++++++++++++++++++++++-------------- engines/sci/engine/kernel.h | 19 ++++++------ 3 files changed, 65 insertions(+), 35 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 4465fc6619..0775d66681 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -3157,10 +3157,11 @@ bool Console::parseInteger(const char *argument, int &result) { } void Console::printBasicVarInfo(reg_t variable) { - int segType = g_sci->getKernel()->findRegType(variable); + int regType = g_sci->getKernel()->findRegType(variable); + int segType = regType; SegManager *segMan = g_sci->getEngineState()->_segMan; - segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_INVALID; + segType &= SIG_TYPE_INTEGER | SIG_TYPE_OBJECT | SIG_TYPE_REFERENCE | SIG_TYPE_NODE | SIG_TYPE_LIST | SIG_TYPE_UNINITIALIZED | SIG_TYPE_ERROR; switch (segType) { case SIG_TYPE_INTEGER: { @@ -3184,12 +3185,15 @@ void Console::printBasicVarInfo(reg_t variable) { case SIG_TYPE_UNINITIALIZED: DebugPrintf(" (uninitialized)"); break; - case SIG_TYPE_INVALID: - DebugPrintf(" (invalid)"); + case SIG_TYPE_ERROR: + DebugPrintf(" (error)"); break; default: DebugPrintf(" (??\?)"); } + + if (regType & SIG_IS_INVALID) + DebugPrintf(" IS INVALID!"); } void Console::printList(List *list) { diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2a378564bb..236a310f38 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -364,7 +364,9 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", NULL, NULL }, // subop + // ^^ we allow invalid references here, because kGraph(restoreBox) gets called with old non-existant handles often + // this should get limited to this call only as soon as subop signatures are available { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop @@ -543,7 +545,8 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS // we also check, if the written signature makes any sense curPos = writtenSig; while (*curPos) { - switch (*curPos) { + curChar = *curPos; + switch (curChar) { case '[': // either or if (eitherOr) error("signature for k%s: '[' used within '[]'", kernelName); @@ -584,6 +587,7 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS case 'l': case 'n': case '.': + case '!': if ((hadOptional) & (!optional)) error("signature for k%s: non-optional type may not follow optional type", kernelName); validType = true; @@ -634,8 +638,13 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS case 'l': case 'n': case '.': + case '!': // and we also got some signature pending? if (signature) { + if (!(signature & SIG_MAYBE_ANY)) + error("signature for k%s: invalid ('!') may only get used in combination with a real type", kernelName); + if ((signature & SIG_IS_INVALID) && ((signature & SIG_MAYBE_ANY) == (SIG_TYPE_NULL | SIG_TYPE_INTEGER))) + error("signature for k%s: invalid ('!') should not be used on exclusive null/integer type", kernelName); if (optional) { signature |= SIG_IS_OPTIONAL; if (curChar != ')') @@ -662,37 +671,44 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS break; case '0': if (signature & SIG_TYPE_NULL) - error("signature for k%s: NULL specified more than once", kernelName); + error("signature for k%s: NULL ('0') specified more than once", kernelName); signature |= SIG_TYPE_NULL; break; case 'i': if (signature & SIG_TYPE_INTEGER) - error("signature for k%s: integer specified more than once", kernelName); + error("signature for k%s: integer ('i') specified more than once", kernelName); signature |= SIG_TYPE_INTEGER | SIG_TYPE_NULL; break; case 'o': if (signature & SIG_TYPE_OBJECT) - error("signature for k%s: object specified more than once", kernelName); + error("signature for k%s: object ('o') specified more than once", kernelName); signature |= SIG_TYPE_OBJECT; break; case 'r': if (signature & SIG_TYPE_REFERENCE) - error("signature for k%s: reference specified more than once", kernelName); + error("signature for k%s: reference ('r') specified more than once", kernelName); signature |= SIG_TYPE_REFERENCE; break; case 'l': if (signature & SIG_TYPE_LIST) - error("signature for k%s: list specified more than once", kernelName); + error("signature for k%s: list ('l') specified more than once", kernelName); signature |= SIG_TYPE_LIST; break; case 'n': if (signature & SIG_TYPE_NODE) - error("signature for k%s: node specified more than once", kernelName); + error("signature for k%s: node ('n') specified more than once", kernelName); signature |= SIG_TYPE_NODE; break; case '.': + if (signature & SIG_MAYBE_ANY) + error("signature for k%s: maybe-any ('.') shouldn't get specified with other types in front of it", kernelName); signature |= SIG_MAYBE_ANY; break; + case '!': + if (signature & SIG_IS_INVALID) + error("signature for k%s: invalid ('!') specified more than once", kernelName); + signature |= SIG_IS_INVALID; + break; case '*': // accepts more of the same parameter signature |= SIG_MORE_MAY_FOLLOW; break; @@ -708,7 +724,7 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS return result; } -int Kernel::findRegType(reg_t reg) { +uint16 Kernel::findRegType(reg_t reg) { // No segment? Must be integer if (!reg.segment) return SIG_TYPE_INTEGER | (reg.offset ? 0 : SIG_TYPE_NULL); @@ -719,21 +735,24 @@ int Kernel::findRegType(reg_t reg) { // Otherwise it's an object SegmentObj *mobj = _segMan->getSegmentObj(reg.segment); if (!mobj) - return SIG_TYPE_INVALID; + return SIG_TYPE_ERROR; + uint16 result = 0; if (!mobj->isValidOffset(reg.offset)) - return SIG_TYPE_INVALID; + result |= SIG_IS_INVALID; switch (mobj->getType()) { case SEG_TYPE_SCRIPT: if (reg.offset <= (*(Script *)mobj).getBufSize() && reg.offset >= -SCRIPT_OBJECT_MAGIC_OFFSET && RAW_IS_OBJECT((*(Script *)mobj).getBuf(reg.offset)) ) { - return ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; + result |= ((Script *)mobj)->getObject(reg.offset) ? SIG_TYPE_OBJECT : SIG_TYPE_REFERENCE; } else - return SIG_TYPE_REFERENCE; + result |= SIG_TYPE_REFERENCE; + break; case SEG_TYPE_CLONES: - return SIG_TYPE_OBJECT; + result |= SIG_TYPE_OBJECT; + break; case SEG_TYPE_LOCALS: case SEG_TYPE_STACK: case SEG_TYPE_SYS_STRINGS: @@ -743,14 +762,18 @@ int Kernel::findRegType(reg_t reg) { case SEG_TYPE_ARRAY: case SEG_TYPE_STRING: #endif - return SIG_TYPE_REFERENCE; + result |= SIG_TYPE_REFERENCE; + break; case SEG_TYPE_LISTS: - return SIG_TYPE_LIST; + result |= SIG_TYPE_LIST; + break; case SEG_TYPE_NODES: - return SIG_TYPE_NODE; + result |= SIG_TYPE_NODE; + break; default: - return 0; + return SIG_TYPE_ERROR; } + return result; } struct SignatureDebugType { @@ -762,11 +785,12 @@ static const SignatureDebugType signatureDebugTypeList[] = { { SIG_TYPE_NULL, "null" }, { SIG_TYPE_INTEGER, "integer" }, { SIG_TYPE_UNINITIALIZED, "uninitialized" }, - { SIG_TYPE_INVALID, "invalid" }, { SIG_TYPE_OBJECT, "object" }, { SIG_TYPE_REFERENCE, "reference" }, { SIG_TYPE_LIST, "list" }, { SIG_TYPE_NODE, "node" }, + { SIG_TYPE_ERROR, "error" }, + { SIG_IS_INVALID, "invalid" }, { 0, NULL } }; @@ -830,10 +854,11 @@ bool Kernel::signatureMatch(const uint16 *sig, int argc, const reg_t *argv) { while (nextSig && argc) { curSig = nextSig; int type = findRegType(*argv); - if (!type) - return false; // couldn't determine type - if (!(type & curSig)) + if ((type & SIG_IS_INVALID) && (!(curSig & SIG_IS_INVALID))) + return false; // pointer is invalid and signature doesn't allow that? + + if (!((type & ~SIG_IS_INVALID) & curSig)) return false; // type mismatch if (!(curSig & SIG_MORE_MAY_FOLLOW)) { diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 719db41e8d..7aa565fe34 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -101,14 +101,15 @@ enum { SIG_TYPE_NULL = 0x01, // may be 0:0 [0] SIG_TYPE_INTEGER = 0x02, // may be 0:* [i], automatically also allows null SIG_TYPE_UNINITIALIZED = 0x04, // may be FFFF:* -> not allowable, only used for comparsion - SIG_TYPE_INVALID = 0x08, // invalid segment or offset -> not allowable, only used for comparsion - SIG_TYPE_OBJECT = 0x10, // may be object [o] - SIG_TYPE_REFERENCE = 0x20, // may be reference [r] - SIG_TYPE_LIST = 0x40, // may be list [l] - SIG_TYPE_NODE = 0x80, // may be node [n] - SIG_IS_OPTIONAL = 0x100, // is optional - SIG_NEEDS_MORE = 0x200, // needs at least one additional parameter following - SIG_MORE_MAY_FOLLOW = 0x400 // may have more parameters of the same type following + SIG_TYPE_OBJECT = 0x08, // may be object [o] + SIG_TYPE_REFERENCE = 0x10, // may be reference [r] + SIG_TYPE_LIST = 0x20, // may be list [l] + SIG_TYPE_NODE = 0x40, // may be node [n] + SIG_TYPE_ERROR = 0x80, // happens, when there is a identification error - only used for comparsion + SIG_IS_INVALID = 0x100, // ptr is invalid [!] -> invalid offset + SIG_IS_OPTIONAL = 0x200, // is optional + SIG_NEEDS_MORE = 0x400, // needs at least one additional parameter following + SIG_MORE_MAY_FOLLOW = 0x800 // may have more parameters of the same type following }; // this does not include SIG_TYPE_UNINITIALIZED, because we can not allow uninitialized values anywhere @@ -196,7 +197,7 @@ public: * KSIG_INVALID set if the type of reg can be determined, but is invalid. * 0 on error. */ - int findRegType(reg_t reg); + uint16 findRegType(reg_t reg); /******************** Text functionality ********************/ /** -- cgit v1.2.3 From 9add81aaf2aa992252be36d9a2f9f2cec0e41eea Mon Sep 17 00:00:00 2001 From: Filippos Karapetis Date: Wed, 7 Jul 2010 20:12:41 +0000 Subject: SCI: Dropped support for the very old saved game versions 9 - 11. Rationale: a lot has changed since then, we're still not stable, and this helps clean up the code, thus we're still in a position to drop support for old saved games svn-id: r50738 --- engines/sci/console.cpp | 9 ----- engines/sci/engine/savegame.cpp | 89 +++++++++-------------------------------- engines/sci/engine/savegame.h | 2 +- engines/sci/engine/segment.h | 2 +- 4 files changed, 22 insertions(+), 80 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 0775d66681..83fa26ea8b 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1401,10 +1401,6 @@ bool Console::cmdPrintSegmentTable(int argc, const char **argv) { DebugPrintf("M dynmem: %d bytes", (*(DynMem *)mobj)._size); break; - case SEG_TYPE_STRING_FRAG: - DebugPrintf("F string fragments"); - break; - #ifdef ENABLE_SCI32 case SEG_TYPE_ARRAY: DebugPrintf("A SCI32 arrays (%d)", (*(ArrayTable *)mobj).entries_used); @@ -1553,11 +1549,6 @@ bool Console::segmentInfo(int nr) { } break; - case SEG_TYPE_STRING_FRAG: { - DebugPrintf("string frags\n"); - break; - } - #ifdef ENABLE_SCI32 case SEG_TYPE_STRING: DebugPrintf("SCI32 strings\n"); diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index 5d82786b9a..d1159acbfb 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -181,27 +181,11 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { if (s.isLoading()) resetSegMan(); - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be reserved_id - s.skip(4, VER(9), VER(18)); // OBSOLETE: Used to be _exportsAreWide - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be gc_mark_bits + s.skip(4, VER(12), VER(18)); // OBSOLETE: Used to be _exportsAreWide if (s.isLoading()) { // Reset _scriptSegMap, to be restored below _scriptSegMap.clear(); - - if (s.getVersion() <= 9) { - // OBSOLETE: Skip over the old id_seg_map when loading (we now - // regenerate the equivalent data, in _scriptSegMap, from scratch). - - s.skip(4); // base_value - while (true) { - uint32 key = 0; - s.syncAsSint32LE(key); - if (key == INTMAPPER_MAGIC_KEY) - break; - s.skip(4); // idx - } - } } @@ -217,35 +201,24 @@ void SegManager::saveLoadWithSerializer(Common::Serializer &s) { // If we were saving and mobj == 0, or if we are loading and this is an // entry marked as empty -> skip to next - if (type == SEG_TYPE_INVALID) { + if (type == SEG_TYPE_INVALID) continue; - } - - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be _segManagerId // Don't save or load HunkTable segments - if (type == SEG_TYPE_HUNK) { + if (type == SEG_TYPE_HUNK) continue; - } - - // Handle the OBSOLETE type SEG_TYPE_STRING_FRAG -- just ignore it - if (s.isLoading() && type == SEG_TYPE_STRING_FRAG) { - continue; - } - - if (s.isLoading()) { + if (s.isLoading()) mobj = SegmentObj::createSegmentObj(type); - } + assert(mobj); // Let the object sync custom data mobj->saveLoadWithSerializer(s); // If we are loading a script, hook it up in the script->segment map. - if (s.isLoading() && type == SEG_TYPE_SCRIPT) { + if (s.isLoading() && type == SEG_TYPE_SCRIPT) _scriptSegMap[((Script *)mobj)->getScriptNumber()] = i; - } } s.syncAsSint32LE(_clonesSegId); @@ -270,7 +243,6 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) s.syncVersion(CURRENT_SAVEGAME_VERSION); obj.savegame_version = s.getVersion(); s.syncString(obj.game_version); - s.skip(4, VER(9), VER(9)); // obsolete: used to be game version s.syncAsSint32LE(obj.savegame_date); s.syncAsSint32LE(obj.savegame_time); if (s.getVersion() < 22) { @@ -283,11 +255,8 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj) } void EngineState::saveLoadWithSerializer(Common::Serializer &s) { - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be savegame_version - Common::String tmp; - s.syncString(tmp, VER(9), VER(23)); // OBSOLETE: Used to be game_version - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be version + s.syncString(tmp, VER(12), VER(23)); // OBSOLETE: Used to be game_version // OBSOLETE: Saved menus. Skip all of the saved data if (s.getVersion() < 14) { @@ -306,7 +275,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { for (int j = 0; j < menuLength; j++) { s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _type s.syncString(tmp); // OBSOLETE: Used to be _keytext - s.skip(4, VER(9), VER(9)); // OBSOLETE: Used to be keytext_size s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be _flags s.skip(64, VER(12), VER(12)); // OBSOLETE: Used to be MENU_SAID_SPEC_SIZE @@ -341,8 +309,6 @@ void EngineState::saveLoadWithSerializer(Common::Serializer &s) { g_sci->_gfxPorts->kernelSetPicWindow(picPortRect, picPortTop, picPortLeft, false); } - s.skip(1, VER(9), VER(9)); // obsolete: used to be a flag indicating if we got sci11 or not - _segMan->saveLoadWithSerializer(s); g_sci->_soundCmd->syncPlayList(s); @@ -357,7 +323,7 @@ void LocalVariables::saveLoadWithSerializer(Common::Serializer &s) { void Object::saveLoadWithSerializer(Common::Serializer &s) { s.syncAsSint32LE(_flags); _pos.saveLoadWithSerializer(s); - s.skip(4, VER(9), VER(12)); // OBSOLETE: Used to be variable_names_nr + s.skip(4, VER(12), VER(12)); // OBSOLETE: Used to be variable_names_nr s.syncAsSint32LE(_methodCount); // that's actually a uint16 syncArray(s, _variables); @@ -483,25 +449,12 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { if (s.isLoading()) init(_nr, g_sci->getResMan()); - s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _bufSize - s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _scriptSize - s.skip(4, VER(9), VER(22)); // OBSOLETE: Used to be _heapSize - - if (s.getVersion() <= 10) { - assert((s.isLoading())); - // OBSOLETE: Skip over the old _objIndices data when loading - s.skip(4); // base_value - while (true) { - uint32 key = 0; - s.syncAsSint32LE(key); - if (key == INTMAPPER_MAGIC_KEY) - break; - s.skip(4); // idx - } - } + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _bufSize + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _scriptSize + s.skip(4, VER(12), VER(22)); // OBSOLETE: Used to be _heapSize - s.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _numExports - s.skip(4, VER(9), VER(19)); // OBSOLETE: Used to be _numSynonyms + s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numExports + s.skip(4, VER(12), VER(19)); // OBSOLETE: Used to be _numSynonyms s.syncAsSint32LE(_lockers); // Sync _objects. This is a hashmap, and we use the following on disk format: @@ -529,7 +482,7 @@ void Script::saveLoadWithSerializer(Common::Serializer &s) { } } - s.skip(4, VER(9), VER(20)); // OBSOLETE: Used to be _localsOffset + s.skip(4, VER(12), VER(20)); // OBSOLETE: Used to be _localsOffset s.syncAsSint32LE(_localsSegment); s.syncAsSint32LE(_markedAsDeleted); @@ -822,14 +775,12 @@ void gamestate_restore(EngineState *s, Common::SeekableReadStream *fh) { } } - if (meta.savegame_version >= 12) { - // We don't need the thumbnail here, so just read it and discard it - Graphics::Surface *thumbnail = new Graphics::Surface(); - assert(thumbnail); - Graphics::loadThumbnail(*fh, *thumbnail); - delete thumbnail; - thumbnail = 0; - } + // We don't need the thumbnail here, so just read it and discard it + Graphics::Surface *thumbnail = new Graphics::Surface(); + assert(thumbnail); + Graphics::loadThumbnail(*fh, *thumbnail); + delete thumbnail; + thumbnail = 0; s->reset(true); s->saveLoadWithSerializer(ser); // FIXME: Error handling? diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h index 29f716d48d..9a882f2bf7 100644 --- a/engines/sci/engine/savegame.h +++ b/engines/sci/engine/savegame.h @@ -37,7 +37,7 @@ struct EngineState; enum { CURRENT_SAVEGAME_VERSION = 23, - MINIMUM_SAVEGAME_VERSION = 9 + MINIMUM_SAVEGAME_VERSION = 12 }; // Savegame metadata diff --git a/engines/sci/engine/segment.h b/engines/sci/engine/segment.h index b1e89e6357..2465576302 100644 --- a/engines/sci/engine/segment.h +++ b/engines/sci/engine/segment.h @@ -67,7 +67,7 @@ enum SegmentType { SEG_TYPE_NODES = 7, SEG_TYPE_HUNK = 8, SEG_TYPE_DYNMEM = 9, - SEG_TYPE_STRING_FRAG = 10, // obsolete, we keep it to be able to load old saves + // 10 used to be string fragments, now obsolete #ifdef ENABLE_SCI32 SEG_TYPE_ARRAY = 11, -- cgit v1.2.3 From b877f3c7115a187acf0fb9fb5fcdacc28ce36ec3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 8 Jul 2010 18:26:05 +0000 Subject: SCI: sorted kernel map alphabetically svn-id: r50746 --- engines/sci/engine/kernel.cpp | 458 ++++++++++++++++++++++++------------------ engines/sci/engine/kernel.h | 22 ++ engines/sci/engine/ksound.cpp | 24 +++ 3 files changed, 313 insertions(+), 191 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 236a310f38..d8d5736a19 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -212,25 +212,33 @@ static const SciWorkaroundEntry kDisposeScript_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; -struct SciKernelMapEntry { - const char *name; - KernelFunc *function; - +struct SciKernelMapSubEntry { SciVersion fromVersion; SciVersion toVersion; - byte forPlatform; + + uint16 subNr; + + const char *name; + KernelFunc *function; const char *signature; - const char *subSignatures; // placeholder const SciWorkaroundEntry *workarounds; }; -#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE -#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01 -#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE -#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1 -#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 -#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE +#define SCI_SUBOPENTRY_TERMINATOR { SCI_VERSION_NONE, SCI_VERSION_NONE, 0, NULL, NULL, NULL, NULL } + + +#define SIG_SCIALL SCI_VERSION_NONE, SCI_VERSION_NONE +#define SIG_SCI0 SCI_VERSION_NONE, SCI_VERSION_01 +#define SIG_SCI1 SCI_VERSION_1_EGA, SCI_VERSION_1_LATE +#define SIG_SCI11 SCI_VERSION_1_1, SCI_VERSION_1_1 +#define SIG_SCI16 SCI_VERSION_NONE, SCI_VERSION_1_1 +#define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE + +// SCI-Sound-Version +#define SIG_SOUNDSCI0 SCI_VERSION_1_EARLY, SCI_VERSION_0_LATE +#define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY +#define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE #define SIGFOR_ALL 0x3f #define SIGFOR_DOS 1 << 0 @@ -245,196 +253,264 @@ struct SciKernelMapEntry { #define MAP_CALL(_name_) #_name_, k##_name_ +static const SciKernelMapSubEntry kDoSound_subops[] = { + { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "(o)", NULL }, + { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "(o)", NULL }, + { SIG_SOUNDSCI0, 2, MAP_CALL(DoSoundDummy), "(o)", NULL }, + { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "(o)", NULL }, + { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(o)", NULL }, + { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "(o)", NULL }, + { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "(o)", NULL }, + { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "(o)", NULL }, + { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(o)", NULL }, + { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "(o)", NULL }, + { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "(o)", NULL }, + { SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "(o)", NULL }, + { SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStop), "(o)", NULL }, + { SIG_SOUNDSCI1EARLY, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 1, MAP_CALL(DoSoundMute), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 4, MAP_CALL(DoSoundUpdate), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 5, MAP_CALL(DoSoundInit), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 6, MAP_CALL(DoSoundDispose), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), NULL, NULL }, + // ^^ Longbow demo + { SIG_SOUNDSCI1LATE, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 1, MAP_CALL(DoSoundMute), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 6, MAP_CALL(DoSoundInit), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 7, MAP_CALL(DoSoundDispose), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 9, MAP_CALL(DoSoundStop), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 10, MAP_CALL(DoSoundPause), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 15, MAP_CALL(DoSoundSetPriority), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 16, MAP_CALL(DoSoundSetLoop), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 17, MAP_CALL(DoSoundUpdateCues), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 18, MAP_CALL(DoSoundSendMidi), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 19, MAP_CALL(DoSoundReverb), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 20, MAP_CALL(DoSoundUpdate), NULL, NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + +struct SciKernelMapEntry { + const char *name; + KernelFunc *function; + + SciVersion fromVersion; + SciVersion toVersion; + byte forPlatform; + + const char *signature; + const SciKernelMapSubEntry *subSignatures; + const SciWorkaroundEntry *workarounds; +}; + // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { - { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, NULL }, - // ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?) - { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, - { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds }, - { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, - { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, - { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL }, - { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL }, - { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, - { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, - { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, - { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // for kq6 hires - { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, - { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL }, - { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, NULL }, - { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iii)(i)(i)(i)", NULL, NULL }, - { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL }, - { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL }, - { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL }, - { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir]*)", NULL, NULL }, // subop - { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL }, - { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL }, - { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, - { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, - { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL }, - { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, - { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL }, - { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, - { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, - { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, - { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, - { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, - { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, - { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL }, - { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL }, - { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", NULL, NULL }, // subop - { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, - { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, - { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL }, - { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, - { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, - { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL }, - { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, - { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL }, - { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, - { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL }, - { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, - { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL }, - { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, - { MAP_CALL(Random), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Abs), SIG_EVERYWHERE, "[io]", NULL, NULL }, + { MAP_CALL(Abs), SIG_EVERYWHERE, "[io]", NULL, NULL }, // ^^ FIXME hoyle - { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, NULL }, + { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, + { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(AddToFront), SIG_EVERYWHERE, "ln", NULL, NULL }, + { MAP_CALL(AddToPic), SIG_EVERYWHERE, "[il](iiiiii)", NULL, NULL }, + { MAP_CALL(Animate), SIG_EVERYWHERE, "(l0)(i)", NULL, NULL }, + { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL }, + { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, + { MAP_CALL(CelHigh), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(CelWide), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL }, + { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, + { MAP_CALL(Clone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL }, + { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop + { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir]*)", NULL, NULL }, // subop + { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, + { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(DisposeScript), SIG_EVERYWHERE, "i(i*)", NULL, kDisposeScript_workarounds }, + { MAP_CALL(DisposeWindow), SIG_EVERYWHERE, "i(i)", NULL, NULL }, + { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", kDoSound_subops, NULL }, // subop + { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // for kq6 hires + { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, + { MAP_CALL(DrawControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DrawMenuBar), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(DrawPic), SIG_EVERYWHERE, "i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(DrawStatus), SIG_EVERYWHERE, "[r0](i)(i)", NULL, NULL }, + { MAP_CALL(EditControl), SIG_EVERYWHERE, "[o0][o0]", NULL, NULL }, + { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(EmptyList), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(FClose), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(FGets), SIG_EVERYWHERE, "rii", NULL, NULL }, + { MAP_CALL(FOpen), SIG_EVERYWHERE, "ri", NULL, NULL }, + { MAP_CALL(FPuts), SIG_EVERYWHERE, "ir", NULL, NULL }, + { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(FindKey), SIG_EVERYWHERE, "l.", NULL, NULL }, + { MAP_CALL(FirstNode), SIG_EVERYWHERE, "[l0]", NULL, NULL }, + { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL }, + { MAP_CALL(GameIsRestarting), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(GetAngle), SIG_EVERYWHERE, "iiii", NULL, NULL }, // ^^ FIXME - occasionally KQ6 passes a 5th argument by mistake - { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL }, - { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, - { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL }, - { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL }, - { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL }, - { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(i)", NULL, NULL }, - { MAP_CALL(Format), SIG_EVERYWHERE, "r(.*)", NULL, NULL }, - { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL }, - { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(BaseSetter), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, - { MAP_CALL(CanBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, - { MAP_CALL(CantBeHere), SIG_EVERYWHERE, "o(l)", NULL, NULL }, - { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, - { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, - { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, - { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL }, - { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL }, - { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, - { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, - { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(CheckFreeSpace), SIG_SCI32, SIGFOR_ALL, "r.*", NULL, NULL }, - { MAP_CALL(CheckFreeSpace), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(CoordPri), SIG_EVERYWHERE, "i(i)", NULL, NULL }, - { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, NULL }, - { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop - { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL }, - { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(CheckSaveGame), SIG_EVERYWHERE, ".*", NULL, NULL }, - { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL }, - { MAP_CALL(FlushResources), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", NULL, NULL }, // subop + { MAP_CALL(GetCWD), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(GetDistance), SIG_EVERYWHERE, "ii(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_SCIALL, SIGFOR_MAC, "io(i*)", NULL, NULL }, + { MAP_CALL(GetEvent), SIG_EVERYWHERE, "io", NULL, NULL }, + { MAP_CALL(GetFarText), SIG_EVERYWHERE, "ii[r0]", NULL, NULL }, + { MAP_CALL(GetMenu), SIG_EVERYWHERE, "i.", NULL, NULL }, + { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL }, + { MAP_CALL(GetPort), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_SCI32, SIGFOR_ALL, "(r*)", NULL, NULL }, + { MAP_CALL(GetSaveDir), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetSaveFiles), SIG_EVERYWHERE, "rrr", NULL, NULL }, + { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", NULL, NULL }, // subop // ^^ we allow invalid references here, because kGraph(restoreBox) gets called with old non-existant handles often // this should get limited to this call only as soon as subop signatures are available - { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(FileIO), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, - { MAP_CALL(AvoidPath), SIG_EVERYWHERE, "ii(.*)", NULL, NULL }, - { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, - { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL }, - { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL }, - { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL }, - { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(GetMessage), SIG_EVERYWHERE, "iiir", NULL, NULL }, - { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop - { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL }, - { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL }, - { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL }, - { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, - { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL }, - { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL }, - { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop - { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, // subop - { MAP_CALL(AssertPalette), SIG_EVERYWHERE, "i", NULL, NULL }, - { MAP_CALL(Empty), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(Intersections), SIG_EVERYWHERE, "iiiiriiiri", NULL, NULL }, + { MAP_CALL(IsItSkip), SIG_EVERYWHERE, "iiiii", NULL, NULL }, + { MAP_CALL(IsObject), SIG_EVERYWHERE, ".", NULL, NULL }, + { MAP_CALL(Joystick), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(LastNode), SIG_EVERYWHERE, "l", NULL, NULL }, + { MAP_CALL(Load), SIG_EVERYWHERE, "ii(i*)", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, + { MAP_CALL(LocalToGlobal), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Lock), SIG_EVERYWHERE, "ii(i)", NULL, NULL }, + { MAP_CALL(MapKeyToDir), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Memory), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(MemoryInfo), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(MemorySegment), SIG_EVERYWHERE, "ir(i)", NULL, NULL }, // subop + { MAP_CALL(MenuSelect), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(MergePoly), SIG_EVERYWHERE, "rli", NULL, NULL }, + { MAP_CALL(Message), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(MoveCursor), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(NewList), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(NewNode), SIG_EVERYWHERE, "..", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCIALL, SIGFOR_MAC, ".*", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI0, SIGFOR_ALL, "iiii[r0]i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI1, SIGFOR_ALL, "iiii[ir]i(i)(i)([ir])(i)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NewWindow), SIG_SCI11, SIGFOR_ALL, "iiiiiiii[r0]i(i)(i)(i)", NULL, NULL }, + { MAP_CALL(NextNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(NodeValue), SIG_EVERYWHERE, "[n0]", NULL, NULL }, + { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, + { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, // subop + { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, + { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, + { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Portrait), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(PrevNode), SIG_EVERYWHERE, "n", NULL, NULL }, + { MAP_CALL(PriCoord), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(Random), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(ReadNumber), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(ResCheck), SIG_EVERYWHERE, "ii(iiii)", NULL, NULL }, + { MAP_CALL(RespondsTo), SIG_EVERYWHERE, ".i", NULL, NULL }, + { MAP_CALL(RestartGame), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(RestoreGame), SIG_EVERYWHERE, "rir", NULL, NULL }, + { MAP_CALL(Said), SIG_EVERYWHERE, "[r0]", NULL, NULL }, + { MAP_CALL(SaveGame), SIG_EVERYWHERE, "rir(r)", NULL, NULL }, + { MAP_CALL(ScriptID), SIG_EVERYWHERE, "[io](i)", NULL, NULL }, + { MAP_CALL(SetCursor), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, + { MAP_CALL(SetDebug), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(SetJump), SIG_EVERYWHERE, "oiii", NULL, NULL }, + { MAP_CALL(SetMenu), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(SetNowSeen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, + { MAP_CALL(SetPort), SIG_EVERYWHERE, "i(iii)(i)(i)(i)", NULL, NULL }, + { MAP_CALL(SetQuitStr), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(SetSynonyms), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(SetVideoMode), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(ShakeScreen), SIG_EVERYWHERE, "(i)(i)", NULL, NULL }, + { MAP_CALL(ShowMovie), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(SinDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(Sort), SIG_EVERYWHERE, "ooo", NULL, NULL }, + { MAP_CALL(Sqrt), SIG_EVERYWHERE, "i", NULL, NULL }, + { MAP_CALL(StrAt), SIG_EVERYWHERE, "ri(i)", NULL, NULL }, + { MAP_CALL(StrCat), SIG_EVERYWHERE, "rr", NULL, NULL }, + { MAP_CALL(StrCmp), SIG_EVERYWHERE, "rr(i)", NULL, NULL }, + { MAP_CALL(StrCpy), SIG_EVERYWHERE, "[r0]r(i)", NULL, NULL }, + { MAP_CALL(StrEnd), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(StrLen), SIG_EVERYWHERE, "[r0]", NULL, NULL }, + { MAP_CALL(StrSplit), SIG_EVERYWHERE, "rr[r0]", NULL, NULL }, + { MAP_CALL(TextColors), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(TextFonts), SIG_EVERYWHERE, "(i*)", NULL, NULL }, + { MAP_CALL(TextSize), SIG_EVERYWHERE, "r[r0]i(i)(r0)", NULL, NULL }, + { MAP_CALL(TimesCos), SIG_EVERYWHERE, "ii", NULL, NULL }, + { "CosMult", kTimesCos, SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesCot), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, + { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, NULL }, + // ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?) + { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, + { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, #ifdef ENABLE_SCI32 // SCI2 Kernel Functions - { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL }, - { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, - { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, - { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, - { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, - { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL }, - { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, - { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, - { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(AddPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(AddScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(Array), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(CreateTextBitmap), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, + { MAP_CALL(DeletePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(DeleteScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(FrameOut), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(GetHighPlanePri), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(InPolygon), SIG_EVERYWHERE, "iio", NULL, NULL }, + { MAP_CALL(IsHiRes), SIG_EVERYWHERE, "", NULL, NULL }, + { MAP_CALL(ListAllTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListAt), SIG_EVERYWHERE, "li", NULL, NULL }, + { MAP_CALL(ListEachElementDo), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListFirstTrue), SIG_EVERYWHERE, "li(.*)", NULL, NULL }, + { MAP_CALL(ListIndexOf), SIG_EVERYWHERE, "l[o0]", NULL, NULL }, + { MAP_CALL(OnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, + { MAP_CALL(RepaintPlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(String), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(UpdatePlane), SIG_EVERYWHERE, "o", NULL, NULL }, + { MAP_CALL(UpdateScreenItem), SIG_EVERYWHERE, "o", NULL, NULL }, // SCI2.1 Kernel Functions - { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(List), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, - { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, - { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, - { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } + { MAP_CALL(CD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(IsOnMe), SIG_EVERYWHERE, "iio(.*)", NULL, NULL }, + { MAP_CALL(List), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(MulDiv), SIG_EVERYWHERE, "iii", NULL, NULL }, + { MAP_CALL(PlayVMD), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Robot), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Save), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { MAP_CALL(Text), SIG_EVERYWHERE, "(.*)", NULL, NULL }, + { NULL, NULL, SIG_EVERYWHERE, NULL, NULL, NULL } #endif }; diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 7aa565fe34..429a7903a1 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -458,6 +458,28 @@ reg_t kCD(EngineState *s, int argc, reg_t *argv); #endif +reg_t kDoSoundInit(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundPlay(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundDummy(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundDispose(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundMute(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundStop(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundPause(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundResume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundMasterVolume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundUpdate(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundFade(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundGetPolyphony(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundUpdateCues(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSendMidi(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundReverb(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetHold(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundGetAudioCapability(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSuspend(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv); + //@} } // End of namespace Sci diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 3d8869e89e..d205d250de 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -42,6 +42,30 @@ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc); } +#define CREATE_FORWARD(_name_, _forward_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->##_forward_(argc, argv, s->r_acc); } + +CREATE_FORWARD(DoSoundInit, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundPlay, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundDummy, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundDispose, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundMute, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundStop, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundPause, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundResume, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundMasterVolume, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundUpdate, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundFade, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundGetPolyphony, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundUpdateCues, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSendMidi, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundReverb, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetHold, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundGetAudioCapability, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSuspend, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetVolume, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetPriority, _soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetLoop, _soundCmd->parseCommand) + reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { case kSciAudioPlay: { -- cgit v1.2.3 From 07fef4c6e6a385732c508fb8129b70dcc4a43571 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 8 Jul 2010 18:38:15 +0000 Subject: SCI: hopefully fix build :P svn-id: r50747 --- engines/sci/engine/ksound.cpp | 46 +++++++++++++++++++++---------------------- 1 file changed, 23 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index d205d250de..88b4f6a352 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -42,29 +42,29 @@ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc); } -#define CREATE_FORWARD(_name_, _forward_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->##_forward_(argc, argv, s->r_acc); } - -CREATE_FORWARD(DoSoundInit, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundPlay, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundDummy, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundDispose, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundMute, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundStop, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundPause, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundResume, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundMasterVolume, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundUpdate, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundFade, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundGetPolyphony, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundUpdateCues, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSendMidi, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundReverb, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetHold, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundGetAudioCapability, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSuspend, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetVolume, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetPriority, _soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetLoop, _soundCmd->parseCommand) +#define CREATE_FORWARD(_name_, _forward_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->_##_forward_(argc, argv, s->r_acc); } + +CREATE_FORWARD(DoSoundInit, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundPlay, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundDummy, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundDispose, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundMute, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundStop, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundPause, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundResume, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundMasterVolume, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundUpdate, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundFade, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundGetPolyphony, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundUpdateCues, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSendMidi, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundReverb, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetHold, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundGetAudioCapability, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSuspend, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetVolume, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetPriority, soundCmd->parseCommand) +CREATE_FORWARD(DoSoundSetLoop, soundCmd->parseCommand) reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { -- cgit v1.2.3 From 7e05d6e62bd8e887ccea2302ad191a775150ccf8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Thu, 8 Jul 2010 21:22:59 +0000 Subject: SCI: part of subfunction signature&mapping implemented, little cleanup svn-id: r50750 --- engines/sci/engine/kernel.cpp | 87 +++++++++++++++++++++++++++++++------------ engines/sci/engine/kernel.h | 19 +++++++--- engines/sci/engine/ksound.cpp | 2 + engines/sci/engine/vm.cpp | 4 +- 4 files changed, 82 insertions(+), 30 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index d8d5736a19..7be4c442eb 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -216,10 +216,10 @@ struct SciKernelMapSubEntry { SciVersion fromVersion; SciVersion toVersion; - uint16 subNr; + uint16 id; const char *name; - KernelFunc *function; + KernelFunctionCall *function; const char *signature; const SciWorkaroundEntry *workarounds; @@ -236,7 +236,7 @@ struct SciKernelMapSubEntry { #define SIG_SCI32 SCI_VERSION_2, SCI_VERSION_NONE // SCI-Sound-Version -#define SIG_SOUNDSCI0 SCI_VERSION_1_EARLY, SCI_VERSION_0_LATE +#define SIG_SOUNDSCI0 SCI_VERSION_0_EARLY, SCI_VERSION_0_LATE #define SIG_SOUNDSCI1EARLY SCI_VERSION_1_EARLY, SCI_VERSION_1_EARLY #define SIG_SOUNDSCI1LATE SCI_VERSION_1_LATE, SCI_VERSION_1_LATE @@ -310,14 +310,14 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { struct SciKernelMapEntry { const char *name; - KernelFunc *function; + KernelFunctionCall *function; SciVersion fromVersion; SciVersion toVersion; byte forPlatform; const char *signature; - const SciKernelMapSubEntry *subSignatures; + const SciKernelMapSubEntry *subFunctions; const SciWorkaroundEntry *workarounds; }; @@ -521,7 +521,7 @@ Kernel::Kernel(ResourceManager *resMan, SegManager *segMan) } Kernel::~Kernel() { - for (KernelFuncsContainer::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i) + for (KernelFunctionArray::iterator i = _kernelFuncs.begin(); i != _kernelFuncs.end(); ++i) free(i->signature); } @@ -999,24 +999,26 @@ void Kernel::mapFunctions() { _kernelFuncs.resize(functionCount); - for (uint functNr = 0; functNr < functionCount; functNr++) { + for (uint id = 0; id < functionCount; id++) { // First, get the name, if known, of the kernel function with number functnr - Common::String sought_name = _kernelNames[functNr]; + Common::String kernelName = _kernelNames[id]; // Reset the table entry - _kernelFuncs[functNr].func = NULL; - _kernelFuncs[functNr].signature = NULL; - _kernelFuncs[functNr].origName = sought_name; - _kernelFuncs[functNr].isDummy = true; - - if (sought_name.empty()) { + _kernelFuncs[id].function = NULL; + _kernelFuncs[id].signature = NULL; + _kernelFuncs[id].origName = kernelName; + _kernelFuncs[id].isDummy = true; + _kernelFuncs[id].workarounds = NULL; + _kernelFuncs[id].subFunctions = NULL; + _kernelFuncs[id].subFunctionCount = 0; + if (kernelName.empty()) { // No name was given -> must be an unknown opcode - warning("Kernel function %x unknown", functNr); + warning("Kernel function %x unknown", id); continue; } // Don't map dummy functions - they will never be called - if (sought_name == "Dummy") + if (kernelName == "Dummy") continue; // If the name is known, look it up in s_kernelMap. This table @@ -1024,7 +1026,7 @@ void Kernel::mapFunctions() { SciKernelMapEntry *kernelMap = s_kernelMap; bool nameMatch = false; while (kernelMap->name) { - if (sought_name == kernelMap->name) { + if (kernelName == kernelMap->name) { if ((kernelMap->fromVersion == SCI_VERSION_NONE) || (kernelMap->fromVersion <= myVersion)) if ((kernelMap->toVersion == SCI_VERSION_NONE) || (kernelMap->toVersion >= myVersion)) if (platformMask & kernelMap->forPlatform) @@ -1037,10 +1039,49 @@ void Kernel::mapFunctions() { if (kernelMap->name) { // A match was found if (kernelMap->function) { - _kernelFuncs[functNr].func = kernelMap->function; - _kernelFuncs[functNr].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); - _kernelFuncs[functNr].workarounds = kernelMap->workarounds; - _kernelFuncs[functNr].isDummy = false; + _kernelFuncs[id].function = kernelMap->function; + _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); + _kernelFuncs[id].workarounds = kernelMap->workarounds; + _kernelFuncs[id].isDummy = false; + if (kernelMap->subFunctions) { + // Get version for subfunction identification + SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; + // Now check whats the highest subfunction-id for this version + const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions; + uint16 subFunctionCount = 0; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) + if (subFunctionCount <= kernelSubMap->id) + subFunctionCount = kernelSubMap->id + 1; + kernelSubMap++; + } + if (!subFunctionCount) + error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id); + // Now allocate required memory and go through it again + _kernelFuncs[id].subFunctionCount = subFunctionCount; + KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount]; + _kernelFuncs[id].subFunctions = subFunctions; + memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount); + // And fill this info out + kernelSubMap = kernelMap->subFunctions; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { + uint subId = kernelSubMap->id; + subFunctions[subId].function = kernelSubMap->function; + subFunctions[subId].name = kernelSubMap->name; + if (kernelSubMap->signature) + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); + subFunctions[subId].workarounds = kernelSubMap->workarounds; + } + kernelSubMap++; + } + // Now we check, if all filled out entries got signatures + // If a signature is missing go through the subfunctions table again and use the last signature + // specified before our entry. If no signature is found at all -> bomb out + // TODO + } ++mapped; } else { //warning("Ignoring function %s\n", s_kernelFuncMap[found].name); @@ -1048,9 +1089,9 @@ void Kernel::mapFunctions() { } } else { if (nameMatch) - error("kernel function %s[%x] not found for this version/platform", sought_name.c_str(), functNr); + error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id); // No match but a name was given -> stub - warning("Kernel function %s[%x] unmapped", sought_name.c_str(), functNr); + warning("k%s[%x]: unmapped", kernelName.c_str(), id); } } // for all functions requesting to be mapped diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 429a7903a1..7fa3916b31 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -118,7 +118,7 @@ enum { // ---------------------------------------------------------------------------- /* Generic description: */ -typedef reg_t KernelFunc(EngineState *s, int argc, reg_t *argv); +typedef reg_t KernelFunctionCall(EngineState *s, int argc, reg_t *argv); struct SciWorkaroundEntry { SciGameId gameId; @@ -133,12 +133,21 @@ struct SciWorkaroundEntry { #define SCI_WORKAROUNDENTRY_TERMINATOR { (SciGameId)0, -1, 0, NULL, NULL, -1, 0, { 0, 0 } } -struct KernelFuncWithSignature { - KernelFunc *func; /**< The actual function */ +struct KernelSubFunction { + KernelFunctionCall *function; + const char *name; + uint16 *signature; + const SciWorkaroundEntry *workarounds; +}; + +struct KernelFunction { + KernelFunctionCall *function; Common::String origName; /**< Original name, in case we couldn't map it */ bool isDummy; uint16 *signature; const SciWorkaroundEntry *workarounds; + const KernelSubFunction *subFunctions; + uint16 subFunctionCount; }; enum AutoDetectedFeatures { @@ -172,8 +181,8 @@ public: void dumpScriptClass(char *data, int seeker, int objsize); SelectorCache _selectorCache; /**< Shortcut list for important selectors. */ - typedef Common::Array KernelFuncsContainer; - KernelFuncsContainer _kernelFuncs; /**< Table of kernel functions. */ + typedef Common::Array KernelFunctionArray; + KernelFunctionArray _kernelFuncs; /**< Table of kernel functions. */ /** * Determines whether a list of registers matches a given signature. diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 88b4f6a352..4ecbc523d5 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -39,6 +39,8 @@ namespace Sci { * Used for synthesized music playback */ reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { + if (!s) + return make_reg(0, g_sci->_features->detectDoSoundType()); return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc); } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index b1e6eead0e..6973694ea9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -786,7 +786,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { if (kernelFuncNr >= (int)kernel->_kernelFuncs.size()) error("Invalid kernel function 0x%x requested", kernelFuncNr); - const KernelFuncWithSignature &kernelCall = kernel->_kernelFuncs[kernelFuncNr]; + const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelFuncNr]; if (kernelCall.signature && !kernel->signatureMatch(kernelCall.signature, argc, s->xs->sp + 1)) { @@ -817,7 +817,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function - s->r_acc = kernelCall.func(s, argc, argv); + s->r_acc = kernelCall.function(s, argc, argv); #if 0 // Used for debugging -- cgit v1.2.3 From 9117eec6a72c9dc4abb72ca45ecebbfb7ee04bfc Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 09:26:57 +0000 Subject: SCI: getting signatures for subfunctions from previous entries, if needed svn-id: r50754 --- engines/sci/engine/kernel.cpp | 47 ++++++++++++++++++++++++++++--------------- 1 file changed, 31 insertions(+), 16 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 7be4c442eb..c5f5e9e61a 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -278,18 +278,18 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), "o", NULL }, + { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), "oiiii", NULL }, + { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "i", NULL }, + { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), "oi", NULL }, + { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), "", NULL }, // ^^ Longbow demo { SIG_SOUNDSCI1LATE, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, { SIG_SOUNDSCI1LATE, 1, MAP_CALL(DoSoundMute), NULL, NULL }, { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), "", NULL }, + { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "", NULL }, { SIG_SOUNDSCI1LATE, 6, MAP_CALL(DoSoundInit), NULL, NULL }, { SIG_SOUNDSCI1LATE, 7, MAP_CALL(DoSoundDispose), NULL, NULL }, { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, @@ -298,9 +298,9 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), NULL, NULL }, { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 15, MAP_CALL(DoSoundSetPriority), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 16, MAP_CALL(DoSoundSetLoop), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), "oi", NULL }, + { SIG_SOUNDSCI1LATE, 15, MAP_CALL(DoSoundSetPriority), "oi", NULL }, + { SIG_SOUNDSCI1LATE, 16, MAP_CALL(DoSoundSetLoop), "oi", NULL }, { SIG_SOUNDSCI1LATE, 17, MAP_CALL(DoSoundUpdateCues), NULL, NULL }, { SIG_SOUNDSCI1LATE, 18, MAP_CALL(DoSoundSendMidi), NULL, NULL }, { SIG_SOUNDSCI1LATE, 19, MAP_CALL(DoSoundReverb), NULL, NULL }, @@ -1065,22 +1065,37 @@ void Kernel::mapFunctions() { memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount); // And fill this info out kernelSubMap = kernelMap->subFunctions; + uint kernelSubNr = 0; while (kernelSubMap->function) { if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { uint subId = kernelSubMap->id; subFunctions[subId].function = kernelSubMap->function; subFunctions[subId].name = kernelSubMap->name; - if (kernelSubMap->signature) - subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); subFunctions[subId].workarounds = kernelSubMap->workarounds; + if (kernelSubMap->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); + } else { + // we go back the submap to find the previous signature for that kernel call + const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; + uint kernelSubLeft = kernelSubNr; + while (kernelSubLeft) { + kernelSubLeft--; + kernelSubMapBack--; + if (kernelSubMapBack->name == kernelSubMap->name) { + if (kernelSubMapBack->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); + break; + } + } + } + if (!subFunctions[subId].signature) + error("k%s: no previous signatures", kernelSubMap->name); + } } kernelSubMap++; + kernelSubNr++; } - // Now we check, if all filled out entries got signatures - // If a signature is missing go through the subfunctions table again and use the last signature - // specified before our entry. If no signature is found at all -> bomb out - // TODO } ++mapped; } else { -- cgit v1.2.3 From ba776fb2934c7124e969d54e559c5136f5a2fc73 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 12:06:41 +0000 Subject: SCI: implemented subsignatures for kDoSound svn-id: r50755 --- engines/sci/console.cpp | 4 +- engines/sci/engine/kernel.cpp | 38 ++--- engines/sci/engine/kernel.h | 1 + engines/sci/engine/ksound.cpp | 49 +++--- engines/sci/engine/savegame.cpp | 2 +- engines/sci/engine/vm.cpp | 28 +++- engines/sci/sound/soundcmd.cpp | 325 ++++++++++++++++------------------------ engines/sci/sound/soundcmd.h | 80 +++++----- 8 files changed, 236 insertions(+), 291 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 83fa26ea8b..3151691900 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -1703,9 +1703,9 @@ bool Console::cmdToggleSound(int argc, const char **argv) { newState.toLowercase(); if (newState == "play") - g_sci->_soundCmd->playSound(id); + g_sci->_soundCmd->processPlaySound(id); else if (newState == "stop") - g_sci->_soundCmd->stopSound(id); + g_sci->_soundCmd->processStopSound(id, false); else DebugPrintf("New state can either be 'play' or 'stop'"); diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c5f5e9e61a..501ad54dfa 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -254,19 +254,19 @@ struct SciKernelMapSubEntry { #define MAP_CALL(_name_) #_name_, k##_name_ static const SciKernelMapSubEntry kDoSound_subops[] = { - { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "(o)", NULL }, - { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "(o)", NULL }, - { SIG_SOUNDSCI0, 2, MAP_CALL(DoSoundDummy), "(o)", NULL }, - { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "(o)", NULL }, - { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(o)", NULL }, - { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "(o)", NULL }, - { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "(o)", NULL }, - { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "(o)", NULL }, - { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(o)", NULL }, - { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "(o)", NULL }, - { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "(o)", NULL }, - { SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "(o)", NULL }, - { SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStop), "(o)", NULL }, + { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "o", NULL }, + { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "o", NULL }, + { SIG_SOUNDSCI0, 2, MAP_CALL(DoSoundDummy), "o", NULL }, + { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "o", NULL }, + { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL }, + { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL }, + { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "[o0]", NULL }, + { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "o", NULL }, + { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL }, + { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL }, + { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", NULL }, + { SIG_SOUNDSCI0, 11, MAP_CALL(DoSoundGetPolyphony), "", NULL }, + { SIG_SOUNDSCI0, 12, MAP_CALL(DoSoundStopAll), "", NULL }, { SIG_SOUNDSCI1EARLY, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 1, MAP_CALL(DoSoundMute), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, @@ -274,19 +274,19 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1EARLY, 4, MAP_CALL(DoSoundUpdate), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 5, MAP_CALL(DoSoundInit), NULL, NULL }, { SIG_SOUNDSCI1EARLY, 6, MAP_CALL(DoSoundDispose), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 7, MAP_CALL(DoSoundPlay), "oi", NULL }, { SIG_SOUNDSCI1EARLY, 8, MAP_CALL(DoSoundStop), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), NULL, NULL }, - { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), NULL, NULL }, + { SIG_SOUNDSCI1EARLY, 9, MAP_CALL(DoSoundPause), "[o0]i", NULL }, + { SIG_SOUNDSCI1EARLY, 10, MAP_CALL(DoSoundFade), "oiiii", NULL }, { SIG_SOUNDSCI1EARLY, 11, MAP_CALL(DoSoundUpdateCues), "o", NULL }, { SIG_SOUNDSCI1EARLY, 12, MAP_CALL(DoSoundSendMidi), "oiiii", NULL }, - { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "i", NULL }, + { SIG_SOUNDSCI1EARLY, 13, MAP_CALL(DoSoundReverb), "oi", NULL }, { SIG_SOUNDSCI1EARLY, 14, MAP_CALL(DoSoundSetHold), "oi", NULL }, { SIG_SOUNDSCI1EARLY, 15, MAP_CALL(DoSoundDummy), "", NULL }, // ^^ Longbow demo { SIG_SOUNDSCI1LATE, 0, MAP_CALL(DoSoundMasterVolume), NULL, NULL }, { SIG_SOUNDSCI1LATE, 1, MAP_CALL(DoSoundMute), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), "", NULL }, { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), "", NULL }, { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "", NULL }, @@ -295,7 +295,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, { SIG_SOUNDSCI1LATE, 9, MAP_CALL(DoSoundStop), NULL, NULL }, { SIG_SOUNDSCI1LATE, 10, MAP_CALL(DoSoundPause), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), NULL, NULL }, + { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), "oiiii(i)", NULL }, { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), "oi", NULL }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 7fa3916b31..a5ea379ba6 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -473,6 +473,7 @@ reg_t kDoSoundDummy(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundDispose(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundMute(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundStop(EngineState *s, int argc, reg_t *argv); +reg_t kDoSoundStopAll(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundPause(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundResume(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundMasterVolume(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/ksound.cpp b/engines/sci/engine/ksound.cpp index 4ecbc523d5..69ae68674b 100644 --- a/engines/sci/engine/ksound.cpp +++ b/engines/sci/engine/ksound.cpp @@ -41,32 +41,33 @@ namespace Sci { reg_t kDoSound(EngineState *s, int argc, reg_t *argv) { if (!s) return make_reg(0, g_sci->_features->detectDoSoundType()); - return g_sci->_soundCmd->parseCommand(argc, argv, s->r_acc); + error("not supposed to call this"); } -#define CREATE_FORWARD(_name_, _forward_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->_##_forward_(argc, argv, s->r_acc); } - -CREATE_FORWARD(DoSoundInit, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundPlay, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundDummy, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundDispose, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundMute, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundStop, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundPause, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundResume, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundMasterVolume, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundUpdate, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundFade, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundGetPolyphony, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundUpdateCues, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSendMidi, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundReverb, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetHold, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundGetAudioCapability, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSuspend, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetVolume, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetPriority, soundCmd->parseCommand) -CREATE_FORWARD(DoSoundSetLoop, soundCmd->parseCommand) +#define CREATE_DOSOUND_FORWARD(_name_) reg_t k##_name_(EngineState *s, int argc, reg_t *argv) { return g_sci->_soundCmd->k##_name_(argc, argv, s->r_acc); } + +CREATE_DOSOUND_FORWARD(DoSoundInit) +CREATE_DOSOUND_FORWARD(DoSoundPlay) +CREATE_DOSOUND_FORWARD(DoSoundDummy) +CREATE_DOSOUND_FORWARD(DoSoundDispose) +CREATE_DOSOUND_FORWARD(DoSoundMute) +CREATE_DOSOUND_FORWARD(DoSoundStop) +CREATE_DOSOUND_FORWARD(DoSoundStopAll) +CREATE_DOSOUND_FORWARD(DoSoundPause) +CREATE_DOSOUND_FORWARD(DoSoundResume) +CREATE_DOSOUND_FORWARD(DoSoundMasterVolume) +CREATE_DOSOUND_FORWARD(DoSoundUpdate) +CREATE_DOSOUND_FORWARD(DoSoundFade) +CREATE_DOSOUND_FORWARD(DoSoundGetPolyphony) +CREATE_DOSOUND_FORWARD(DoSoundUpdateCues) +CREATE_DOSOUND_FORWARD(DoSoundSendMidi) +CREATE_DOSOUND_FORWARD(DoSoundReverb) +CREATE_DOSOUND_FORWARD(DoSoundSetHold) +CREATE_DOSOUND_FORWARD(DoSoundGetAudioCapability) +CREATE_DOSOUND_FORWARD(DoSoundSuspend) +CREATE_DOSOUND_FORWARD(DoSoundSetVolume) +CREATE_DOSOUND_FORWARD(DoSoundSetPriority) +CREATE_DOSOUND_FORWARD(DoSoundSetLoop) reg_t kDoCdAudio(EngineState *s, int argc, reg_t *argv) { switch (argv[0].toUint16()) { diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp index d1159acbfb..0fe5f2088a 100644 --- a/engines/sci/engine/savegame.cpp +++ b/engines/sci/engine/savegame.cpp @@ -607,7 +607,7 @@ void SoundCommandParser::reconstructPlayList(int savegame_version) { (*i)->volume = readSelectorValue(_segMan, (*i)->soundObj, SELECTOR(vol)); } - cmdPlaySound((*i)->soundObj, 0); + processPlaySound((*i)->soundObj); } } } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 6973694ea9..a0f38c634c 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -787,16 +787,17 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { error("Invalid kernel function 0x%x requested", kernelFuncNr); const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelFuncNr]; + reg_t *argv = s->xs->sp + 1; if (kernelCall.signature - && !kernel->signatureMatch(kernelCall.signature, argc, s->xs->sp + 1)) { + && !kernel->signatureMatch(kernelCall.signature, argc, argv)) { // signature mismatch, check if a workaround is available bool workaroundFound; SciTrackOriginReply originReply; reg_t workaround; workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, workaroundFound, &originReply); if (!workaroundFound) { - kernel->signatureDebug(kernelCall.signature, argc, s->xs->sp + 1); + kernel->signatureDebug(kernelCall.signature, argc, argv); error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernel->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. @@ -804,8 +805,6 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { return; } - reg_t *argv = s->xs->sp + 1; - if (!kernelCall.isDummy) { // Add stack frame to indicate we're executing a callk. // This is useful in debugger backtraces if this @@ -817,7 +816,26 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function - s->r_acc = kernelCall.function(s, argc, argv); + if (!kernelCall.subFunctionCount) { + s->r_acc = kernelCall.function(s, argc, argv); + } else { + // Sub-functions available, check signature and call that one directly + if (argc < 1) + error("[VM] k%s: no subfunction-id parameter given"); + const uint16 subId = argv[0].toUint16(); + // Skip over subfunction-id + argc--; + argv++; + if (subId >= kernelCall.subFunctionCount) + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.origName, subId); + const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; + if (!kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { + // Signature mismatch + kernel->signatureDebug(kernelSubCall.signature, argc, argv); + error("[VM] k%s: subfunction signature mismatch", kernelSubCall.name); + } + s->r_acc = kernelSubCall.function(s, argc, argv); + } #if 0 // Used for debugging diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index d318b1ced0..6732137962 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -36,133 +36,29 @@ namespace Sci { #define SCI1_SOUND_FLAG_MAY_PAUSE 1 /* Only here for completeness; The interpreter doesn't touch this bit */ #define SCI1_SOUND_FLAG_SCRIPTED_PRI 2 /* but does touch this */ -#define SOUNDCOMMAND(x) _soundCommands.push_back(new MusicEntryCommand(#x, &SoundCommandParser::x)) - SoundCommandParser::SoundCommandParser(ResourceManager *resMan, SegManager *segMan, Kernel *kernel, AudioPlayer *audio, SciVersion soundVersion) : _resMan(resMan), _segMan(segMan), _kernel(kernel), _audio(audio), _soundVersion(soundVersion) { _music = new SciMusic(_soundVersion); _music->init(); - - switch (_soundVersion) { - case SCI_VERSION_0_EARLY: - case SCI_VERSION_0_LATE: - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdResumeSound); - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdUpdateSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdStopAllSounds); - _cmdUpdateCuesIndex = -1; - break; - case SCI_VERSION_1_EARLY: - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdUpdateSound); - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdUpdateCues); - SOUNDCOMMAND(cmdSendMidi); - SOUNDCOMMAND(cmdReverb); - SOUNDCOMMAND(cmdSetSoundHold); - SOUNDCOMMAND(cmdDummy); // Longbow demo - _cmdUpdateCuesIndex = 11; - break; - case SCI_VERSION_1_LATE: - SOUNDCOMMAND(cmdMasterVolume); - SOUNDCOMMAND(cmdMuteSound); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdGetPolyphony); - SOUNDCOMMAND(cmdGetAudioCapability); - SOUNDCOMMAND(cmdSuspendSound); - SOUNDCOMMAND(cmdInitSound); - SOUNDCOMMAND(cmdDisposeSound); - SOUNDCOMMAND(cmdPlaySound); - SOUNDCOMMAND(cmdStopSound); - SOUNDCOMMAND(cmdPauseSound); - SOUNDCOMMAND(cmdFadeSound); - SOUNDCOMMAND(cmdSetSoundHold); - SOUNDCOMMAND(cmdDummy); - SOUNDCOMMAND(cmdSetSoundVolume); - SOUNDCOMMAND(cmdSetSoundPriority); - SOUNDCOMMAND(cmdSetSoundLoop); - SOUNDCOMMAND(cmdUpdateCues); - SOUNDCOMMAND(cmdSendMidi); - SOUNDCOMMAND(cmdReverb); - SOUNDCOMMAND(cmdUpdateSound); - _cmdUpdateCuesIndex = 17; - break; - default: - error("Sound command parser: unknown sound version %d", _soundVersion); - break; - } } SoundCommandParser::~SoundCommandParser() { - for (SoundCommandContainer::iterator i = _soundCommands.begin(); i != _soundCommands.end(); ++i) - delete *i; - delete _music; } -reg_t SoundCommandParser::parseCommand(int argc, reg_t *argv, reg_t acc) { - uint16 command = argv[0].toUint16(); - reg_t obj = (argc > 1) ? argv[1] : NULL_REG; - int16 value = (argc > 2) ? argv[2].toSint16() : 0; - _acc = acc; - _argc = argc; - _argv = argv; - - if (argc == 6) { // cmdSendMidi - byte channel = argv[2].toUint16() & 0xf; - byte midiCmd = argv[3].toUint16() & 0xff; - - uint16 controller = argv[4].toUint16(); - uint16 param = argv[5].toUint16(); - - if (channel) - channel--; // channel is given 1-based, we are using 0-based - - _midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); - } - - if (command < _soundCommands.size()) { - if (command != _cmdUpdateCuesIndex) { - //printf("%s, object %04x:%04x\n", _soundCommands[command]->desc, PRINT_REG(obj)); // debug - debugC(2, kDebugLevelSound, "%s, object %04x:%04x", _soundCommands[command]->desc, PRINT_REG(obj)); - } - - (this->*(_soundCommands[command]->sndCmd))(obj, value); - } else { - error("Invalid sound command requested (%d), valid range is 0-%d", command, _soundCommands.size() - 1); - } - - return _acc; +reg_t SoundCommandParser::kDoSoundInit(int argc, reg_t *argv, reg_t acc) { + processInitSound(argv[0]); + return acc; } -void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { - if (!obj.segment) - return; - +void SoundCommandParser::processInitSound(reg_t obj) { int resourceId = readSelectorValue(_segMan, obj, SELECTOR(number)); // Check if a track with the same sound object is already playing MusicEntry *oldSound = _music->getSlot(obj); if (oldSound) - cmdDisposeSound(obj, value); + processDisposeSound(obj); MusicEntry *newSound = new MusicEntry(); newSound->resourceId = resourceId; @@ -208,10 +104,12 @@ void SoundCommandParser::cmdInitSound(reg_t obj, int16 value) { } } -void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { + processPlaySound(argv[0]); + return acc; +} +void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -221,8 +119,8 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { int resourceId = obj.segment ? readSelectorValue(_segMan, obj, SELECTOR(number)) : -1; if (musicSlot->resourceId != resourceId) { // another sound loaded into struct - cmdDisposeSound(obj, value); - cmdInitSound(obj, value); + processDisposeSound(obj); + processInitSound(obj); // Find slot again :) musicSlot = _music->getSlot(obj); } @@ -250,21 +148,24 @@ void SoundCommandParser::cmdPlaySound(reg_t obj, int16 value) { _music->soundPlay(musicSlot); } -void SoundCommandParser::cmdDummy(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundDummy(int argc, reg_t *argv, reg_t acc) { warning("cmdDummy invoked"); // not supposed to occur + return acc; } -void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) { + processDisposeSound(argv[0]); + return acc; +} +void SoundCommandParser::processDisposeSound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } - cmdStopSound(obj, value); + processStopSound(obj, false); _music->soundKill(musicSlot); writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); @@ -274,14 +175,12 @@ void SoundCommandParser::cmdDisposeSound(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(state), kSoundStopped); } -void SoundCommandParser::cmdStopSound(reg_t obj, int16 value) { - processStopSound(obj, value, false); +reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) { + processStopSound(argv[0], false); + return acc; } -void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying) { - if (!obj.segment) - return; - +void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -309,19 +208,22 @@ void SoundCommandParser::processStopSound(reg_t obj, int16 value, bool sampleFin _music->soundStop(musicSlot); } -void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + uint16 value = argc > 1 ? argv[1].toUint16() : 0; + if (!obj.segment) { // pause the whole playlist // Pausing/Resuming the whole playlist was introduced in the SCI1 late // sound scheme. if (_soundVersion <= SCI_VERSION_1_EARLY) - return; + return acc; _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdPauseSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } if (_soundVersion <= SCI_VERSION_0_LATE) { @@ -332,51 +234,51 @@ void SoundCommandParser::cmdPauseSound(reg_t obj, int16 value) { _music->soundToggle(musicSlot, value); } } + return acc; } -void SoundCommandParser::cmdResumeSound(reg_t obj, int16 value) { - // SCI0 only command - - if (!obj.segment) - return; +// SCI0 only command +reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); _music->soundResume(musicSlot); + return acc; } -void SoundCommandParser::cmdMuteSound(reg_t obj, int16 value) { - if (_argc > 1) // the first parameter is the sound command - _music->soundSetSoundOn(obj.toUint16()); - _acc = make_reg(0, _music->soundGetSoundOn()); +reg_t SoundCommandParser::kDoSoundMute(int argc, reg_t *argv, reg_t acc) { + if (argc > 0) + _music->soundSetSoundOn(argv[0].toUint16()); + return make_reg(0, _music->soundGetSoundOn()); } -void SoundCommandParser::cmdMasterVolume(reg_t obj, int16 value) { - debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", value); - _acc = make_reg(0, _music->soundGetMasterVolume()); +reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc) { + acc = make_reg(0, _music->soundGetMasterVolume()); - if (_argc > 1) { // the first parameter is the sound command - int vol = CLIP(obj.toSint16(), 0, kMaxSciVolume); + if (argc > 0) { + debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", argv[0].toSint16()); + int vol = CLIP(argv[0].toSint16(), 0, kMaxSciVolume); vol = vol * Audio::Mixer::kMaxMixerVolume / kMaxSciVolume; ConfMan.setInt("music_volume", vol); ConfMan.setInt("sfx_volume", vol); g_engine->syncSoundSettings(); } + return acc; } -void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } int volume = musicSlot->volume; @@ -385,11 +287,11 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { if (musicSlot->status != kSoundPlaying) { debugC(2, kDebugLevelSound, "cmdFadeSound: fading requested, but sound is currently not playing"); writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); - return; + return acc; } - switch (_argc) { - case 2: // SCI0 + switch (argc) { + case 1: // SCI0 // SCI0 fades out all the time and when fadeout is done it will also // stop the music from playing musicSlot->fadeTo = 0; @@ -398,34 +300,34 @@ void SoundCommandParser::cmdFadeSound(reg_t obj, int16 value) { musicSlot->fadeTicker = 0; break; - case 5: // SCI01+ - case 6: // SCI1+ (SCI1 late sound scheme), with fade and continue - musicSlot->fadeTo = CLIP(_argv[2].toUint16(), 0, MUSIC_VOLUME_MAX); - musicSlot->fadeStep = volume > _argv[2].toUint16() ? -_argv[4].toUint16() : _argv[4].toUint16(); - musicSlot->fadeTickerStep = _argv[3].toUint16() * 16667 / _music->soundGetTempo(); + case 4: // SCI01+ + case 5: // SCI1+ (SCI1 late sound scheme), with fade and continue + musicSlot->fadeTo = CLIP(argv[1].toUint16(), 0, MUSIC_VOLUME_MAX); + musicSlot->fadeStep = volume > argv[1].toUint16() ? -argv[3].toUint16() : argv[3].toUint16(); + musicSlot->fadeTickerStep = argv[2].toUint16() * 16667 / _music->soundGetTempo(); musicSlot->fadeTicker = 0; - musicSlot->stopAfterFading = (_argc == 6) ? (_argv[5].toUint16() != 0) : false; + musicSlot->stopAfterFading = (argc == 5) ? (argv[4].toUint16() != 0) : false; break; default: - error("cmdFadeSound: unsupported argc %d", _argc); + error("cmdFadeSound: unsupported argc %d", argc); } debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); + return acc; } -void SoundCommandParser::cmdGetPolyphony(reg_t obj, int16 value) { - _acc = make_reg(0, _music->soundGetVoices()); // Get the number of voices +reg_t SoundCommandParser::kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc) { + return make_reg(0, _music->soundGetVoices()); // Get the number of voices } -void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } musicSlot->loop = readSelectorValue(_segMan, obj, SELECTOR(loop)); @@ -435,12 +337,15 @@ void SoundCommandParser::cmdUpdateSound(reg_t obj, int16 value) { uint32 objPrio = readSelectorValue(_segMan, obj, SELECTOR(pri)); if (objPrio != musicSlot->priority) _music->soundSetPriority(musicSlot, objPrio); + return acc; } -void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc) { + processUpdateCues(argv[0]); + return acc; +} +void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj)); @@ -460,7 +365,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { musicSlot->sampleLoopCounter = currentLoopCounter; } if ((!_music->soundIsActive(musicSlot)) && (musicSlot->status != kSoundPaused)) { - processStopSound(obj, 0, true); + processStopSound(obj, true); } else { _music->updateAudioStreamTicker(musicSlot); } @@ -482,7 +387,7 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(signal), musicSlot->signal); // We need to do this especially because state selector needs to get updated if (musicSlot->signal == SIGNAL_OFFSET) - cmdStopSound(obj, 0); + processStopSound(obj, false); } } else { // Slot actually has no data (which would mean that a sound-resource w/ @@ -498,10 +403,10 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { // We need signal for sci0 at least in iceman as well (room 14, fireworks) writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); if (_soundVersion <= SCI_VERSION_0_LATE) { - cmdStopSound(obj, 0); + processStopSound(obj, false); } else { if (musicSlot->stopAfterFading) - cmdStopSound(obj, 0); + processStopSound(obj, false); } } @@ -518,39 +423,56 @@ void SoundCommandParser::cmdUpdateCues(reg_t obj, int16 value) { } } -void SoundCommandParser::cmdSendMidi(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + byte channel = argv[2].toUint16() & 0xf; + byte midiCmd = argv[3].toUint16() & 0xff; + + uint16 controller = argv[4].toUint16(); + uint16 param = argv[5].toUint16(); + + if (channel) + channel--; // channel is given 1-based, we are using 0-based + + uint32 midiCommand = (channel | midiCmd) | ((uint32)controller << 8) | ((uint32)param << 16); + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! // if so, allow it //_music->sendMidiCommand(_midiCommand); warning("cmdSendMidi: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } - _music->sendMidiCommand(musicSlot, _midiCommand); + _music->sendMidiCommand(musicSlot, midiCommand); + return acc; } -void SoundCommandParser::cmdReverb(reg_t obj, int16 value) { - _music->setReverb(obj.toUint16() & 0xF); +reg_t SoundCommandParser::kDoSoundReverb(int argc, reg_t *argv, reg_t acc) { + _music->setReverb(argv[0].toUint16() & 0xF); + return acc; } -void SoundCommandParser::cmdSetSoundHold(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } // Set the special hold marker ID where the song should be looped at. - musicSlot->hold = value; + musicSlot->hold = argv[1].toSint16(); + return acc; } -void SoundCommandParser::cmdGetAudioCapability(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc) { // Tests for digital audio support - _acc = make_reg(0, 1); + return make_reg(0, 1); } -void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundStopAll(int argc, reg_t *argv, reg_t acc) { Common::StackLock(_music->_mutex); const MusicList::iterator end = _music->getPlayListEnd(); @@ -558,18 +480,19 @@ void SoundCommandParser::cmdStopAllSounds(reg_t obj, int16 value) { if (_soundVersion <= SCI_VERSION_0_LATE) { writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(state), kSoundStopped); } else { - writeSelectorValue(_segMan, obj, SELECTOR(handle), 0); + writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(handle), 0); writeSelectorValue(_segMan, (*i)->soundObj, SELECTOR(signal), SIGNAL_OFFSET); } (*i)->dataInc = 0; _music->soundStop(*i); } + return acc; } -void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { @@ -578,7 +501,7 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { // the drum sounds of the energizer bunny at the beginning), so this is // normal behavior. //warning("cmdSetSoundVolume: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } debugC(2, kDebugLevelSound, "cmdSetSoundVolume: %d", value); @@ -590,16 +513,17 @@ void SoundCommandParser::cmdSetSoundVolume(reg_t obj, int16 value) { _music->soundSetVolume(musicSlot, value); writeSelectorValue(_segMan, obj, SELECTOR(vol), value); } + return acc; } -void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj)); - return; + return acc; } if (value == -1) { @@ -619,11 +543,12 @@ void SoundCommandParser::cmdSetSoundPriority(reg_t obj, int16 value) { writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) | 2); //DoSOund(0xF,hobj,w) } + return acc; } -void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { - if (!obj.segment) - return; +reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { + reg_t obj = argv[0]; + int16 value = argv[1].toSint16(); MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { @@ -637,7 +562,7 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { } else { // Doesn't really matter } - return; + return acc; } if (value == -1) { musicSlot->loop = 0xFFFF; @@ -646,11 +571,13 @@ void SoundCommandParser::cmdSetSoundLoop(reg_t obj, int16 value) { } writeSelectorValue(_segMan, obj, SELECTOR(loop), musicSlot->loop); + return acc; } -void SoundCommandParser::cmdSuspendSound(reg_t obj, int16 value) { +reg_t SoundCommandParser::kDoSoundSuspend(int argc, reg_t *argv, reg_t acc) { // TODO warning("STUB: cmdSuspendSound"); + return acc; } void SoundCommandParser::updateSci0Cues() { @@ -674,7 +601,7 @@ void SoundCommandParser::updateSci0Cues() { if ((*i)->signal == 0 && (*i)->status != kSoundPlaying) continue; - cmdUpdateCues((*i)->soundObj, 0); + processUpdateCues((*i)->soundObj); noOnePlaying = false; } _music->_mutex.unlock(); @@ -708,10 +635,10 @@ void SoundCommandParser::startNewSound(int number) { // Overwrite the first sound in the playlist MusicEntry *song = *_music->getPlayListStart(); reg_t soundObj = song->soundObj; - cmdDisposeSound(soundObj, 0); + processDisposeSound(soundObj); writeSelectorValue(_segMan, soundObj, SELECTOR(number), number); - cmdInitSound(soundObj, 0); - cmdPlaySound(soundObj, 0); + processInitSound(soundObj); + processPlaySound(soundObj); } void SoundCommandParser::setMasterVolume(int vol) { diff --git a/engines/sci/sound/soundcmd.h b/engines/sci/sound/soundcmd.h index d1a81462fe..a8bc1eb280 100644 --- a/engines/sci/sound/soundcmd.h +++ b/engines/sci/sound/soundcmd.h @@ -34,13 +34,13 @@ namespace Sci { class Console; class SciMusic; class SoundCommandParser; -typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); +//typedef void (SoundCommandParser::*SoundCommand)(reg_t obj, int16 value); -struct MusicEntryCommand { - MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {} - SoundCommand sndCmd; - const char *desc; -}; +//struct MusicEntryCommand { +// MusicEntryCommand(const char *d, SoundCommand c) : sndCmd(c), desc(d) {} +// SoundCommand sndCmd; +// const char *desc; +//}; class SoundCommandParser { public: @@ -51,7 +51,7 @@ public: kMaxSciVolume = 15 }; - reg_t parseCommand(int argc, reg_t *argv, reg_t acc); + //reg_t parseCommand(int argc, reg_t *argv, reg_t acc); // Functions used for game state loading void clearPlayList(); @@ -63,13 +63,14 @@ public: void pauseAll(bool pause); // Debug console functions - void playSound(reg_t obj) { cmdPlaySound(obj, 0); } - void stopSound(reg_t obj) { cmdStopSound(obj, 0); } void startNewSound(int number); void stopAllSounds(); void printPlayList(Console *con); void printSongInfo(reg_t obj, Console *con); + void processPlaySound(reg_t obj); + void processStopSound(reg_t obj, bool sampleFinishedPlaying); + /** * Synchronizes the current state of the music list to the rest of the engine, so that * the changes that the sound thread makes to the music are registered with the engine @@ -79,45 +80,42 @@ public: */ void updateSci0Cues(); + reg_t kDoSoundInit(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundPlay(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundDummy(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundMute(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundPause(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundResume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundStop(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundStopAll(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundDispose(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundFade(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundGetPolyphony(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundUpdate(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundReverb(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetHold(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundGetAudioCapability(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc); + reg_t kDoSoundSuspend(int argc, reg_t *argv, reg_t acc); + private: - typedef Common::Array SoundCommandContainer; - SoundCommandContainer _soundCommands; + //typedef Common::Array SoundCommandContainer; + //SoundCommandContainer _soundCommands; ResourceManager *_resMan; SegManager *_segMan; Kernel *_kernel; SciMusic *_music; AudioPlayer *_audio; SciVersion _soundVersion; - int _argc; - reg_t *_argv; // for cmdFadeSound - uint32 _midiCommand; // for cmdSendMidi - reg_t _acc; - int _cmdUpdateCuesIndex; - - void cmdInitSound(reg_t obj, int16 value); - void cmdPlaySound(reg_t obj, int16 value); - void cmdDummy(reg_t obj, int16 value); - void cmdMuteSound(reg_t obj, int16 value); - void cmdPauseSound(reg_t obj, int16 value); - void cmdResumeSound(reg_t obj, int16 value); - void cmdStopSound(reg_t obj, int16 value); - void cmdDisposeSound(reg_t obj, int16 value); - void cmdMasterVolume(reg_t obj, int16 value); - void cmdFadeSound(reg_t obj, int16 value); - void cmdGetPolyphony(reg_t obj, int16 value); - void cmdStopAllSounds(reg_t obj, int16 value); - void cmdUpdateSound(reg_t obj, int16 value); - void cmdUpdateCues(reg_t obj, int16 value); - void cmdSendMidi(reg_t obj, int16 value); - void cmdReverb(reg_t obj, int16 value); - void cmdSetSoundHold(reg_t obj, int16 value); - void cmdGetAudioCapability(reg_t obj, int16 value); - void cmdSetSoundVolume(reg_t obj, int16 value); - void cmdSetSoundPriority(reg_t obj, int16 value); - void cmdSetSoundLoop(reg_t obj, int16 value); - void cmdSuspendSound(reg_t obj, int16 value); - - void processStopSound(reg_t obj, int16 value, bool sampleFinishedPlaying); + + void processInitSound(reg_t obj); + void processDisposeSound(reg_t obj); + void processUpdateCues(reg_t obj); }; } // End of namespace Sci -- cgit v1.2.3 From 125f28c367288ae9fe2992aaa96541ae067d7511 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 12:26:54 +0000 Subject: SCI: fixing signature for kDoSound(suspend) svn-id: r50756 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 501ad54dfa..4af3b4d547 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -289,7 +289,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1LATE, 2, MAP_CALL(DoSoundDummy), "", NULL }, { SIG_SOUNDSCI1LATE, 3, MAP_CALL(DoSoundGetPolyphony), NULL, NULL }, { SIG_SOUNDSCI1LATE, 4, MAP_CALL(DoSoundGetAudioCapability), "", NULL }, - { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "", NULL }, + { SIG_SOUNDSCI1LATE, 5, MAP_CALL(DoSoundSuspend), "i", NULL }, { SIG_SOUNDSCI1LATE, 6, MAP_CALL(DoSoundInit), NULL, NULL }, { SIG_SOUNDSCI1LATE, 7, MAP_CALL(DoSoundDispose), NULL, NULL }, { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, -- cgit v1.2.3 From b602e7071be26838288d9b8f162a3dff70b7927f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 12:30:34 +0000 Subject: SCI: fixing regression of r50755 - fixing kDoSoundSendMidi svn-id: r50757 --- engines/sci/sound/soundcmd.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 6732137962..e3c78a06cb 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -425,11 +425,11 @@ void SoundCommandParser::processUpdateCues(reg_t obj) { reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; - byte channel = argv[2].toUint16() & 0xf; - byte midiCmd = argv[3].toUint16() & 0xff; + byte channel = argv[1].toUint16() & 0xf; + byte midiCmd = argv[2].toUint16() & 0xff; - uint16 controller = argv[4].toUint16(); - uint16 param = argv[5].toUint16(); + uint16 controller = argv[3].toUint16(); + uint16 param = argv[4].toUint16(); if (channel) channel--; // channel is given 1-based, we are using 0-based -- cgit v1.2.3 From b8933d7e8f1886cc22b0ef8face8ead4e890c3e6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 13:01:48 +0000 Subject: SCI: removing unneeded mutex locking inside sci0 update cues svn-id: r50758 --- engines/sci/sound/soundcmd.cpp | 3 --- 1 file changed, 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index e3c78a06cb..b1ad11651f 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -584,8 +584,6 @@ void SoundCommandParser::updateSci0Cues() { bool noOnePlaying = true; MusicEntry *pWaitingForPlay = NULL; - _music->_mutex.lock(); - const MusicList::iterator end = _music->getPlayListEnd(); for (MusicList::iterator i = _music->getPlayListStart(); i != end; ++i) { // Is the sound stopped, and the sound object updated too? If yes, skip @@ -604,7 +602,6 @@ void SoundCommandParser::updateSci0Cues() { processUpdateCues((*i)->soundObj); noOnePlaying = false; } - _music->_mutex.unlock(); if (noOnePlaying && pWaitingForPlay) { // If there is a queued entry, play it now ffs: SciMusic::soundPlay() -- cgit v1.2.3 From aadf2e976555d08b7f8e773cc4d69882fa1c9d3d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 14:11:27 +0000 Subject: SCI: added currently commented-out pauseSound implementation for some sci0 games, allowing integer for that subfunction svn-id: r50759 --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/sound/music.cpp | 20 ++++++++++++++++++-- engines/sci/sound/music.h | 1 + engines/sci/sound/soundcmd.cpp | 24 ++++++++++++++++++++++-- 4 files changed, 42 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4af3b4d547..99c2ba1d5d 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -260,7 +260,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "o", NULL }, { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL }, { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL }, - { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "[o0]", NULL }, + { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "[o0i]", NULL }, { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "o", NULL }, { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL }, { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL }, diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index 874f0a381e..cf084f81eb 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -166,8 +166,6 @@ void SciMusic::pauseAll(bool pause) { } void SciMusic::stopAll() { - Common::StackLock lock(_mutex); - const MusicList::iterator end = _playList.end(); for (MusicList::iterator i = _playList.begin(); i != end; ++i) { soundStop(*i); @@ -199,6 +197,24 @@ MusicEntry *SciMusic::getSlot(reg_t obj) { return NULL; } +// We return the currently active music slot for SCI0 +MusicEntry *SciMusic::getActiveSci0MusicSlot() { + const MusicList::iterator end = _playList.end(); + MusicEntry *highestPrioritySlot = NULL; + for (MusicList::iterator i = _playList.begin(); i != end; ++i) { + MusicEntry *playSlot = *i; + if (playSlot->pMidiParser) { + if (playSlot->status == kSoundPlaying) + return playSlot; + if (playSlot->status == kSoundPaused) { + if ((!highestPrioritySlot) || (highestPrioritySlot->priority < playSlot->priority)) + highestPrioritySlot = playSlot; + } + } + } + return highestPrioritySlot; +} + void SciMusic::setReverb(byte reverb) { Common::StackLock lock(_mutex); _pMidiDrv->setReverb(reverb); diff --git a/engines/sci/sound/music.h b/engines/sci/sound/music.h index 486848b48f..943a5bd2a8 100644 --- a/engines/sci/sound/music.h +++ b/engines/sci/sound/music.h @@ -157,6 +157,7 @@ public: } MusicEntry *getSlot(reg_t obj); + MusicEntry *getActiveSci0MusicSlot(); void pushBackSlot(MusicEntry *slotEntry) { Common::StackLock lock(_mutex); diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index b1ad11651f..b23aed4745 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -213,8 +213,28 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { uint16 value = argc > 1 ? argv[1].toUint16() : 0; if (!obj.segment) { // pause the whole playlist - // Pausing/Resuming the whole playlist was introduced in the SCI1 late - // sound scheme. + // SCI0 games (up to including qfg1) give us 0/1 for either resuming or pausing the current music + // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume + if (_soundVersion <= SCI_VERSION_0_LATE) { + // TODO: this code doesn't work right currently + return make_reg(0, 0); + MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); + switch (obj.offset) { + case 1: + if ((musicSlot) && (musicSlot->status == kSoundPlaying)) + _music->soundPause(musicSlot); + return make_reg(0, 0); + case 0: + if ((musicSlot) && (musicSlot->status == kSoundPaused)) + _music->soundResume(musicSlot); + return make_reg(0, 1); + return make_reg(0, 0); + default: + error("kDoSoundPause: parameter 0 is invalid for sound-sci0"); + } + } + + // Pausing/Resuming the whole playlist was introduced in the SCI1 late sound scheme. if (_soundVersion <= SCI_VERSION_1_EARLY) return acc; -- cgit v1.2.3 From eddd6d0dba563349b1d3a16bf0251ba9f5f194c1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 16:05:47 +0000 Subject: SCI: actually all sound-sci0 games used a completely different kDoSoundPause logic, implement it - fixes all sorts of games not pausing when going to restore menu and more svn-id: r50760 --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/sound/soundcmd.cpp | 38 +++++++++++++++++++------------------- 2 files changed, 20 insertions(+), 20 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 99c2ba1d5d..3e30480b99 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -260,7 +260,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI0, 3, MAP_CALL(DoSoundDispose), "o", NULL }, { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL }, { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL }, - { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "[o0i]", NULL }, + { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "i", NULL }, { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "o", NULL }, { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL }, { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL }, diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index b23aed4745..26fbfb6c7c 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -209,30 +209,30 @@ void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) } reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { + if (_soundVersion <= SCI_VERSION_0_LATE) { + uint16 value = argv[0].toUint16(); + MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); + switch (value) { + case 1: + if ((musicSlot) && (musicSlot->status == kSoundPlaying)) + _music->soundPause(musicSlot); + return make_reg(0, 0); + case 0: + if ((musicSlot) && (musicSlot->status == kSoundPaused)) { + _music->soundResume(musicSlot); + return make_reg(0, 1); + } + return make_reg(0, 0); + default: + error("kDoSoundPause: parameter 0 is invalid for sound-sci0"); + } + } + reg_t obj = argv[0]; uint16 value = argc > 1 ? argv[1].toUint16() : 0; - if (!obj.segment) { // pause the whole playlist // SCI0 games (up to including qfg1) give us 0/1 for either resuming or pausing the current music // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume - if (_soundVersion <= SCI_VERSION_0_LATE) { - // TODO: this code doesn't work right currently - return make_reg(0, 0); - MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); - switch (obj.offset) { - case 1: - if ((musicSlot) && (musicSlot->status == kSoundPlaying)) - _music->soundPause(musicSlot); - return make_reg(0, 0); - case 0: - if ((musicSlot) && (musicSlot->status == kSoundPaused)) - _music->soundResume(musicSlot); - return make_reg(0, 1); - return make_reg(0, 0); - default: - error("kDoSoundPause: parameter 0 is invalid for sound-sci0"); - } - } // Pausing/Resuming the whole playlist was introduced in the SCI1 late sound scheme. if (_soundVersion <= SCI_VERSION_1_EARLY) -- cgit v1.2.3 From 541daf918aa9734692b7a58ec80ba03a975bd8fb Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 9 Jul 2010 16:53:20 +0000 Subject: Introduce the RivenScriptManager to keep track of scripts and free them when required. The old way of using SharedPtr was quite hacky and didn't work properly when talking to Gehn in ospit. svn-id: r50761 --- engines/mohawk/console.cpp | 12 +++++--- engines/mohawk/riven.cpp | 18 +++++++---- engines/mohawk/riven.h | 1 + engines/mohawk/riven_scripts.cpp | 66 ++++++++++++++++++++++++++++------------ engines/mohawk/riven_scripts.h | 33 ++++++++++++++------ 5 files changed, 92 insertions(+), 38 deletions(-) (limited to 'engines') diff --git a/engines/mohawk/console.cpp b/engines/mohawk/console.cpp index abdcf42dc0..5dcfff4f90 100644 --- a/engines/mohawk/console.cpp +++ b/engines/mohawk/console.cpp @@ -558,9 +558,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { printf ("==================================\n\n"); Common::SeekableReadStream *cardStream = _vm->getRawData(MKID_BE('CARD'), (uint16)atoi(argv[3])); cardStream->seek(4); - RivenScriptList scriptList = RivenScript::readScripts(_vm, cardStream); - for (uint32 i = 0; i < scriptList.size(); i++) + RivenScriptList scriptList = _vm->_scriptMan->readScripts(cardStream, false); + for (uint32 i = 0; i < scriptList.size(); i++) { scriptList[i]->dumpScript(varNames, xNames, 0); + delete scriptList[i]; + } delete cardStream; } else if (!scumm_stricmp(argv[2], "HSPT")) { printf ("\n\nDumping scripts for %s\'s card %d hotspots!\n", argv[1], (uint16)atoi(argv[3])); @@ -573,9 +575,11 @@ bool RivenConsole::Cmd_DumpScript(int argc, const char **argv) { for (uint16 i = 0; i < hotspotCount; i++) { printf ("Hotspot %d:\n", i); hsptStream->seek(22, SEEK_CUR); // Skip non-script related stuff - RivenScriptList scriptList = RivenScript::readScripts(_vm, hsptStream); - for (uint32 j = 0; j < scriptList.size(); j++) + RivenScriptList scriptList = _vm->_scriptMan->readScripts(hsptStream, false); + for (uint32 j = 0; j < scriptList.size(); j++) { scriptList[j]->dumpScript(varNames, xNames, 1); + delete scriptList[j]; + } } delete hsptStream; diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index 81e33d6513..07b08dc220 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -53,6 +53,7 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _ignoreNextMouseUp = false; _extrasFile = NULL; _curStack = aspit; + _hotspots = NULL; // NOTE: We can never really support CD swapping. All of the music files // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive @@ -80,16 +81,17 @@ MohawkEngine_Riven::~MohawkEngine_Riven() { delete _externalScriptHandler; delete _extrasFile; delete _saveLoad; + delete _scriptMan; delete[] _vars; delete _optionsDialog; delete _rnd; + delete[] _hotspots; delete g_atrusJournalRect1; delete g_atrusJournalRect2; delete g_cathJournalRect2; delete g_atrusJournalRect3; delete g_cathJournalRect3; delete g_trapBookRect3; - _cardData.scripts.clear(); } GUI::Debugger *MohawkEngine_Riven::getDebugger() { @@ -105,6 +107,7 @@ Common::Error MohawkEngine_Riven::run() { _saveLoad = new RivenSaveLoad(this, _saveFileMan); _externalScriptHandler = new RivenExternal(this); _optionsDialog = new RivenOptionsDialog(this); + _scriptMan = new RivenScriptManager(this); _rnd = new Common::RandomSource(); g_eventRec.registerRandomSource(*_rnd, "riven"); @@ -347,13 +350,13 @@ void MohawkEngine_Riven::refreshCard() { } void MohawkEngine_Riven::loadCard(uint16 id) { - // NOTE: Do not clear the card scripts because it may delete a currently running script! + // NOTE: The card scripts are cleared by the RivenScriptManager automatically. Common::SeekableReadStream* inStream = getRawData(ID_CARD, id); _cardData.name = inStream->readSint16BE(); _cardData.zipModePlace = inStream->readUint16BE(); - _cardData.scripts = RivenScript::readScripts(this, inStream); + _cardData.scripts = _scriptMan->readScripts(inStream); _cardData.hasData = true; delete inStream; @@ -371,7 +374,10 @@ void MohawkEngine_Riven::loadCard(uint16 id) { } void MohawkEngine_Riven::loadHotspots(uint16 id) { - // NOTE: Do not clear the hotspots because it may delete a currently running script! + // Clear old hotspots + delete[] _hotspots; + + // NOTE: The hotspot scripts are cleared by the RivenScriptManager automatically. Common::SeekableReadStream* inStream = getRawData(ID_HSPT, id); @@ -413,7 +419,7 @@ void MohawkEngine_Riven::loadHotspots(uint16 id) { _hotspots[i].zipModeHotspot = inStream->readUint16BE(); // Read in the scripts now - _hotspots[i].scripts = RivenScript::readScripts(this, inStream); + _hotspots[i].scripts = _scriptMan->readScripts(inStream); } delete inStream; @@ -649,4 +655,4 @@ bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } -} +} // End of namespace Mohawk diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 3e2ab59597..631285455e 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -113,6 +113,7 @@ public: RivenGraphics *_gfx; RivenExternal *_externalScriptHandler; Common::RandomSource *_rnd; + RivenScriptManager *_scriptMan; Card _cardData; diff --git a/engines/mohawk/riven_scripts.cpp b/engines/mohawk/riven_scripts.cpp index a23fd26b96..1fcaba8ac0 100644 --- a/engines/mohawk/riven_scripts.cpp +++ b/engines/mohawk/riven_scripts.cpp @@ -35,28 +35,16 @@ namespace Mohawk { -RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType) - : _vm(vm), _stream(stream), _scriptType(scriptType) { +RivenScript::RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard) + : _vm(vm), _stream(stream), _scriptType(scriptType), _parentStack(parentStack), _parentCard(parentCard) { setupOpcodes(); + _isRunning = false; } RivenScript::~RivenScript() { delete _stream; } -RivenScriptList RivenScript::readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream) { - RivenScriptList scriptList; - - uint16 scriptCount = stream->readUint16BE(); - for (uint16 i = 0; i < scriptCount; i++) { - uint16 scriptType = stream->readUint16BE(); - uint32 scriptSize = calculateScriptSize(stream); - scriptList.push_back(Common::SharedPtr(new RivenScript(vm, stream->readStream(scriptSize), scriptType))); - } - - return scriptList; -} - uint32 RivenScript::calculateCommandSize(Common::SeekableReadStream* script) { uint16 command = script->readUint16BE(); uint32 commandSize = 2; @@ -161,7 +149,7 @@ void RivenScript::setupOpcodes() { OPCODE(activateFLST), OPCODE(zipMode), OPCODE(activateMLST), - OPCODE(activateSLSTWithVolume) + OPCODE(empty) // Activate an SLST with a volume parameter (not used) }; _opcodes = riven_opcodes; @@ -239,10 +227,13 @@ void RivenScript::dumpCommands(Common::StringArray varNames, Common::StringArray } void RivenScript::runScript() { + _isRunning = true; + if (_stream->pos() != 0) _stream->seek(0); processCommands(true); + _isRunning = false; } void RivenScript::processCommands(bool runCommands) { @@ -610,9 +601,46 @@ void RivenScript::activateMLST(uint16 op, uint16 argc, uint16 *argv) { _vm->_video->activateMLST(argv[0], _vm->getCurCard()); } -// Command 47: activate SLST record with a volume argument -void RivenScript::activateSLSTWithVolume(uint16 op, uint16 argc, uint16 *argv) { - warning("STUB: activateSLSTWithVolume()"); +RivenScriptManager::RivenScriptManager(MohawkEngine_Riven *vm) { + _vm = vm; +} + +RivenScriptManager::~RivenScriptManager() { + for (uint32 i = 0; i < _currentScripts.size(); i++) + delete _currentScripts[i]; +} + +RivenScriptList RivenScriptManager::readScripts(Common::SeekableReadStream *stream, bool garbageCollect) { + if (garbageCollect) + unloadUnusedScripts(); // Garbage collect! + + RivenScriptList scriptList; + + uint16 scriptCount = stream->readUint16BE(); + for (uint16 i = 0; i < scriptCount; i++) { + uint16 scriptType = stream->readUint16BE(); + uint32 scriptSize = RivenScript::calculateScriptSize(stream); + RivenScript *script = new RivenScript(_vm, stream->readStream(scriptSize), scriptType, _vm->getCurStack(), _vm->getCurCard()); + scriptList.push_back(script); + + // Only add it to the scripts that we will free later if it is requested. + // (ie. we don't want to store scripts from the dumpScript console command) + if (garbageCollect) + _currentScripts.push_back(script); + } + + return scriptList; +} + +void RivenScriptManager::unloadUnusedScripts() { + // Free any scripts that aren't part of the current card and aren't running + for (uint32 i = 0; i < _currentScripts.size(); i++) { + if ((_vm->getCurStack() != _currentScripts[i]->getParentStack() || _vm->getCurCard() != _currentScripts[i]->getParentCard()) && !_currentScripts[i]->isRunning()) { + delete _currentScripts[i]; + _currentScripts.remove_at(i); + i--; + } + } } } // End of namespace Mohawk diff --git a/engines/mohawk/riven_scripts.h b/engines/mohawk/riven_scripts.h index a1512af697..5187bbde08 100644 --- a/engines/mohawk/riven_scripts.h +++ b/engines/mohawk/riven_scripts.h @@ -50,19 +50,20 @@ enum { }; class RivenScript; -typedef Common::Array > RivenScriptList; class RivenScript { public: - RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType); + RivenScript(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream, uint16 scriptType, uint16 parentStack, uint16 parentCard); ~RivenScript(); void runScript(); void dumpScript(Common::StringArray varNames, Common::StringArray xNames, byte tabs); uint16 getScriptType() { return _scriptType; } + uint16 getParentStack() { return _parentStack; } + uint16 getParentCard() { return _parentCard; } + bool isRunning() { return _isRunning; } - // Read in an array of script objects from a stream - static RivenScriptList readScripts(MohawkEngine_Riven *vm, Common::SeekableReadStream *stream); + static uint32 calculateScriptSize(Common::SeekableReadStream *script); private: typedef void (RivenScript::*OpcodeProcRiven)(uint16 op, uint16 argc, uint16 *argv); @@ -70,18 +71,18 @@ private: OpcodeProcRiven proc; const char *desc; }; - const RivenOpcode* _opcodes; + const RivenOpcode *_opcodes; void setupOpcodes(); MohawkEngine_Riven *_vm; Common::SeekableReadStream *_stream; - uint16 _scriptType; + uint16 _scriptType, _parentStack, _parentCard, _parentHotspot; + bool _isRunning; void dumpCommands(Common::StringArray varNames, Common::StringArray xNames, byte tabs); void processCommands(bool runCommands); - static uint32 calculateCommandSize(Common::SeekableReadStream* script); - static uint32 calculateScriptSize(Common::SeekableReadStream* script); + static uint32 calculateCommandSize(Common::SeekableReadStream *script); DECLARE_OPCODE(empty) { warning ("Unknown Opcode %04x", op); } @@ -120,7 +121,21 @@ private: DECLARE_OPCODE(activateFLST); DECLARE_OPCODE(zipMode); DECLARE_OPCODE(activateMLST); - DECLARE_OPCODE(activateSLSTWithVolume); +}; + +typedef Common::Array RivenScriptList; + +class RivenScriptManager { +public: + RivenScriptManager(MohawkEngine_Riven *vm); + ~RivenScriptManager(); + + RivenScriptList readScripts(Common::SeekableReadStream *stream, bool garbageCollect = true); + +private: + void unloadUnusedScripts(); + RivenScriptList _currentScripts; + MohawkEngine_Riven *_vm; }; } // End of namespace Mohawk -- cgit v1.2.3 From 0e4bf4aff70846b77bac2f39d0f031cede6afa05 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 9 Jul 2010 16:53:50 +0000 Subject: Fix some other valgrind warnings. svn-id: r50762 --- engines/mohawk/sound.cpp | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/mohawk/sound.cpp b/engines/mohawk/sound.cpp index 5e1ea8cdb2..091bd68021 100644 --- a/engines/mohawk/sound.cpp +++ b/engines/mohawk/sound.cpp @@ -233,6 +233,10 @@ void Sound::playSLST(uint16 index, uint16 card) { if (slstRecord.index == index) { playSLST(slstRecord); + delete[] slstRecord.sound_ids; + delete[] slstRecord.volumes; + delete[] slstRecord.balances; + delete[] slstRecord.u2; delete slstStream; return; } @@ -244,6 +248,7 @@ void Sound::playSLST(uint16 index, uint16 card) { } delete slstStream; + // No matching records, assume we need to stop all SLST's stopAllSLST(); } @@ -277,8 +282,11 @@ void Sound::playSLST(SLSTRecord slstRecord) { } void Sound::stopAllSLST() { - for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) + for (uint16 i = 0; i < _currentSLSTSounds.size(); i++) { _vm->_mixer->stopHandle(*_currentSLSTSounds[i].handle); + delete _currentSLSTSounds[i].handle; + } + _currentSLSTSounds.clear(); } @@ -314,6 +322,7 @@ void Sound::playSLSTSound(uint16 id, bool fade, bool loop, uint16 volume, int16 void Sound::stopSLSTSound(uint16 index, bool fade) { // TODO: Fade out, mixer needs to be extended to get volume on a handle _vm->_mixer->stopHandle(*_currentSLSTSounds[index].handle); + delete _currentSLSTSounds[index].handle; _currentSLSTSounds.remove_at(index); } -- cgit v1.2.3 From 18d1ab8c709602d71ad4175c29d4517f1bc5bbab Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 18:11:42 +0000 Subject: SCI: move comments and change selector for sci0 sound in kDoSoundPause, also allow pausing everything even for sci1early (qfg2 is using it) svn-id: r50765 --- engines/sci/sound/soundcmd.cpp | 22 +++++++--------------- 1 file changed, 7 insertions(+), 15 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 26fbfb6c7c..5ac8c6b270 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -210,16 +210,21 @@ void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { if (_soundVersion <= SCI_VERSION_0_LATE) { + // SCI0 games give us 0/1 for either resuming or pausing the current music + // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume uint16 value = argv[0].toUint16(); MusicEntry *musicSlot = _music->getActiveSci0MusicSlot(); switch (value) { case 1: - if ((musicSlot) && (musicSlot->status == kSoundPlaying)) + if ((musicSlot) && (musicSlot->status == kSoundPlaying)) { _music->soundPause(musicSlot); + writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); + } return make_reg(0, 0); case 0: if ((musicSlot) && (musicSlot->status == kSoundPaused)) { _music->soundResume(musicSlot); + writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPlaying); return make_reg(0, 1); } return make_reg(0, 0); @@ -231,13 +236,6 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { reg_t obj = argv[0]; uint16 value = argc > 1 ? argv[1].toUint16() : 0; if (!obj.segment) { // pause the whole playlist - // SCI0 games (up to including qfg1) give us 0/1 for either resuming or pausing the current music - // this one doesn't count, so pausing 2 times and resuming once means here that we are supposed to resume - - // Pausing/Resuming the whole playlist was introduced in the SCI1 late sound scheme. - if (_soundVersion <= SCI_VERSION_1_EARLY) - return acc; - _music->pauseAll(value); } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); @@ -246,13 +244,7 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { return acc; } - if (_soundVersion <= SCI_VERSION_0_LATE) { - // Always pause the sound in SCI0 games. It's resumed in cmdResumeSound() - writeSelectorValue(_segMan, musicSlot->soundObj, SELECTOR(state), kSoundPaused); - _music->soundPause(musicSlot); - } else { - _music->soundToggle(musicSlot, value); - } + _music->soundToggle(musicSlot, value); } return acc; } -- cgit v1.2.3 From 3fe205ba7f376bcc7f4f87226b61918acb9ce925 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 18:35:46 +0000 Subject: SCI: fixing regression of r50414 - we set volume to standard levels inside initCommands since then, so if we set the actual needed volume before calling that it will get ignored - fixes lsl1demo svn-id: r50766 --- engines/sci/sound/music.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/sound/music.cpp b/engines/sci/sound/music.cpp index cf084f81eb..55a7e1fdc4 100644 --- a/engines/sci/sound/music.cpp +++ b/engines/sci/sound/music.cpp @@ -374,9 +374,10 @@ void SciMusic::soundPlay(MusicEntry *pSnd) { _mutex.lock(); pSnd->pMidiParser->mainThreadBegin(); pSnd->pMidiParser->tryToOwnChannels(); + if (pSnd->status == kSoundStopped) + pSnd->pMidiParser->sendInitCommands(); pSnd->pMidiParser->setVolume(pSnd->volume); if (pSnd->status == kSoundStopped) { - pSnd->pMidiParser->sendInitCommands(); pSnd->pMidiParser->jumpToTick(0); } else { // Fast forward to the last position and perform associated events when loading -- cgit v1.2.3 From d27e4a475bde10c00e7f7f67ce7f4e14cc634db2 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 21:10:14 +0000 Subject: SCI: removing origName from KernelFunction struct, adding debugCalls boolean for later use svn-id: r50769 --- engines/sci/engine/kernel.cpp | 115 ++++++++++++++++++++---------------------- engines/sci/engine/kernel.h | 5 +- engines/sci/engine/vm.cpp | 8 +-- 3 files changed, 63 insertions(+), 65 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 3e30480b99..2b8daf03d1 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -1006,11 +1006,12 @@ void Kernel::mapFunctions() { // Reset the table entry _kernelFuncs[id].function = NULL; _kernelFuncs[id].signature = NULL; - _kernelFuncs[id].origName = kernelName; + _kernelFuncs[id].name = NULL; _kernelFuncs[id].isDummy = true; _kernelFuncs[id].workarounds = NULL; _kernelFuncs[id].subFunctions = NULL; _kernelFuncs[id].subFunctionCount = 0; + _kernelFuncs[id].debugCalls = false; if (kernelName.empty()) { // No name was given -> must be an unknown opcode warning("Kernel function %x unknown", id); @@ -1038,70 +1039,66 @@ void Kernel::mapFunctions() { if (kernelMap->name) { // A match was found - if (kernelMap->function) { - _kernelFuncs[id].function = kernelMap->function; - _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); - _kernelFuncs[id].workarounds = kernelMap->workarounds; - _kernelFuncs[id].isDummy = false; - if (kernelMap->subFunctions) { - // Get version for subfunction identification - SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; - // Now check whats the highest subfunction-id for this version - const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions; - uint16 subFunctionCount = 0; - while (kernelSubMap->function) { - if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) - if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) - if (subFunctionCount <= kernelSubMap->id) - subFunctionCount = kernelSubMap->id + 1; - kernelSubMap++; - } - if (!subFunctionCount) - error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id); - // Now allocate required memory and go through it again - _kernelFuncs[id].subFunctionCount = subFunctionCount; - KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount]; - _kernelFuncs[id].subFunctions = subFunctions; - memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount); - // And fill this info out - kernelSubMap = kernelMap->subFunctions; - uint kernelSubNr = 0; - while (kernelSubMap->function) { - if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) - if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { - uint subId = kernelSubMap->id; - subFunctions[subId].function = kernelSubMap->function; - subFunctions[subId].name = kernelSubMap->name; - subFunctions[subId].workarounds = kernelSubMap->workarounds; - if (kernelSubMap->signature) { - subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); - } else { - // we go back the submap to find the previous signature for that kernel call - const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; - uint kernelSubLeft = kernelSubNr; - while (kernelSubLeft) { - kernelSubLeft--; - kernelSubMapBack--; - if (kernelSubMapBack->name == kernelSubMap->name) { - if (kernelSubMapBack->signature) { - subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); - break; - } + _kernelFuncs[id].function = kernelMap->function; + _kernelFuncs[id].name = kernelMap->name; + _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); + _kernelFuncs[id].workarounds = kernelMap->workarounds; + _kernelFuncs[id].isDummy = false; + if (kernelMap->subFunctions) { + // Get version for subfunction identification + SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; + // Now check whats the highest subfunction-id for this version + const SciKernelMapSubEntry *kernelSubMap = kernelMap->subFunctions; + uint16 subFunctionCount = 0; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) + if (subFunctionCount <= kernelSubMap->id) + subFunctionCount = kernelSubMap->id + 1; + kernelSubMap++; + } + if (!subFunctionCount) + error("k%s[%x]: no subfunctions found for requested version", kernelName.c_str(), id); + // Now allocate required memory and go through it again + _kernelFuncs[id].subFunctionCount = subFunctionCount; + KernelSubFunction *subFunctions = new KernelSubFunction[subFunctionCount]; + _kernelFuncs[id].subFunctions = subFunctions; + memset(subFunctions, 0, sizeof(KernelSubFunction) * subFunctionCount); + // And fill this info out + kernelSubMap = kernelMap->subFunctions; + uint kernelSubNr = 0; + while (kernelSubMap->function) { + if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) + if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { + uint subId = kernelSubMap->id; + subFunctions[subId].function = kernelSubMap->function; + subFunctions[subId].name = kernelSubMap->name; + subFunctions[subId].workarounds = kernelSubMap->workarounds; + if (kernelSubMap->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); + } else { + // we go back the submap to find the previous signature for that kernel call + const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; + uint kernelSubLeft = kernelSubNr; + while (kernelSubLeft) { + kernelSubLeft--; + kernelSubMapBack--; + if (kernelSubMapBack->name == kernelSubMap->name) { + if (kernelSubMapBack->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); + break; } } - if (!subFunctions[subId].signature) - error("k%s: no previous signatures", kernelSubMap->name); } + if (!subFunctions[subId].signature) + error("k%s: no previous signatures", kernelSubMap->name); } - kernelSubMap++; - kernelSubNr++; - } + } + kernelSubMap++; + kernelSubNr++; } - ++mapped; - } else { - //warning("Ignoring function %s\n", s_kernelFuncMap[found].name); - ++ignored; } + ++mapped; } else { if (nameMatch) error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id); diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a5ea379ba6..b7806ce551 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -141,13 +141,14 @@ struct KernelSubFunction { }; struct KernelFunction { - KernelFunctionCall *function; - Common::String origName; /**< Original name, in case we couldn't map it */ bool isDummy; + KernelFunctionCall *function; + const char *name; uint16 *signature; const SciWorkaroundEntry *workarounds; const KernelSubFunction *subFunctions; uint16 subFunctionCount; + bool debugCalls; }; enum AutoDetectedFeatures { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a0f38c634c..e8a28780fb 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -798,7 +798,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, workaroundFound, &originReply); if (!workaroundFound) { kernel->signatureDebug(kernelCall.signature, argc, argv); - error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernel->getKernelName(kernelFuncNr).c_str(), kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. if (workaround.segment) @@ -827,7 +827,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { argc--; argv++; if (subId >= kernelCall.subFunctionCount) - error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.origName, subId); + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; if (!kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { // Signature mismatch @@ -857,7 +857,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { if (s->_executionStack.begin() != s->_executionStack.end()) s->_executionStack.pop_back(); } else { - Common::String warningMsg = "Dummy function " + kernelCall.origName + + Common::String warningMsg = "Dummy function " + kernel->getKernelName(kernelFuncNr) + Common::String::printf("[0x%x]", kernelFuncNr) + " invoked - ignoring. Params: " + Common::String::printf("%d", argc) + " ("; @@ -871,7 +871,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { // Make sure that the game doesn't call a function that is considered unused. If // that happens, error out. - if (kernelCall.origName == "Dummy") + if (kernel->getKernelName(kernelFuncNr) == "Dummy") error("Kernel function %d was called, which was considered to be unused", kernelFuncNr); } } -- cgit v1.2.3 From af479a20ae1df5d851a854a1d1906072b50166e3 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 21:33:12 +0000 Subject: SCI: adding workaround support for kernel subcalls, cleanup svn-id: r50770 --- engines/sci/engine/vm.cpp | 49 +++++++++++++++++++++++++---------------------- 1 file changed, 26 insertions(+), 23 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index e8a28780fb..0663c18338 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -270,7 +270,7 @@ struct SciTrackOriginReply { int localCallOffset; }; -static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, bool &workaroundFound, SciTrackOriginReply *trackOrigin) { +static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *workaroundList, SciTrackOriginReply *trackOrigin) { EngineState *state = g_sci->getEngineState(); ExecStack *lastCall = state->xs; Script *local_script = state->_segMan->getScriptIfLoaded(lastCall->local_segment); @@ -315,7 +315,6 @@ static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *w if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->inheritanceLevel == inheritanceLevel) && (workaround->objectName == searchObjectName) && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { // Workaround found - workaroundFound = true; return workaround->newValue; } workaround++; @@ -334,8 +333,6 @@ static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *w trackOrigin->methodName = curMethodName; trackOrigin->scriptNr = curScriptNr; trackOrigin->localCallOffset = lastCall->debugLocalCallOffset; - - workaroundFound = false; return make_reg(0xFFFF, 0xFFFF); } @@ -369,10 +366,9 @@ static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, i if (type == VAR_TEMP && r[index].segment == 0xffff) { // Uninitialized read on a temp // We need to find correct replacements for each situation manually - bool workaroundFound; SciTrackOriginReply originReply; - r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, workaroundFound, &originReply); - if (!workaroundFound) + r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply); + if ((r[index].segment == 0xFFFF) && (r[index].offset == 0xFFFF)) error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } return r[index]; @@ -780,25 +776,24 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { } } -static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { +static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { Kernel *kernel = g_sci->getKernel(); - if (kernelFuncNr >= (int)kernel->_kernelFuncs.size()) - error("Invalid kernel function 0x%x requested", kernelFuncNr); + if (kernelCallNr >= (int)kernel->_kernelFuncs.size()) + error("Invalid kernel function 0x%x requested", kernelCallNr); - const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelFuncNr]; + const KernelFunction &kernelCall = kernel->_kernelFuncs[kernelCallNr]; reg_t *argv = s->xs->sp + 1; if (kernelCall.signature && !kernel->signatureMatch(kernelCall.signature, argc, argv)) { // signature mismatch, check if a workaround is available - bool workaroundFound; SciTrackOriginReply originReply; reg_t workaround; - workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, workaroundFound, &originReply); - if (!workaroundFound) { + workaround = trackOriginAndFindWorkaround(0, kernelCall.workarounds, &originReply); + if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { kernel->signatureDebug(kernelCall.signature, argc, argv); - error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelFuncNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. if (workaround.segment) @@ -812,7 +807,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { ExecStack *xstack; xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->debugSelector = kernelFuncNr; + xstack->debugSelector = kernelCallNr; xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function @@ -821,7 +816,7 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { } else { // Sub-functions available, check signature and call that one directly if (argc < 1) - error("[VM] k%s: no subfunction-id parameter given"); + error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr); const uint16 subId = argv[0].toUint16(); // Skip over subfunction-id argc--; @@ -831,8 +826,16 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; if (!kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { // Signature mismatch - kernel->signatureDebug(kernelSubCall.signature, argc, argv); - error("[VM] k%s: subfunction signature mismatch", kernelSubCall.name); + SciTrackOriginReply originReply; + reg_t workaround; + workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); + if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { + kernel->signatureDebug(kernelSubCall.signature, argc, argv); + error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + } + // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment) + return; } s->r_acc = kernelSubCall.function(s, argc, argv); } @@ -857,8 +860,8 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { if (s->_executionStack.begin() != s->_executionStack.end()) s->_executionStack.pop_back(); } else { - Common::String warningMsg = "Dummy function " + kernel->getKernelName(kernelFuncNr) + - Common::String::printf("[0x%x]", kernelFuncNr) + + Common::String warningMsg = "Dummy function " + kernel->getKernelName(kernelCallNr) + + Common::String::printf("[0x%x]", kernelCallNr) + " invoked - ignoring. Params: " + Common::String::printf("%d", argc) + " ("; @@ -871,8 +874,8 @@ static void callKernelFunc(EngineState *s, int kernelFuncNr, int argc) { // Make sure that the game doesn't call a function that is considered unused. If // that happens, error out. - if (kernel->getKernelName(kernelFuncNr) == "Dummy") - error("Kernel function %d was called, which was considered to be unused", kernelFuncNr); + if (kernel->getKernelName(kernelCallNr) == "Dummy") + error("Kernel function %d was called, which was considered to be unused", kernelCallNr); } } -- cgit v1.2.3 From 02cac2d5aadaf73385ea979afdf6222a72b026cf Mon Sep 17 00:00:00 2001 From: Florian Kagerer Date: Fri, 9 Jul 2010 21:36:59 +0000 Subject: KYRA/PC98: fix music volume svn-id: r50772 --- engines/kyra/sound_towns.cpp | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/kyra/sound_towns.cpp b/engines/kyra/sound_towns.cpp index f6d71f8549..8003ca25f3 100644 --- a/engines/kyra/sound_towns.cpp +++ b/engines/kyra/sound_towns.cpp @@ -2788,16 +2788,15 @@ void TownsPC98_OpnSquareSineSource::nextTick(int32 *buffer, uint32 bufferSize) { int32 finOut = 0; for (int ii = 0; ii < 3; ii++) { - if ((_channels[ii].vol >> 4) & 1) - finOut += _tleTable[_channels[ii].out ? _pReslt : 0]; - else - finOut += _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; + int32 finOutTemp = ((_channels[ii].vol >> 4) & 1) ? _tleTable[_channels[ii].out ? _pReslt : 0] : _tlTable[_channels[ii].out ? (_channels[ii].vol & 0x0f) : 0]; if ((1 << ii) & _volMaskA) - finOut = (finOut * _volumeA) / Audio::Mixer::kMaxMixerVolume; + finOutTemp = (finOutTemp * _volumeA) / Audio::Mixer::kMaxMixerVolume; if ((1 << ii) & _volMaskB) - finOut = (finOut * _volumeB) / Audio::Mixer::kMaxMixerVolume; + finOutTemp = (finOutTemp * _volumeB) / Audio::Mixer::kMaxMixerVolume; + + finOut += finOutTemp; } finOut /= 3; -- cgit v1.2.3 From 0cd97ca5c5394aebf542ad7357d8bb0983b2ea09 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Fri, 9 Jul 2010 21:51:20 +0000 Subject: SCI: improve error message on subcall signature mismatch svn-id: r50774 --- engines/sci/engine/vm.cpp | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0663c18338..a354491a83 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -831,7 +831,12 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { kernel->signatureDebug(kernelSubCall.signature, argc, argv); - error("[VM] k%s (%x) signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + int callNameLen = strlen(kernelCall.name); + if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { + const char *subCallName = kernelSubCall.name + callNameLen; + error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + } + error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. if (workaround.segment) -- cgit v1.2.3 From de7108054fe802b0fb283bfc7484988a1344b9e1 Mon Sep 17 00:00:00 2001 From: Matthew Hoops Date: Fri, 9 Jul 2010 22:10:22 +0000 Subject: Add detection for 'Little Monster at School' and the bunch of demos that came on the CD (on the demo server now too). svn-id: r50776 --- engines/mohawk/detection.cpp | 2 + engines/mohawk/detection_tables.h | 135 ++++++++++++++++++++++++++++++++++++++ 2 files changed, 137 insertions(+) (limited to 'engines') diff --git a/engines/mohawk/detection.cpp b/engines/mohawk/detection.cpp index c3a0c17251..f04338239f 100644 --- a/engines/mohawk/detection.cpp +++ b/engines/mohawk/detection.cpp @@ -117,6 +117,8 @@ static const PlainGameDescriptor mohawkGames[] = { {"ruff", "Ruff's Bone"}, {"newkid", "The New Kid on the Block"}, {"arthurrace", "Arthur's Reading Race"}, + {"arthurbday", "Arthur's Birthday"}, + {"lilmonster", "Little Monster at School"}, #endif {0, 0} }; diff --git a/engines/mohawk/detection_tables.h b/engines/mohawk/detection_tables.h index ea72574978..7470dbf1dd 100644 --- a/engines/mohawk/detection_tables.h +++ b/engines/mohawk/detection_tables.h @@ -617,6 +617,21 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + { + { + "tortoise", + "Demo", + AD_ENTRY1("The Tortoise and the Hare Demo", "35d571806838667743c7c15a133e9335"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + { { "arthur", @@ -647,6 +662,21 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + { + { + "arthur", + "Demo v1.1", + AD_ENTRY1("ARTHUR.512", "f19e824e0a2f2745ed698e6aaf44f838"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + { { "arthur", @@ -662,6 +692,21 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + { + { + "arthur", + "Demo", + AD_ENTRY1("Arthur's Teacher Trouble Demo", "dcbd8af6bf25854df8ad36fd13665d08"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + { { "grandma", @@ -707,6 +752,21 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + { + { + "grandma", + "Demo", + AD_ENTRY1("Just Grandma and Me Demo", "552d8729fa77a4a83c88283c7d79bd31"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + { { "ruff", @@ -767,6 +827,21 @@ static const MohawkGameDescription gameDescriptions[] = { 0 }, + { + { + "newkid", + "Demo", + AD_ENTRY1("The New Kid on the Block Demo", "7d33237e0ea452a97f2a3acdfb9e1286"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + { { "arthurrace", @@ -797,6 +872,66 @@ static const MohawkGameDescription gameDescriptions[] = { 0, 0 }, + + { + { + "arthurbday", + "Demo", + AD_ENTRY1("BIRTHDAY.512", "fb73e387cfec65c5c930db068a8f468a"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "arthurbday", + "Demo", + AD_ENTRY1("Arthur's Birthday Demo", "0d974ec635eea615475368e865f1b1c8"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_DEMO, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + GF_DEMO, + 0 + }, + + { + { + "lilmonster", + "", + AD_ENTRY1("MONSTER.512", "e7b24bf8f59106b5c4df51b39eb8c0ef"), + Common::EN_ANY, + Common::kPlatformWindows, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, + + { + { + "lilmonster", + "", + AD_ENTRY1("BookOutline", "970409f9d967d63c05e63113f8e78fe2"), + Common::EN_ANY, + Common::kPlatformMacintosh, + ADGF_NO_FLAGS, + Common::GUIO_NONE + }, + GType_LIVINGBOOKSV1, + 0, + 0 + }, #endif { AD_TABLE_END_MARKER, 0, 0, 0 } -- cgit v1.2.3 From f687a44d2ad911b22408fee0505aab187607b3ef Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 10:20:23 +0000 Subject: SCI: added kPalVary signatures & mapping, removed debug-warnings svn-id: r50777 --- engines/sci/engine/kernel.cpp | 16 ++++- engines/sci/engine/kernel.h | 9 +++ engines/sci/engine/kgraphics.cpp | 137 ++++++++++++++------------------------- 3 files changed, 72 insertions(+), 90 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2b8daf03d1..ce5d4c9f2b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -308,6 +308,18 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +static const SciKernelMapSubEntry kPalVary_subops[] = { + { SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL }, + { SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL }, + { SIG_SCIALL, 2, MAP_CALL(PalVaryGetCurrentStep), "", NULL }, + { SIG_SCIALL, 3, MAP_CALL(PalVaryDeinit), "", NULL }, + { SIG_SCIALL, 4, MAP_CALL(PalVaryChangeTarget), "i", NULL }, + { SIG_SCIALL, 5, MAP_CALL(PalVaryChangeTicks), "i", NULL }, + { SIG_SCIALL, 6, MAP_CALL(PalVaryPauseResume), "i", NULL }, + { SIG_SCI32, 8, MAP_CALL(PalVaryUnknown), "", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + struct SciKernelMapEntry { const char *name; KernelFunctionCall *function; @@ -355,7 +367,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(DoAudio), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(DoAvoider), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DoBresen), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", kDoSound_subops, NULL }, // subop + { MAP_CALL(DoSound), SIG_EVERYWHERE, "i([io])(i)(ii[io])(i)", kDoSound_subops, NULL }, { MAP_CALL(DoSync), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(DrawCel), SIG_SCI11, SIGFOR_PC, "iiiii(i)(i)(r0)", NULL, NULL }, // for kq6 hires { MAP_CALL(DrawCel), SIG_EVERYWHERE, "iiiii(i)(i)", NULL, NULL }, @@ -426,7 +438,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(NumCels), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, - { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", NULL, NULL }, // subop + { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", kPalVary_subops, NULL }, { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index b7806ce551..9c7a9bfbe1 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -491,6 +491,15 @@ reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv); +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv); + //@} } // End of namespace Sci diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index bacba674d7..f006c1e0ae 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -641,97 +641,58 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { } reg_t kPalVary(EngineState *s, int argc, reg_t *argv) { - uint16 operation = argv[0].toUint16(); + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - switch (operation) { - case 0: { // Init - GuiResourceId paletteId; - uint16 ticks, stepStop; - uint16 direction; - if ((argc >= 3) && (argc <= 5)) { - paletteId = argv[1].toUint16(); - ticks = argv[2].toUint16(); - stepStop = argc >= 4 ? argv[3].toUint16() : 64; - direction = argc >= 5 ? argv[4].toUint16() : 1; - warning("kPalVary(init) called with paletteId = %d, ticks = %d, stop = %d, direction = %d", paletteId, ticks, stepStop, direction); - if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction)) - return SIGNAL_REG; - } else { - warning("kPalVary(init) called with unsupported argc %d", argc); - } - break; - } - case 1: { // Reverse - int16 ticks, stepStop, direction; +reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv) { + GuiResourceId paletteId = argv[0].toUint16(); + uint16 ticks = argv[1].toUint16(); + uint16 stepStop = argc >= 3 ? argv[2].toUint16() : 64; + uint16 direction = argc >= 4 ? argv[3].toUint16() : 1; + if (g_sci->_gfxPalette->kernelPalVaryInit(paletteId, ticks, stepStop, direction)) + return SIGNAL_REG; + return NULL_REG; +} - if ((argc >= 1) && (argc <= 4)) { - ticks = argc >= 2 ? argv[1].toUint16() : -1; - stepStop = argc >= 3 ? argv[2].toUint16() : 0; - direction = argc >= 4 ? argv[3].toSint16() : -1; +reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv) { + int16 ticks = argc >= 1 ? argv[0].toUint16() : -1; + int16 stepStop = argc >= 2 ? argv[1].toUint16() : 0; + int16 direction = argc >= 3 ? argv[2].toSint16() : -1; - int16 result = g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction); - warning("kPalVary(reverse) called with ticks = %d, stop = %d, direction = %d", ticks, stepStop, direction); - return make_reg(0, result); - } else { - warning("kPalVary(reverse) called with unsupported argc %d", argc); - } - } - case 2: { // Get Current Step - if (argc == 1) { - int16 currentStep = g_sci->_gfxPalette->kernelPalVaryGetCurrentStep(); - return make_reg(0, currentStep); - } else { - warning("kPalVary(getCurrentStep) called with unsupported argc %d", argc); - } - break; - } - case 3: { // DeInit - if (argc == 1) { - g_sci->_gfxPalette->kernelPalVaryDeinit(); - warning("kPalVary(deinit)"); - } else { - warning("kPalVary(deinit) called with unsupported argc %d", argc); - } - break; - } - case 4: { // Change Target - if (argc == 2) { - GuiResourceId paletteId = argv[1].toUint16(); - int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId); - return make_reg(0, currentStep); - } else { - warning("kPalVary(changeTarget) called with unsupported argc %d", argc); - } - break; - } - case 5: { // Change ticks - if (argc == 2) { - uint16 ticks = argv[1].toUint16(); - g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); - } else { - warning("kPalVary(changeTicks) called with unsupported argc %d", argc); - } - break; - } - case 6: { // Pause/Resume - bool pauseState; - if (argc == 2) { - pauseState = argv[1].isNull() ? false : true; - g_sci->_gfxPalette->kernelPalVaryPause(pauseState); - warning("kPalVary(pause) called with state = %d", pauseState); - } else { - warning("kPalVary(pause) called with unsupported argc %d", argc); - } - break; - } - case 8: { // Unknown (seems to be SCI32 exclusive) - // Called in PQ4 (1 parameter) - warning("kPalVary(8) called with parameter %d (argc %d)", argv[1].toUint16(), argc); - break; - } - default: - error("kPalVary(%d), not implemented (argc = %d)", operation, argc); - } + return make_reg(0, g_sci->_gfxPalette->kernelPalVaryReverse(ticks, stepStop, direction)); +} + +reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv) { + return make_reg(0, g_sci->_gfxPalette->kernelPalVaryGetCurrentStep()); +} + +reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxPalette->kernelPalVaryDeinit(); + return NULL_REG; +} + +reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv) { + GuiResourceId paletteId = argv[1].toUint16(); + int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId); + return make_reg(0, currentStep); +} + +reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) { + uint16 ticks = argv[1].toUint16(); + g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); + return NULL_REG; +} + +reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { + bool pauseState = pauseState = argv[1].isNull() ? false : true; + g_sci->_gfxPalette->kernelPalVaryPause(pauseState); + return NULL_REG; +} + +reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) { + // Unknown (seems to be SCI32 exclusive) return NULL_REG; } -- cgit v1.2.3 From bab61443ac5b59d20f3846518121286338c5724d Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 10 Jul 2010 11:15:10 +0000 Subject: Fixed warning. svn-id: r50778 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index f006c1e0ae..12cac971f0 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -686,7 +686,7 @@ reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) { } reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { - bool pauseState = pauseState = argv[1].isNull() ? false : true; + bool pauseState = argv[1].isNull() ? false : true; g_sci->_gfxPalette->kernelPalVaryPause(pauseState); return NULL_REG; } -- cgit v1.2.3 From cfc93a7e4dff46e1bca4656c2976c1f3c1e68a87 Mon Sep 17 00:00:00 2001 From: Torbjörn Andersson Date: Sat, 10 Jul 2010 11:16:46 +0000 Subject: Simplified the expression. svn-id: r50779 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 12cac971f0..25eb81f65c 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -686,7 +686,7 @@ reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) { } reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { - bool pauseState = argv[1].isNull() ? false : true; + bool pauseState = !argv[1].isNull(); g_sci->_gfxPalette->kernelPalVaryPause(pauseState); return NULL_REG; } -- cgit v1.2.3 From f38348b82e3e6781ae2a166e951fc83f11f8d618 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 12:19:32 +0000 Subject: SCI: adding kPalette signatures, fixing 3 kPalVary calls, fixing kAssertPalette (we used the wrong parameter number before, maybe the issues were caused by this) svn-id: r50780 --- engines/sci/engine/kernel.cpp | 14 ++++- engines/sci/engine/kernel.h | 9 +++ engines/sci/engine/kgraphics.cpp | 131 +++++++++++++++++++++------------------ engines/sci/graphics/palette.cpp | 5 +- 4 files changed, 94 insertions(+), 65 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index ce5d4c9f2b..2069b8ee80 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -320,6 +320,18 @@ static const SciKernelMapSubEntry kPalVary_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +static const SciKernelMapSubEntry kPalette_subops[] = { + { SIG_SCIALL, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, + { SIG_SCIALL, 2, MAP_CALL(PaletteSetFlag), "iii", NULL }, + { SIG_SCIALL, 3, MAP_CALL(PaletteUnsetFlag), "iii", NULL }, + { SIG_SCIALL, 4, MAP_CALL(PaletteSetIntensity), "iii(i)", NULL }, + { SIG_SCIALL, 5, MAP_CALL(PaletteFindColor), "iii", NULL }, + { SIG_SCIALL, 6, MAP_CALL(PaletteAnimate), "i*", NULL }, + { SIG_SCIALL, 7, MAP_CALL(PaletteSave), "", NULL }, + { SIG_SCIALL, 8, MAP_CALL(PaletteRestore), "i", NULL }, + SCI_SUBOPENTRY_TERMINATOR +}; + struct SciKernelMapEntry { const char *name; KernelFunctionCall *function; @@ -439,7 +451,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(NumLoops), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(OnControl), SIG_EVERYWHERE, "ii(i)(i)(i)", NULL, NULL }, { MAP_CALL(PalVary), SIG_EVERYWHERE, "i(i*)", kPalVary_subops, NULL }, - { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", NULL, NULL }, // subop + { MAP_CALL(Palette), SIG_EVERYWHERE, "i(.*)", kPalette_subops, NULL }, { MAP_CALL(Parse), SIG_EVERYWHERE, "ro", NULL, NULL }, { MAP_CALL(PicNotValid), SIG_EVERYWHERE, "(i)", NULL, NULL }, { MAP_CALL(Platform), SIG_EVERYWHERE, "(.*)", NULL, NULL }, diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 9c7a9bfbe1..5815fec53b 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -500,6 +500,15 @@ reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv); +reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv); + //@} } // End of namespace Sci diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 25eb81f65c..9714374ade 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -555,66 +555,72 @@ reg_t kSetNowSeen(EngineState *s, int argc, reg_t *argv) { return s->r_acc; } +// we are called on EGA/amiga games as well, this doesnt make sense. +// doing this would actually break the system EGA/amiga palette reg_t kPalette(EngineState *s, int argc, reg_t *argv) { - // we are called on EGA/amiga games as well, this doesnt make sense. - // doing this would actually break the system EGA/amiga palette - if (!g_sci->getResMan()->isVGA()) - return s->r_acc; + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - switch (argv[0].toUint16()) { - case 1: // Set resource palette - if (argc == 2 || argc == 3) { - GuiResourceId resourceId = argv[1].toUint16(); - bool force = false; - if (argc == 3) - force = argv[2].toUint16() == 2 ? true : false; - g_sci->_gfxPalette->kernelSetFromResource(resourceId, force); - } else { - warning("kPalette(1) called with %d parameters", argc); - } - break; - case 2: { // Set palette-flag(s) - uint16 fromColor = CLIP(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP(argv[2].toUint16(), 1, 255); - uint16 flags = argv[3].toUint16(); +reg_t kPaletteSetFromResource(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + GuiResourceId resourceId = argv[0].toUint16(); + bool force = false; + if (argc == 2) + force = argv[1].toUint16() == 2 ? true : false; + g_sci->_gfxPalette->kernelSetFromResource(resourceId, force); + } + return s->r_acc; +} + +reg_t kPaletteSetFlag(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP(argv[1].toUint16(), 1, 255); + uint16 flags = argv[2].toUint16(); g_sci->_gfxPalette->kernelSetFlag(fromColor, toColor, flags); - break; } - case 3: { // Remove palette-flag(s) - uint16 fromColor = CLIP(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP(argv[2].toUint16(), 1, 255); - uint16 flags = argv[3].toUint16(); + return s->r_acc; +} + +reg_t kPaletteUnsetFlag(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP(argv[1].toUint16(), 1, 255); + uint16 flags = argv[2].toUint16(); g_sci->_gfxPalette->kernelUnsetFlag(fromColor, toColor, flags); - break; } - case 4: { // Set palette intensity - switch (argc) { - case 4: - case 5: { - uint16 fromColor = CLIP(argv[1].toUint16(), 1, 255); - uint16 toColor = CLIP(argv[2].toUint16(), 1, 255); - uint16 intensity = argv[3].toUint16(); - bool setPalette = (argc < 5) ? true : (argv[4].isNull()) ? true : false; - - g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette); - break; - } - default: - warning("kPalette(4) called with %d parameters", argc); - } - break; + return s->r_acc; +} + +reg_t kPaletteSetIntensity(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 fromColor = CLIP(argv[0].toUint16(), 1, 255); + uint16 toColor = CLIP(argv[1].toUint16(), 1, 255); + uint16 intensity = argv[2].toUint16(); + bool setPalette = (argc < 4) ? true : (argv[3].isNull()) ? true : false; + + g_sci->_gfxPalette->kernelSetIntensity(fromColor, toColor, intensity, setPalette); } - case 5: { // Find closest color - uint16 r = argv[1].toUint16(); - uint16 g = argv[2].toUint16(); - uint16 b = argv[3].toUint16(); + return s->r_acc; +} +reg_t kPaletteFindColor(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + uint16 r = argv[0].toUint16(); + uint16 g = argv[1].toUint16(); + uint16 b = argv[2].toUint16(); return make_reg(0, g_sci->_gfxPalette->kernelFindColor(r, g, b)); } - case 6: { // Animate + return NULL_REG; +} + +reg_t kPaletteAnimate(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { int16 argNr; bool paletteChanged = false; - for (argNr = 1; argNr < argc; argNr += 3) { + for (argNr = 0; argNr < argc; argNr += 3) { uint16 fromColor = argv[argNr].toUint16(); uint16 toColor = argv[argNr + 1].toUint16(); int16 speed = argv[argNr + 2].toSint16(); @@ -623,20 +629,21 @@ reg_t kPalette(EngineState *s, int argc, reg_t *argv) { } if (paletteChanged) g_sci->_gfxPalette->kernelAnimateSet(); - break; } - case 7: { // Save palette to heap + return s->r_acc; +} + +reg_t kPaletteSave(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { warning("kPalette(7), save palette to heap STUB"); - break; - } - case 8: { // Restore palette from heap - warning("kPalette(8), set stored palette STUB"); - break; - } - default: - error("kPalette(%d), not implemented", argv[0].toUint16()); } + return NULL_REG; +} +reg_t kPaletteRestore(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isVGA()) { + warning("kPalette(8), restore palette from heap STUB"); + } return s->r_acc; } @@ -674,19 +681,19 @@ reg_t kPalVaryDeinit(EngineState *s, int argc, reg_t *argv) { } reg_t kPalVaryChangeTarget(EngineState *s, int argc, reg_t *argv) { - GuiResourceId paletteId = argv[1].toUint16(); + GuiResourceId paletteId = argv[0].toUint16(); int16 currentStep = g_sci->_gfxPalette->kernelPalVaryChangeTarget(paletteId); return make_reg(0, currentStep); } reg_t kPalVaryChangeTicks(EngineState *s, int argc, reg_t *argv) { - uint16 ticks = argv[1].toUint16(); + uint16 ticks = argv[0].toUint16(); g_sci->_gfxPalette->kernelPalVaryChangeTicks(ticks); return NULL_REG; } reg_t kPalVaryPauseResume(EngineState *s, int argc, reg_t *argv) { - bool pauseState = !argv[1].isNull(); + bool pauseState = !argv[0].isNull(); g_sci->_gfxPalette->kernelPalVaryPause(pauseState); return NULL_REG; } @@ -697,7 +704,7 @@ reg_t kPalVaryUnknown(EngineState *s, int argc, reg_t *argv) { } reg_t kAssertPalette(EngineState *s, int argc, reg_t *argv) { - GuiResourceId paletteId = argv[1].toUint16(); + GuiResourceId paletteId = argv[0].toUint16(); g_sci->_gfxPalette->kernelAssertPalette(paletteId); return s->r_acc; diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 9c64c21743..b85281e9c4 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -482,8 +482,9 @@ void GfxPalette::kernelAnimateSet() { void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { // Sometimes invalid viewIds are asked for, ignore those (e.g. qfg1vga) - if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId))) - return; + //if (!_resMan->testResource(ResourceId(kResourceTypeView, resourceId))) + // return; + // maybe we took the wrong parameter before, if this causes invalid view again, enable to commented out code again GfxView *view = g_sci->_gfxCache->getView(resourceId); Palette *viewPalette = view->getPalette(); -- cgit v1.2.3 From ce6a73adf532045c60f4c4072228b7bfdff87385 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 13:19:20 +0000 Subject: SCI: updated debug output from kDoSound svn-id: r50781 --- engines/sci/sound/soundcmd.cpp | 44 +++++++++++++++++++++--------------------- 1 file changed, 22 insertions(+), 22 deletions(-) (limited to 'engines') diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 5ac8c6b270..11b0215a32 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -73,7 +73,7 @@ void SoundCommandParser::processInitSound(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) newSound->volume = CLIP(readSelectorValue(_segMan, obj, SELECTOR(vol)), 0, MUSIC_VOLUME_MAX); - debugC(2, kDebugLevelSound, "cmdInitSound, number %d, loop %d, prio %d, vol %d", resourceId, + debugC(2, kDebugLevelSound, "kDoSound(init): number %d, loop %d, prio %d, vol %d", resourceId, newSound->loop, newSound->priority, newSound->volume); // In SCI1.1 games, sound effects are started from here. If we can find @@ -112,7 +112,7 @@ reg_t SoundCommandParser::kDoSoundPlay(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processPlaySound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdPlaySound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(play): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -142,7 +142,7 @@ void SoundCommandParser::processPlaySound(reg_t obj) { if (_soundVersion >= SCI_VERSION_1_EARLY) musicSlot->volume = readSelectorValue(_segMan, obj, SELECTOR(vol)); - debugC(2, kDebugLevelSound, "cmdPlaySound, number %d, loop %d, prio %d, vol %d", resourceId, + debugC(2, kDebugLevelSound, "kDoSound(play): number %d, loop %d, prio %d, vol %d", resourceId, musicSlot->loop, musicSlot->priority, musicSlot->volume); _music->soundPlay(musicSlot); @@ -161,7 +161,7 @@ reg_t SoundCommandParser::kDoSoundDispose(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processDisposeSound(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdDisposeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(dispose): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -183,7 +183,7 @@ reg_t SoundCommandParser::kDoSoundStop(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processStopSound(reg_t obj, bool sampleFinishedPlaying) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdStopSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(stop): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -229,7 +229,7 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { } return make_reg(0, 0); default: - error("kDoSoundPause: parameter 0 is invalid for sound-sci0"); + error("kDoSound(pause): parameter 0 is invalid for sound-sci0"); } } @@ -240,7 +240,7 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { } else { // pause a playlist slot MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdPauseSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(pause): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -255,7 +255,7 @@ reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdResumeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(resume):: Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -274,7 +274,7 @@ reg_t SoundCommandParser::kDoSoundMasterVolume(int argc, reg_t *argv, reg_t acc) acc = make_reg(0, _music->soundGetMasterVolume()); if (argc > 0) { - debugC(2, kDebugLevelSound, "cmdMasterVolume: %d", argv[0].toSint16()); + debugC(2, kDebugLevelSound, "kDoSound(masterVolume): %d", argv[0].toSint16()); int vol = CLIP(argv[0].toSint16(), 0, kMaxSciVolume); vol = vol * Audio::Mixer::kMaxMixerVolume / kMaxSciVolume; ConfMan.setInt("music_volume", vol); @@ -289,7 +289,7 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdFadeSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(fade): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -297,7 +297,7 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { // If sound is not playing currently, set signal directly if (musicSlot->status != kSoundPlaying) { - debugC(2, kDebugLevelSound, "cmdFadeSound: fading requested, but sound is currently not playing"); + debugC(2, kDebugLevelSound, "kDoSound(fade): fading requested, but sound is currently not playing"); writeSelectorValue(_segMan, obj, SELECTOR(signal), SIGNAL_OFFSET); return acc; } @@ -322,10 +322,10 @@ reg_t SoundCommandParser::kDoSoundFade(int argc, reg_t *argv, reg_t acc) { break; default: - error("cmdFadeSound: unsupported argc %d", argc); + error("kDoSound(fade): unsupported argc %d", argc); } - debugC(2, kDebugLevelSound, "cmdFadeSound: to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); + debugC(2, kDebugLevelSound, "kDoSound(fade): to %d, step %d, ticker %d", musicSlot->fadeTo, musicSlot->fadeStep, musicSlot->fadeTickerStep); return acc; } @@ -338,7 +338,7 @@ reg_t SoundCommandParser::kDoSoundUpdate(int argc, reg_t *argv, reg_t acc) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdUpdateSound: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(update): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -360,7 +360,7 @@ reg_t SoundCommandParser::kDoSoundUpdateCues(int argc, reg_t *argv, reg_t acc) { void SoundCommandParser::processUpdateCues(reg_t obj) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdUpdateCues: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(updateCues): Slot not found (%04x:%04x)", PRINT_REG(obj)); return; } @@ -453,7 +453,7 @@ reg_t SoundCommandParser::kDoSoundSendMidi(int argc, reg_t *argv, reg_t acc) { // TODO: maybe it's possible to call this with obj == 0:0 and send directly?! // if so, allow it //_music->sendMidiCommand(_midiCommand); - warning("cmdSendMidi: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(sendMidi): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } _music->sendMidiCommand(musicSlot, midiCommand); @@ -470,7 +470,7 @@ reg_t SoundCommandParser::kDoSoundSetHold(int argc, reg_t *argv, reg_t acc) { MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdSetSoundHold: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(setHold): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -516,7 +516,7 @@ reg_t SoundCommandParser::kDoSoundSetVolume(int argc, reg_t *argv, reg_t acc) { return acc; } - debugC(2, kDebugLevelSound, "cmdSetSoundVolume: %d", value); + debugC(2, kDebugLevelSound, "kDoSound(setVolume): %d", value); value = CLIP(value, 0, MUSIC_VOLUME_MAX); @@ -534,7 +534,7 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) MusicEntry *musicSlot = _music->getSlot(obj); if (!musicSlot) { - warning("cmdSetSoundPriority: Slot not found (%04x:%04x)", PRINT_REG(obj)); + warning("kDoSound(setPriority): Slot not found (%04x:%04x)", PRINT_REG(obj)); return acc; } @@ -544,7 +544,7 @@ reg_t SoundCommandParser::kDoSoundSetPriority(int argc, reg_t *argv, reg_t acc) if (song->data[0] == 0xf0) _music->soundSetPriority(musicSlot, song->data[1]); else - warning("cmdSetSoundPriority: Attempt to unset song priority when there is no built-in value"); + warning("kDoSound(setPriority): Attempt to unset song priority when there is no built-in value"); //pSnd->prio=0;field_15B=0 writeSelectorValue(_segMan, obj, SELECTOR(flags), readSelectorValue(_segMan, obj, SELECTOR(flags)) & 0xFD); @@ -570,7 +570,7 @@ reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { // request to loop the sound, so in this case, don't throw any warning, // otherwise do, because the sound won't be looped. if (value == -1) { - warning("cmdSetSoundLoop: Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); + warning("kDoSound(setLoop): Slot not found (%04x:%04x) and the song was requested to be looped", PRINT_REG(obj)); } else { // Doesn't really matter } @@ -588,7 +588,7 @@ reg_t SoundCommandParser::kDoSoundSetLoop(int argc, reg_t *argv, reg_t acc) { reg_t SoundCommandParser::kDoSoundSuspend(int argc, reg_t *argv, reg_t acc) { // TODO - warning("STUB: cmdSuspendSound"); + warning("kDoSound(suspend): STUB"); return acc; } -- cgit v1.2.3 From e807983e8fd742334348f99fcdb72d351b18d2e6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 14:00:43 +0000 Subject: SCI: removed unused debug flags, changed fileio debug prints to only happen on debugflag "file" svn-id: r50782 --- engines/sci/engine/kfile.cpp | 47 +++++++++++++++++++++----------------------- engines/sci/sci.cpp | 3 --- engines/sci/sci.h | 29 ++++++++++++--------------- 3 files changed, 35 insertions(+), 44 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index f371e8a799..69b80ce7ce 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -135,17 +135,17 @@ void file_open(EngineState *s, const char *filename, int mode) { } if (!inFile) - warning("file_open(_K_FILE_MODE_OPEN_OR_FAIL) failed to open file '%s'", englishName.c_str()); + warning(" -> file_open(_K_FILE_MODE_OPEN_OR_FAIL): failed to open file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_CREATE) { // Create the file, destroying any content it might have had outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) - warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str()); + warning(" -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); } else if (mode == _K_FILE_MODE_OPEN_OR_CREATE) { // Try to open file, create it if it doesn't exist outFile = saveFileMan->openForSaving(wrappedName); if (!outFile) - warning("file_open(_K_FILE_MODE_CREATE) failed to create file '%s'", englishName.c_str()); + warning(" -> file_open(_K_FILE_MODE_CREATE): failed to create file '%s'", englishName.c_str()); // QfG1 opens the character export file with _K_FILE_MODE_CREATE first, // closes it immediately and opens it again with this here. Perhaps // other games use this for read access as well. I guess changing this @@ -156,7 +156,7 @@ void file_open(EngineState *s, const char *filename, int mode) { } if (!inFile && !outFile) { // Failed - debug(3, "file_open() failed"); + debugC(2, kDebugLevelFile, " -> file_open() failed"); s->r_acc = SIGNAL_REG; return; } @@ -177,14 +177,14 @@ void file_open(EngineState *s, const char *filename, int mode) { s->r_acc = make_reg(0, handle); - debug(3, " -> opened file '%s' with handle %d", englishName.c_str(), handle); + debugC(2, kDebugLevelFile, " -> opened file '%s' with handle %d", englishName.c_str(), handle); } reg_t kFOpen(EngineState *s, int argc, reg_t *argv) { Common::String name = s->_segMan->getString(argv[0]); int mode = argv[1].toUint16(); - debug(3, "kFOpen(%s,0x%x)", name.c_str(), mode); + debugC(2, kDebugLevelFile, "kFOpen(%s,0x%x)", name.c_str(), mode); file_open(s, name.c_str(), mode); return s->r_acc; } @@ -204,7 +204,7 @@ static FileHandle *getFileFromHandle(EngineState *s, uint handle) { } reg_t kFClose(EngineState *s, int argc, reg_t *argv) { - debug(3, "kFClose(%d)", argv[0].toUint16()); + debugC(2, kDebugLevelFile, "kFClose(%d)", argv[0].toUint16()); if (argv[0] != SIGNAL_REG) { FileHandle *f = getFileFromHandle(s, argv[0].toUint16()); if (f) @@ -225,8 +225,6 @@ reg_t kFPuts(EngineState *s, int argc, reg_t *argv) { } static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { - debugC(2, kDebugLevelFile, "FGets'ing %d bytes from handle %d", maxsize, handle); - FileHandle *f = getFileFromHandle(s, handle); if (!f) return; @@ -248,7 +246,7 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { *dest = f->_in->readByte(); } - debugC(2, kDebugLevelFile, "FGets'ed \"%s\"", dest); + debugC(2, kDebugLevelFile, " -> FGets'ed \"%s\"", dest); } static bool _savegame_index_struct_compare(const SavegameDesc &l, const SavegameDesc &r) { @@ -316,7 +314,7 @@ reg_t kFGets(EngineState *s, int argc, reg_t *argv) { char *buf = new char[maxsize]; int handle = argv[2].toUint16(); - debug(3, "kFGets(%d,%d)", handle, maxsize); + debugC(2, kDebugLevelFile, "kFGets(%d, %d)", handle, maxsize); fgets_wrapper(s, buf, maxsize, handle); s->_segMan->memcpy(argv[0], (const byte*)buf, maxsize); return argv[0]; @@ -331,7 +329,7 @@ reg_t kGetCWD(EngineState *s, int argc, reg_t *argv) { // TODO/FIXME: Is "/" a good value? Maybe "" or "." or "C:\" are better? s->_segMan->strcpy(argv[0], "/"); - debug(3, "kGetCWD() -> %s", "/"); + debugC(2, kDebugLevelFile, "kGetCWD() -> %s", "/"); return argv[0]; } @@ -700,12 +698,12 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { warning("Attempted to open a file with an empty filename"); return SIGNAL_REG; } + debugC(2, kDebugLevelFile, "kFileIO(open): %s, 0x%x", name.c_str(), mode); file_open(s, name.c_str(), mode); - debug(3, "K_FILEIO_OPEN(%s,0x%x)", name.c_str(), mode); break; } case K_FILEIO_CLOSE : { - debug(3, "K_FILEIO_CLOSE(%d)", argv[1].toUint16()); + debugC(2, kDebugLevelFile, "kFileIO(close): %d", argv[1].toUint16()); FileHandle *f = getFileFromHandle(s, argv[1].toUint16()); if (f) @@ -716,8 +714,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int size = argv[3].toUint16(); char *buf = new char[size]; - debug(3, "K_FILEIO_READ_RAW(%d,%d)", handle, size); - + debugC(2, kDebugLevelFile, "kFileIO(readRaw): %d, %d", handle, size); FileHandle *f = getFileFromHandle(s, handle); if (f) { @@ -733,7 +730,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int size = argv[3].toUint16(); char *buf = new char[size]; s->_segMan->memcpy((byte*)buf, argv[2], size); - debug(3, "K_FILEIO_WRITE_RAW(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(writeRaw): %d, %d", handle, size); FileHandle *f = getFileFromHandle(s, handle); if (f) @@ -769,7 +766,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { saveFileMan->removeSavefile(wrappedName); } - debug(3, "K_FILEIO_UNLINK(%s)", name.c_str()); + debugC(2, kDebugLevelFile, "kFileIO(unlink): %s", name.c_str()); // TODO/FIXME: Should we return something (like, a bool indicating // whether deleting the save succeeded or failed)? @@ -779,7 +776,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int size = argv[2].toUint16(); char *buf = new char[size]; int handle = argv[3].toUint16(); - debug(3, "K_FILEIO_READ_STRING(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(readString): %d, %d", handle, size); fgets_wrapper(s, buf, size, handle); s->_segMan->memcpy(argv[1], (const byte*)buf, size); @@ -790,7 +787,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int size = argv[3].toUint16(); Common::String str = s->_segMan->getString(argv[2]); - debug(3, "K_FILEIO_WRITE_STRING(%d,%d)", handle, size); + debugC(2, kDebugLevelFile, "kFileIO(writeString): %d, %d", handle, size); // CHECKME: Is the size parameter used at all? // In the LSL5 password protection it is zero, and we should @@ -806,7 +803,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { int handle = argv[1].toUint16(); int offset = argv[2].toUint16(); int whence = argv[3].toUint16(); - debug(3, "K_FILEIO_SEEK(%d,%d,%d)", handle, offset, whence); + debugC(2, kDebugLevelFile, "kFileIO(seek): %d, %d, %d", handle, offset, whence); FileHandle *f = getFileFromHandle(s, handle); if (f) @@ -817,7 +814,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { Common::String mask = s->_segMan->getString(argv[1]); reg_t buf = argv[2]; int attr = argv[3].toUint16(); // We won't use this, Win32 might, though... - debug(3, "K_FILEIO_FIND_FIRST(%s,0x%x)", mask.c_str(), attr); + debugC(2, kDebugLevelFile, "kFileIO(findFirst): %s, 0x%x", mask.c_str(), attr); // We remove ".*". mask will get prefixed, so we will return all additional files for that gameid if (mask == "*.*") @@ -835,7 +832,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { break; } case K_FILEIO_FIND_NEXT : { - debug(3, "K_FILEIO_FIND_NEXT()"); + debugC(2, kDebugLevelFile, "kFileIO(findNext)"); s->r_acc = s->_dirseeker.nextFile(s->_segMan); break; } @@ -877,7 +874,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { exists = true; } - debug(3, "K_FILEIO_FILE_EXISTS(%s) -> %d", name.c_str(), exists); + debugC(2, kDebugLevelFile, "kFileIO(fileExists) %s -> %d", name.c_str(), exists); return make_reg(0, exists); } case K_FILEIO_RENAME: { @@ -925,7 +922,7 @@ reg_t kFileIO(EngineState *s, int argc, reg_t *argv) { break; #endif default: - error("Unknown FileIO() sub-command: %d", func_nr); + error("kFileIO(): unknown sub-command: %d", func_nr); } return s->r_acc; diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index 91eeac3a21..ec8f697123 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -97,10 +97,8 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam DebugMan.addDebugChannel(kDebugLevelFuncCheck, "Func", "Function parameter debugging"); DebugMan.addDebugChannel(kDebugLevelBresen, "Bresenham", "Bresenham algorithms debugging"); DebugMan.addDebugChannel(kDebugLevelSound, "Sound", "Sound debugging"); - DebugMan.addDebugChannel(kDebugLevelGfxDriver, "Gfxdriver", "Gfx driver debugging"); DebugMan.addDebugChannel(kDebugLevelBaseSetter, "Base", "Base Setter debugging"); DebugMan.addDebugChannel(kDebugLevelParser, "Parser", "Parser debugging"); - DebugMan.addDebugChannel(kDebugLevelMenu, "Menu", "Menu handling debugging"); DebugMan.addDebugChannel(kDebugLevelSaid, "Said", "Said specs debugging"); DebugMan.addDebugChannel(kDebugLevelFile, "File", "File I/O debugging"); DebugMan.addDebugChannel(kDebugLevelTime, "Time", "Time debugging"); @@ -110,7 +108,6 @@ SciEngine::SciEngine(OSystem *syst, const ADGameDescription *desc, SciGameId gam DebugMan.addDebugChannel(kDebugLevelVM, "VM", "VM debugging"); DebugMan.addDebugChannel(kDebugLevelScripts, "Scripts", "Notifies when scripts are unloaded"); DebugMan.addDebugChannel(kDebugLevelGC, "GC", "Garbage Collector debugging"); - DebugMan.addDebugChannel(kDebugLevelSci0Pic, "Sci0Pic", "SCI0 pic drawing debugging"); DebugMan.addDebugChannel(kDebugLevelResMan, "ResMan", "Resource manager debugging"); DebugMan.addDebugChannel(kDebugLevelOnStartup, "OnStartup", "Enter debugger at start of game"); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index c09342f749..8f7205ea7a 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -84,22 +84,19 @@ enum kDebugLevels { kDebugLevelFuncCheck = 1 << 5, kDebugLevelBresen = 1 << 6, kDebugLevelSound = 1 << 7, - kDebugLevelGfxDriver = 1 << 8, - kDebugLevelBaseSetter = 1 << 9, - kDebugLevelParser = 1 << 10, - kDebugLevelMenu = 1 << 11, - kDebugLevelSaid = 1 << 12, - kDebugLevelFile = 1 << 13, - kDebugLevelTime = 1 << 14, - kDebugLevelRoom = 1 << 15, - kDebugLevelAvoidPath = 1 << 16, - kDebugLevelDclInflate = 1 << 17, - kDebugLevelVM = 1 << 18, - kDebugLevelScripts = 1 << 19, - kDebugLevelGC = 1 << 20, - kDebugLevelSci0Pic = 1 << 21, - kDebugLevelResMan = 1 << 22, - kDebugLevelOnStartup = 1 << 23 + kDebugLevelBaseSetter = 1 << 8, + kDebugLevelParser = 1 << 9, + kDebugLevelSaid = 1 << 10, + kDebugLevelFile = 1 << 11, + kDebugLevelTime = 1 << 12, + kDebugLevelRoom = 1 << 13, + kDebugLevelAvoidPath = 1 << 14, + kDebugLevelDclInflate = 1 << 15, + kDebugLevelVM = 1 << 16, + kDebugLevelScripts = 1 << 17, + kDebugLevelGC = 1 << 18, + kDebugLevelResMan = 1 << 19, + kDebugLevelOnStartup = 1 << 20 }; enum SciGameId { -- cgit v1.2.3 From 28d07c7e0a8e2e84aa5bba45105dc4091476f4ee Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 16:22:08 +0000 Subject: SCI: calculate widths for menu after switching to menuport, i guess this was the reason why we sometimes had issues drawing parts of the menu (random issue) svn-id: r50784 --- engines/sci/graphics/menu.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/graphics/menu.cpp b/engines/sci/graphics/menu.cpp index f959ffb3a5..bfe58e03d5 100644 --- a/engines/sci/graphics/menu.cpp +++ b/engines/sci/graphics/menu.cpp @@ -704,8 +704,8 @@ GuiMenuItemEntry *GfxMenu::interactiveWithKeyboard() { // selecting first item of first menu every time. Also sierra sci didn't // allow mouse interaction, when menu was activated via keyboard. - calculateMenuAndItemWidth(); _oldPort = _ports->setPort(_ports->_menuPort); + calculateMenuAndItemWidth(); _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL); _ports->penColor(0); @@ -827,8 +827,8 @@ GuiMenuItemEntry *GfxMenu::interactiveWithMouse() { bool firstMenuChange = true; GuiMenuItemEntry *curItemEntry = NULL; - calculateMenuAndItemWidth(); _oldPort = _ports->setPort(_ports->_menuPort); + calculateMenuAndItemWidth(); _barSaveHandle = _paint16->bitsSave(_ports->_menuRect, GFX_SCREEN_MASK_VISUAL); _ports->penColor(0); -- cgit v1.2.3 From b7906e7feb33cf1b31433f9962bb02b393e1943e Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 17:08:42 +0000 Subject: SCI: allow invalid handles in kDisplay calls, fixes pq3 intro signature mismatch svn-id: r50785 --- engines/sci/engine/kernel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2069b8ee80..2fb1452fa2 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -370,7 +370,8 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(CosDiv), SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(DeleteKey), SIG_EVERYWHERE, "l.", NULL, NULL }, { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop - { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir]*)", NULL, NULL }, // subop + { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, NULL }, + // ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, -- cgit v1.2.3 From 790e9b0351a043d2d5e4c048a081f5f6ab24c9a9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 18:21:09 +0000 Subject: SCI: added signatures for kGraph, removed isDummy boolean from KernelFunction svn-id: r50786 --- engines/sci/engine/kernel.cpp | 67 +++++++++++++-- engines/sci/engine/kernel.h | 13 ++- engines/sci/engine/kgraphics.cpp | 178 +++++++++++++++++---------------------- engines/sci/engine/vm.cpp | 107 ++++++++++------------- 4 files changed, 197 insertions(+), 168 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 2fb1452fa2..0fd21671a0 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -199,6 +199,41 @@ static const char *s_defaultKernelNames[] = { /*0x88*/ "Dummy" // DbugStr }; +reg_t kStub(EngineState *s, int argc, reg_t *argv) { + Kernel *kernel = g_sci->getKernel(); + int kernelCallNr = -1; + + Common::List::iterator callIterator = s->_executionStack.end(); + if (callIterator != s->_executionStack.begin()) { + callIterator--; + ExecStack lastCall = *callIterator; + kernelCallNr = lastCall.debugSelector; + } + + Common::String warningMsg = "Dummy function k" + kernel->getKernelName(kernelCallNr) + + Common::String::printf("[%x]", kernelCallNr) + + " invoked. Params: " + + Common::String::printf("%d", argc) + " ("; + + for (int i = 0; i < argc; i++) { + warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); + warningMsg += (i == argc - 1 ? ")" : ", "); + } + + warning("%s", warningMsg.c_str()); + return s->r_acc; +} + +reg_t kStubNull(EngineState *s, int argc, reg_t *argv) { + kStub(s, argc, argv); + return NULL_REG; +} + +reg_t kDummy(EngineState *s, int argc, reg_t *argv) { + kStub(s, argc, argv); + error("Kernel function was called, which was considered to be unused - see log for details"); +} + // [io] -> either integer or object // (io) -> optionally integer AND an object // (i) -> optional integer @@ -308,6 +343,26 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +static const SciKernelMapSubEntry kGraph_subops[] = { + { SIG_SCI32, 1, MAP_CALL(StubNull), "", NULL }, // called by gk1 sci32 right at the start + { SIG_SCIALL, 2, MAP_CALL(GraphGetColorCount), "", NULL }, + // 3 - set palette via resource + { SIG_SCIALL, 4, MAP_CALL(GraphDrawLine), "iiiii(i)(i)", NULL }, + // 5 - nop + // 6 - draw pattern + { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", NULL }, + { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", NULL }, + // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same + { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, + { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL }, + { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", NULL }, + { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r)", NULL }, + { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL }, + { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL }, + { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires + SCI_SUBOPENTRY_TERMINATOR +}; + static const SciKernelMapSubEntry kPalVary_subops[] = { { SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL }, { SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL }, @@ -372,6 +427,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(DeviceInfo), SIG_EVERYWHERE, "i(r)(r)(i)", NULL, NULL }, // subop { MAP_CALL(Display), SIG_EVERYWHERE, "[ir]([ir!]*)", NULL, NULL }, // ^ we allow invalid references here, because kDisplay gets called with those in e.g. pq3 during intro + // restoreBits() checks and skips invalid handles, so that's fine. Sierra SCI behaved the same { MAP_CALL(DirLoop), SIG_EVERYWHERE, "oi", NULL, NULL }, { MAP_CALL(DisposeClone), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(DisposeList), SIG_EVERYWHERE, "l", NULL, NULL }, @@ -417,9 +473,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", NULL, NULL }, // subop - // ^^ we allow invalid references here, because kGraph(restoreBox) gets called with old non-existant handles often - // this should get limited to this call only as soon as subop signatures are available + { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", kGraph_subops, NULL }, { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, @@ -1032,7 +1086,6 @@ void Kernel::mapFunctions() { _kernelFuncs[id].function = NULL; _kernelFuncs[id].signature = NULL; _kernelFuncs[id].name = NULL; - _kernelFuncs[id].isDummy = true; _kernelFuncs[id].workarounds = NULL; _kernelFuncs[id].subFunctions = NULL; _kernelFuncs[id].subFunctionCount = 0; @@ -1044,8 +1097,10 @@ void Kernel::mapFunctions() { } // Don't map dummy functions - they will never be called - if (kernelName == "Dummy") + if (kernelName == "Dummy") { + _kernelFuncs[id].function = kDummy; continue; + } // If the name is known, look it up in s_kernelMap. This table // maps kernel func names to actual function (pointers). @@ -1068,7 +1123,6 @@ void Kernel::mapFunctions() { _kernelFuncs[id].name = kernelMap->name; _kernelFuncs[id].signature = parseKernelSignature(kernelMap->name, kernelMap->signature); _kernelFuncs[id].workarounds = kernelMap->workarounds; - _kernelFuncs[id].isDummy = false; if (kernelMap->subFunctions) { // Get version for subfunction identification SciVersion mySubVersion = (SciVersion)kernelMap->function(NULL, 0, NULL).offset; @@ -1129,6 +1183,7 @@ void Kernel::mapFunctions() { error("k%s[%x]: not found for this version/platform", kernelName.c_str(), id); // No match but a name was given -> stub warning("k%s[%x]: unmapped", kernelName.c_str(), id); + _kernelFuncs[id].function = kStub; } } // for all functions requesting to be mapped diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index 5815fec53b..a054aa2b1c 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -141,7 +141,6 @@ struct KernelSubFunction { }; struct KernelFunction { - bool isDummy; KernelFunctionCall *function; const char *name; uint16 *signature; @@ -491,6 +490,18 @@ reg_t kDoSoundSetVolume(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundSetPriority(EngineState *s, int argc, reg_t *argv); reg_t kDoSoundSetLoop(EngineState *s, int argc, reg_t *argv); +reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv); +reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv); +reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv); +reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv); +reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv); +reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv); +reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv); + reg_t kPalVaryInit(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryReverse(EngineState *s, int argc, reg_t *argv); reg_t kPalVaryGetCurrentStep(EngineState *s, int argc, reg_t *argv); diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 9714374ade..0e7930275a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -207,128 +207,108 @@ reg_t kPicNotValid(EngineState *s, int argc, reg_t *argv) { return make_reg(0, g_sci->_gfxScreen->kernelPicNotValid(newPicNotValid)); } -Common::Rect kGraphCreateRect(int16 x, int16 y, int16 x1, int16 y1) { +static Common::Rect getGraphRect(reg_t *argv) { + int16 x = argv[1].toSint16(); + int16 y = argv[0].toSint16(); + int16 x1 = argv[3].toSint16(); + int16 y1 = argv[2].toSint16(); if (x > x1) SWAP(x, x1); if (y > y1) SWAP(y, y1); return Common::Rect(x, y, x1, y1); } -// Graph subfunctions -enum { - K_GRAPH_GET_COLORS_NR = 2, - // 3 - SET PALETTE VIA RESOURCE - K_GRAPH_DRAW_LINE = 4, - // 5 - NOP - // 6 - DRAW PATTERN - K_GRAPH_SAVE_BOX = 7, - K_GRAPH_RESTORE_BOX = 8, - K_GRAPH_FILL_BOX_BACKGROUND = 9, - K_GRAPH_FILL_BOX_FOREGROUND = 10, - K_GRAPH_FILL_BOX_ANY = 11, - K_GRAPH_UPDATE_BOX = 12, - K_GRAPH_REDRAW_BOX = 13, - K_GRAPH_ADJUST_PRIORITY = 14, - K_GRAPH_SAVE_UPSCALEDHIRES_BOX = 15 // KQ6CD Windows version -}; +static Common::Point getGraphPoint(reg_t *argv) { + int16 x = argv[1].toSint16(); + int16 y = argv[0].toSint16(); + return Common::Point(x, y); +} reg_t kGraph(EngineState *s, int argc, reg_t *argv) { - int16 x = 0, y = 0, x1 = 0, y1 = 0; - uint16 screenMask; - int16 priority, control, color, colorMask; - Common::Rect rect; - - if (argc >= 5) { - x = argv[2].toSint16(); - y = argv[1].toSint16(); - x1 = argv[4].toSint16(); - y1 = argv[3].toSint16(); - } - - switch (argv[0].toSint16()) { - case 1: - // TODO: Happens in GK1CD, right when it starts - warning("Unsupported kGraph() operation %04x", argv[0].toSint16()); - // Returns an integer - return SIGNAL_REG; - - case K_GRAPH_GET_COLORS_NR: - if (g_sci->getResMan()->isAmiga32color()) - return make_reg(0, 32); - return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256); - - case K_GRAPH_DRAW_LINE: - priority = (argc > 6) ? argv[6].toSint16() : -1; - control = (argc > 7) ? argv[7].toSint16() : -1; - color = argv[5].toSint16(); - - // TODO: Find out why we get >15 for color in EGA - if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color()) - color &= 0x0F; + if (!s) + return make_reg(0, getSciVersion()); + error("not supposed to call this"); +} - g_sci->_gfxPaint16->kernelGraphDrawLine(Common::Point(x, y), Common::Point(x1, y1), color, priority, control); - break; +reg_t kGraphGetColorCount(EngineState *s, int argc, reg_t *argv) { + if (g_sci->getResMan()->isAmiga32color()) + return make_reg(0, 32); + return make_reg(0, !g_sci->getResMan()->isVGA() ? 16 : 256); +} - case K_GRAPH_SAVE_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - screenMask = (argc > 5) ? argv[5].toUint16() : 0; - return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask); +reg_t kGraphDrawLine(EngineState *s, int argc, reg_t *argv) { + int16 color = argv[4].toSint16(); + int16 priority = (argc > 5) ? argv[5].toSint16() : -1; + int16 control = (argc > 6) ? argv[6].toSint16() : -1; - case K_GRAPH_RESTORE_BOX: - // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX - g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[1]); - break; + // TODO: Find out why we get >15 for color in EGA + if (!g_sci->getResMan()->isVGA() && !g_sci->getResMan()->isAmiga32color()) + color &= 0x0F; - case K_GRAPH_FILL_BOX_BACKGROUND: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect); - break; + g_sci->_gfxPaint16->kernelGraphDrawLine(getGraphPoint(argv), getGraphPoint(argv + 2), color, priority, control); + return s->r_acc; +} - case K_GRAPH_FILL_BOX_FOREGROUND: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect); - break; +reg_t kGraphSaveBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + uint16 screenMask = (argc > 4) ? argv[4].toUint16() : 0; + return g_sci->_gfxPaint16->kernelGraphSaveBox(rect, screenMask); +} - case K_GRAPH_FILL_BOX_ANY: - priority = (argc > 7) ? argv[7].toSint16() : -1; - control = (argc > 8) ? argv[8].toSint16() : -1; - color = argv[6].toSint16(); - colorMask = argv[5].toUint16(); +reg_t kGraphRestoreBox(EngineState *s, int argc, reg_t *argv) { + // This may be called with a memoryhandle from SAVE_BOX or SAVE_UPSCALEDHIRES_BOX + g_sci->_gfxPaint16->kernelGraphRestoreBox(argv[0]); + return s->r_acc; +} - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control); - break; +reg_t kGraphFillBoxBackground(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphFillBoxBackground(rect); + return s->r_acc; +} - case K_GRAPH_UPDATE_BOX: { - rect = kGraphCreateRect(x, y, x1, y1); - bool hiresMode = (argc > 6) ? true : false; - // arg5 is the map (1 for visual, etc.) - // argc == 7 on upscaled hires - g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode); - break; - } +reg_t kGraphFillBoxForeground(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphFillBoxForeground(rect); + return s->r_acc; +} - case K_GRAPH_REDRAW_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - g_sci->_gfxPaint16->kernelGraphRedrawBox(rect); - break; +reg_t kGraphFillBoxAny(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + int16 colorMask = argv[4].toUint16(); + int16 color = argv[5].toSint16(); + int16 priority = (argc > 6) ? argv[6].toSint16() : -1; + int16 control = (argc > 7) ? argv[7].toSint16() : -1; - case K_GRAPH_ADJUST_PRIORITY: - // Seems to be only implemented for SCI0/SCI01 games - debugC(2, kDebugLevelGraphics, "adjust_priority(%d, %d)", argv[1].toUint16(), argv[2].toUint16()); - g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[1].toUint16(), argv[2].toUint16()); - break; + g_sci->_gfxPaint16->kernelGraphFillBox(rect, colorMask, color, priority, control); + return s->r_acc; +} - case K_GRAPH_SAVE_UPSCALEDHIRES_BOX: - rect = kGraphCreateRect(x, y, x1, y1); - return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect); +reg_t kGraphUpdateBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + // argv[4] is the map (1 for visual, etc.) + // argc == 6 on upscaled hires + bool hiresMode = (argc > 5) ? true : false; + g_sci->_gfxPaint16->kernelGraphUpdateBox(rect, hiresMode); + return s->r_acc; +} - default: - error("Unsupported kGraph() operation %04x", argv[0].toSint16()); - } +reg_t kGraphRedrawBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + g_sci->_gfxPaint16->kernelGraphRedrawBox(rect); + return s->r_acc; +} +// Seems to be only implemented for SCI0/SCI01 games +reg_t kGraphAdjustPriority(EngineState *s, int argc, reg_t *argv) { + g_sci->_gfxPorts->kernelGraphAdjustPriority(argv[0].toUint16(), argv[1].toUint16()); return s->r_acc; } +reg_t kGraphSaveUpscaledHiresBox(EngineState *s, int argc, reg_t *argv) { + Common::Rect rect = getGraphRect(argv); + return g_sci->_gfxPaint16->kernelGraphSaveUpscaledHiresBox(rect); +} + reg_t kTextSize(EngineState *s, int argc, reg_t *argv) { int16 textWidth, textHeight; Common::String text = s->_segMan->getString(argv[1]); diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index a354491a83..cbfaf5575f 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -800,50 +800,51 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { return; } - if (!kernelCall.isDummy) { - // Add stack frame to indicate we're executing a callk. - // This is useful in debugger backtraces if this - // kernel function calls a script itself. - ExecStack *xstack; - xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, - s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->debugSelector = kernelCallNr; - xstack->type = EXEC_STACK_TYPE_KERNEL; - - // Call kernel function - if (!kernelCall.subFunctionCount) { - s->r_acc = kernelCall.function(s, argc, argv); - } else { - // Sub-functions available, check signature and call that one directly - if (argc < 1) - error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr); - const uint16 subId = argv[0].toUint16(); - // Skip over subfunction-id - argc--; - argv++; - if (subId >= kernelCall.subFunctionCount) - error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); - const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; - if (!kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { - // Signature mismatch - SciTrackOriginReply originReply; - reg_t workaround; - workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); - if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { - kernel->signatureDebug(kernelSubCall.signature, argc, argv); - int callNameLen = strlen(kernelCall.name); - if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { - const char *subCallName = kernelSubCall.name + callNameLen; - error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); - } - error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + // Add stack frame to indicate we're executing a callk. + // This is useful in debugger backtraces if this + // kernel function calls a script itself. + ExecStack *xstack; + xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, + s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); + xstack->debugSelector = kernelCallNr; + xstack->type = EXEC_STACK_TYPE_KERNEL; + + // Call kernel function + if (!kernelCall.subFunctionCount) { + s->r_acc = kernelCall.function(s, argc, argv); + } else { + // Sub-functions available, check signature and call that one directly + if (argc < 1) + error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr); + const uint16 subId = argv[0].toUint16(); + // Skip over subfunction-id + argc--; + argv++; + if (subId >= kernelCall.subFunctionCount) + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); + const KernelSubFunction &kernelSubCall = kernelCall.subFunctions[subId]; + if (kernelSubCall.signature && !kernel->signatureMatch(kernelSubCall.signature, argc, argv)) { + // Signature mismatch + SciTrackOriginReply originReply; + reg_t workaround; + workaround = trackOriginAndFindWorkaround(0, kernelSubCall.workarounds, &originReply); + if ((workaround.segment == 0xFFFF) && (workaround.offset == 0xFFFF)) { + kernel->signatureDebug(kernelSubCall.signature, argc, argv); + int callNameLen = strlen(kernelCall.name); + if (strncmp(kernelCall.name, kernelSubCall.name, callNameLen) == 0) { + const char *subCallName = kernelSubCall.name + callNameLen; + error("[VM] k%s(%s): signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, subCallName, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } - // FIXME: implement some real workaround type logic - ignore call, still do call etc. - if (workaround.segment) - return; + error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } - s->r_acc = kernelSubCall.function(s, argc, argv); + // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment) + return; } + if (!kernelSubCall.function) + error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); + s->r_acc = kernelSubCall.function(s, argc, argv); + } #if 0 // Used for debugging @@ -861,27 +862,9 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { debug("%s", debugMsg.c_str()); #endif - // Remove callk stack frame again, if there's still an execution stack - if (s->_executionStack.begin() != s->_executionStack.end()) - s->_executionStack.pop_back(); - } else { - Common::String warningMsg = "Dummy function " + kernel->getKernelName(kernelCallNr) + - Common::String::printf("[0x%x]", kernelCallNr) + - " invoked - ignoring. Params: " + - Common::String::printf("%d", argc) + " ("; - - for (int i = 0; i < argc; i++) { - warningMsg += Common::String::printf("%04x:%04x", PRINT_REG(argv[i])); - warningMsg += (i == argc - 1 ? ")" : ", "); - } - - warning("%s", warningMsg.c_str()); - - // Make sure that the game doesn't call a function that is considered unused. If - // that happens, error out. - if (kernel->getKernelName(kernelCallNr) == "Dummy") - error("Kernel function %d was called, which was considered to be unused", kernelCallNr); - } + // Remove callk stack frame again, if there's still an execution stack + if (s->_executionStack.begin() != s->_executionStack.end()) + s->_executionStack.pop_back(); } static void gcCountDown(EngineState *s) { -- cgit v1.2.3 From a92a8d3c54f1a90c480bddc12d7f48c826bcd684 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 18:31:11 +0000 Subject: SCI: adding workaround for script error when leaving ulence flats bar in sq1 svn-id: r50787 --- engines/sci/engine/kernel.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 0fd21671a0..bb00f5903b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -247,6 +247,12 @@ static const SciWorkaroundEntry kDisposeScript_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kUnLoad_workarounds[] = { + { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // parameter 1 is not passed, script error when leaving ulence flats bar + SCI_WORKAROUNDENTRY_TERMINATOR +}; + struct SciKernelMapSubEntry { SciVersion fromVersion; SciVersion toVersion; @@ -552,8 +558,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(TimesSin), SIG_EVERYWHERE, "ii", NULL, NULL }, { "SinMult", kTimesSin, SIG_EVERYWHERE, "ii", NULL, NULL }, { MAP_CALL(TimesTan), SIG_EVERYWHERE, "ii", NULL, NULL }, - { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, NULL }, - // ^^ - in SQ1 when leaving ulence flats bar, kUnLoad is called with just one argument (FIXME?) + { MAP_CALL(UnLoad), SIG_EVERYWHERE, "i[ri]", NULL, kUnLoad_workarounds }, { MAP_CALL(ValidPath), SIG_EVERYWHERE, "r", NULL, NULL }, { MAP_CALL(Wait), SIG_EVERYWHERE, "i", NULL, NULL }, -- cgit v1.2.3 From 8b112704b2e840c6b0f789d527c6bc79fcc9c7e9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 18:34:38 +0000 Subject: SCI: adding descriptive comments for subop-tables svn-id: r50788 --- engines/sci/engine/kernel.cpp | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index bb00f5903b..4d5ee4aafe 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -294,6 +294,7 @@ struct SciKernelMapSubEntry { #define MAP_CALL(_name_) #_name_, k##_name_ +// version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI0, 0, MAP_CALL(DoSoundInit), "o", NULL }, { SIG_SOUNDSCI0, 1, MAP_CALL(DoSoundPlay), "o", NULL }, @@ -349,6 +350,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +// version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kGraph_subops[] = { { SIG_SCI32, 1, MAP_CALL(StubNull), "", NULL }, // called by gk1 sci32 right at the start { SIG_SCIALL, 2, MAP_CALL(GraphGetColorCount), "", NULL }, @@ -369,6 +371,7 @@ static const SciKernelMapSubEntry kGraph_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +// version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kPalVary_subops[] = { { SIG_SCIALL, 0, MAP_CALL(PalVaryInit), "ii(i)(i)", NULL }, { SIG_SCIALL, 1, MAP_CALL(PalVaryReverse), "(i)(i)(i)", NULL }, @@ -381,6 +384,7 @@ static const SciKernelMapSubEntry kPalVary_subops[] = { SCI_SUBOPENTRY_TERMINATOR }; +// version, subId, function-mapping, signature, workarounds static const SciKernelMapSubEntry kPalette_subops[] = { { SIG_SCIALL, 1, MAP_CALL(PaletteSetFromResource), "i(i)", NULL }, { SIG_SCIALL, 2, MAP_CALL(PaletteSetFlag), "iii", NULL }, -- cgit v1.2.3 From 5c2489f1533067dcfe303496055e63e8c8d7c189 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 19:58:25 +0000 Subject: SCI: removing hoyle workaround from kAbs & signature and adding it into workaround table svn-id: r50790 --- engines/sci/engine/kernel.cpp | 11 +++++++++-- engines/sci/engine/kmath.cpp | 6 ------ engines/sci/engine/vm.cpp | 4 ++++ 3 files changed, 13 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 4d5ee4aafe..74b0502af4 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -241,6 +241,14 @@ reg_t kDummy(EngineState *s, int argc, reg_t *argv) { // i* -> optional multiple integers // .* -> any parameters afterwards (or none) +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kAbs_workarounds[] = { + { GID_HOYLE1, 1, 0, "room1", "doit", -1, 0, { 2, 0x3e9 } }, // crazy eights - called with objects instead of integers + { GID_HOYLE1, 2, 0, "room2", "doit", -1, 0, { 2, 0x3e9 } }, // old maid - called with objects instead of integers + { GID_HOYLE1, 3, 0, "room3", "doit", -1, 0, { 2, 0x3e9 } }, // hearts - called with objects instead of integers + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kDisposeScript_workarounds[] = { { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard @@ -412,8 +420,7 @@ struct SciKernelMapEntry { // name, version/platform, signature, sub-signatures, workarounds static SciKernelMapEntry s_kernelMap[] = { - { MAP_CALL(Abs), SIG_EVERYWHERE, "[io]", NULL, NULL }, - // ^^ FIXME hoyle + { MAP_CALL(Abs), SIG_EVERYWHERE, "i", NULL, kAbs_workarounds }, { MAP_CALL(AddAfter), SIG_EVERYWHERE, "lnn", NULL, NULL }, { MAP_CALL(AddMenu), SIG_EVERYWHERE, "rr", NULL, NULL }, { MAP_CALL(AddToEnd), SIG_EVERYWHERE, "ln", NULL, NULL }, diff --git a/engines/sci/engine/kmath.cpp b/engines/sci/engine/kmath.cpp index a7baf72b65..eab964d624 100644 --- a/engines/sci/engine/kmath.cpp +++ b/engines/sci/engine/kmath.cpp @@ -36,12 +36,6 @@ reg_t kRandom(EngineState *s, int argc, reg_t *argv) { } reg_t kAbs(EngineState *s, int argc, reg_t *argv) { - if (g_sci->getGameId() == GID_HOYLE1) { - // This is a hack, but so is the code in Hoyle1 that needs it. - // FIXME: where is this exactly needed? - if (argv[0].segment) - return make_reg(0, 0x3e9); // Yes people, this is an object - } return make_reg(0, abs(argv[0].toSint16())); } diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index cbfaf5575f..4755db3922 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -796,6 +796,8 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { error("[VM] k%s[%x]: signature mismatch via method %s::%s (script %d, localCall %x)", kernelCall.name, kernelCallNr, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment == 2) + s->r_acc = make_reg(0, workaround.offset); if (workaround.segment) return; } @@ -838,6 +840,8 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { error("[VM] k%s: signature mismatch via method %s::%s (script %d, localCall %x)", kernelSubCall.name, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); } // FIXME: implement some real workaround type logic - ignore call, still do call etc. + if (workaround.segment == 2) + s->r_acc = make_reg(0, workaround.offset); if (workaround.segment) return; } -- cgit v1.2.3 From 5e4d4fde678e0fda0bd371770046208d7082b8c4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 20:45:59 +0000 Subject: SCI: adding workaround for kGraph(fillBoxAny) in sq4cd when accessing the game menu svn-id: r50791 --- engines/sci/engine/kernel.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 74b0502af4..44062d70c0 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -255,6 +255,12 @@ static const SciWorkaroundEntry kDisposeScript_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { + { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kUnLoad_workarounds[] = { { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // parameter 1 is not passed, script error when leaving ulence flats bar @@ -371,7 +377,7 @@ static const SciKernelMapSubEntry kGraph_subops[] = { // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL }, - { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", NULL }, + { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", kGraphFillBoxAny_workarounds }, { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r)", NULL }, { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL }, { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL }, -- cgit v1.2.3 From 09fd47236d82c169a0c2886f6baa752beb401a3d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 20:50:52 +0000 Subject: SCI: adding to execstack only right before executing kernel call, otherwise it wouldnt be possible to skip over sub-function kernel calls via workarounds svn-id: r50792 --- engines/sci/engine/vm.cpp | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 4755db3922..b265170cad 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -776,6 +776,17 @@ static reg_t pointer_add(EngineState *s, reg_t base, int offset) { } } +static void addKernelCallToExecStack(EngineState *s, int kernelCallNr, int argc, reg_t *argv) { + // Add stack frame to indicate we're executing a callk. + // This is useful in debugger backtraces if this + // kernel function calls a script itself. + ExecStack *xstack; + xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, + s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); + xstack->debugSelector = kernelCallNr; + xstack->type = EXEC_STACK_TYPE_KERNEL; +} + static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { Kernel *kernel = g_sci->getKernel(); @@ -802,17 +813,10 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { return; } - // Add stack frame to indicate we're executing a callk. - // This is useful in debugger backtraces if this - // kernel function calls a script itself. - ExecStack *xstack; - xstack = add_exec_stack_entry(s->_executionStack, NULL_REG, NULL, NULL_REG, argc, argv - 1, 0, -1, -1, NULL_REG, - s->_executionStack.size()-1, SCI_XS_CALLEE_LOCALS); - xstack->debugSelector = kernelCallNr; - xstack->type = EXEC_STACK_TYPE_KERNEL; // Call kernel function if (!kernelCall.subFunctionCount) { + addKernelCallToExecStack(s, kernelCallNr, argc, argv); s->r_acc = kernelCall.function(s, argc, argv); } else { // Sub-functions available, check signature and call that one directly @@ -847,6 +851,7 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { } if (!kernelSubCall.function) error("[VM] k%s: subfunction-id %d requested, but not available", kernelCall.name, subId); + addKernelCallToExecStack(s, kernelCallNr, argc, argv); s->r_acc = kernelSubCall.function(s, argc, argv); } -- cgit v1.2.3 From 5721b75205acd15053430f24e92b8f170478ced0 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 21:47:37 +0000 Subject: SCI: fixing kGraph(updateBox) signature for kq6 hires/lowres (allowing null reference) svn-id: r50793 --- engines/sci/engine/kernel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 44062d70c0..7796f31047 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -378,7 +378,8 @@ static const SciKernelMapSubEntry kGraph_subops[] = { { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL }, { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", kGraphFillBoxAny_workarounds }, - { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r)", NULL }, + { SIG_SCI11, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r0)", NULL }, // kq6 hires + { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)", NULL }, { SIG_SCIALL, 13, MAP_CALL(GraphRedrawBox), "iiii", NULL }, { SIG_SCIALL, 14, MAP_CALL(GraphAdjustPriority), "ii", NULL }, { SIG_SCI11, 15, MAP_CALL(GraphSaveUpscaledHiresBox), "iiii", NULL }, // kq6 hires -- cgit v1.2.3 From df6ead5f93758aa9871594fc3872930eaf9c9d60 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sat, 10 Jul 2010 22:27:28 +0000 Subject: SCI: calling speed throttler as well from kPalette(setIntensity) if needed - fixes kq6 intro svn-id: r50794 --- engines/sci/engine/kmisc.cpp | 23 +---------------------- engines/sci/engine/state.cpp | 15 +++++++++++++++ engines/sci/engine/state.h | 1 + engines/sci/engine/vm.cpp | 3 +-- engines/sci/graphics/palette.cpp | 6 +++++- 5 files changed, 23 insertions(+), 25 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 3d206d0358..1ed12c092e 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -67,28 +67,7 @@ reg_t kGameIsRestarting(EngineState *s, int argc, reg_t *argv) { neededSleep = 60; } - if (s->_throttleTrigger) { - // Some games seem to get the duration of main loop initially and then - // switch of animations for the whole game based on that (qfg2, iceman). - // We are now running full speed initially to avoid that. - // It seems like we dont need to do that anymore - //if (s->_throttleCounter < 50) { - // s->_throttleCounter++; - // return s->r_acc; - //} - - uint32 curTime = g_system->getMillis(); - uint32 duration = curTime - s->_throttleLastTime; - - if (duration < neededSleep) { - g_sci->sleep(neededSleep - duration); - s->_throttleLastTime = g_system->getMillis(); - } else { - s->_throttleLastTime = curTime; - } - s->_throttleTrigger = false; - } - + s->speedThrottler(neededSleep); return s->r_acc; } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 6f54a3c199..245a021605 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -111,6 +111,21 @@ void EngineState::reset(bool isRestoring) { scriptGCInterval = GC_INTERVAL; } +void EngineState::speedThrottler(uint32 neededSleep) { + if (_throttleTrigger) { + uint32 curTime = g_system->getMillis(); + uint32 duration = curTime - _throttleLastTime; + + if (duration < neededSleep) { + g_sci->sleep(neededSleep - duration); + _throttleLastTime = g_system->getMillis(); + } else { + _throttleLastTime = curTime; + } + _throttleTrigger = false; + } +} + void EngineState::wait(int16 ticks) { uint32 time = g_system->getMillis(); r_acc = make_reg(0, ((long)time - (long)lastWaitTime) * 60 / 1000); diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index 885c8a871c..e304c6d889 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -106,6 +106,7 @@ public: uint32 lastWaitTime; /**< The last time the game invoked Wait() */ uint32 _screenUpdateTime; /**< The last time the game updated the screen */ + void speedThrottler(uint32 neededSleep); void wait(int16 ticks); uint32 _throttleCounter; /**< total times kAnimate was invoked */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index b265170cad..0dd82621fe 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -857,8 +857,7 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { #if 0 // Used for debugging - Common::String debugMsg = kernelFunc.origName + - Common::String::printf("[0x%x]", kernelFuncNr) + + Common::String debugMsg = Common::String::printf("%s [0x%x]", kernelCall.name, kernelCallNr) + Common::String::printf(", %d params: ", argc) + " ("; diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index b85281e9c4..7e9dc0ed31 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -411,7 +411,11 @@ void GfxPalette::kernelSetIntensity(uint16 fromColor, uint16 toColor, uint16 int memset(&_sysPalette.intensity[0] + fromColor, intensity, toColor - fromColor); if (setPalette) { setOnScreen(); - g_sci->getEngineState()->_throttleTrigger = true; + EngineState *state = g_sci->getEngineState(); + // Call speed throttler from here as well just in case we need it + // At least in kq6 intro the scripts call us in a tight loop for fadein/fadeout + state->speedThrottler(30); + state->_throttleTrigger = true; } } -- cgit v1.2.3 From c77c84f5c52deb34930ed4e7f627ad672579c74c Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 10:11:31 +0000 Subject: SCI: also sync palette after playing movies, fixes kq6 intro svn-id: r50798 --- engines/sci/engine/kgraphics.cpp | 4 +++- engines/sci/graphics/palette.cpp | 4 ++++ engines/sci/graphics/palette.h | 2 ++ engines/sci/graphics/screen.cpp | 14 +++++++++++++- engines/sci/graphics/screen.h | 3 ++- 5 files changed, 24 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 0e7930275a..13f2bd4875 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -1192,8 +1192,10 @@ reg_t kShowMovie(EngineState *s, int argc, reg_t *argv) { // We also won't be copying the screen to the SCI screen... if (g_system->getScreenFormat().bytesPerPixel != 1) initGraphics(screenWidth, screenHeight, screenWidth > 320); - else + else { g_sci->_gfxScreen->kernelSyncWithFramebuffer(); + g_sci->_gfxPalette->kernelSyncScreenPalette(); + } } if (reshowCursor) diff --git a/engines/sci/graphics/palette.cpp b/engines/sci/graphics/palette.cpp index 7e9dc0ed31..957199f8b9 100644 --- a/engines/sci/graphics/palette.cpp +++ b/engines/sci/graphics/palette.cpp @@ -498,6 +498,10 @@ void GfxPalette::kernelAssertPalette(GuiResourceId resourceId) { } } +void GfxPalette::kernelSyncScreenPalette() { + _screen->getPalette(&_sysPalette); +} + // palVary // init - only does, if palVaryOn == false // target, start, new palette allocation diff --git a/engines/sci/graphics/palette.h b/engines/sci/graphics/palette.h index 1fa8c16d26..6af1d5a490 100644 --- a/engines/sci/graphics/palette.h +++ b/engines/sci/graphics/palette.h @@ -65,6 +65,8 @@ public: void kernelAnimateSet(); void kernelAssertPalette(GuiResourceId resourceId); + void kernelSyncScreenPalette(); + bool kernelPalVaryInit(GuiResourceId resourceId, uint16 ticks, uint16 stepStop, uint16 direction); int16 kernelPalVaryReverse(int16 ticks, uint16 stepStop, int16 direction); int16 kernelPalVaryGetCurrentStep(); diff --git a/engines/sci/graphics/screen.cpp b/engines/sci/graphics/screen.cpp index 1d3a4ea1f7..488bb83ab3 100644 --- a/engines/sci/graphics/screen.cpp +++ b/engines/sci/graphics/screen.cpp @@ -499,7 +499,19 @@ void GfxScreen::bitsRestoreDisplayScreen(Common::Rect rect, byte *&memoryPtr) { } } -void GfxScreen::setPalette(Palette*pal) { +void GfxScreen::getPalette(Palette *pal) { + // just copy palette to system + byte bpal[4 * 256]; + // Get current palette, update it and put back + g_system->grabPalette(bpal, 0, 256); + for (int16 i = 1; i < 255; i++) { + pal->colors[i].r = bpal[i * 4]; + pal->colors[i].g = bpal[i * 4 + 1]; + pal->colors[i].b = bpal[i * 4 + 2]; + } +} + +void GfxScreen::setPalette(Palette *pal) { // just copy palette to system byte bpal[4 * 256]; // Get current palette, update it and put back diff --git a/engines/sci/graphics/screen.h b/engines/sci/graphics/screen.h index 900c338bb2..f1e3d028a8 100644 --- a/engines/sci/graphics/screen.h +++ b/engines/sci/graphics/screen.h @@ -106,7 +106,8 @@ public: void bitsGetRect(byte *memoryPtr, Common::Rect *destRect); void bitsRestore(byte *memoryPtr); - void setPalette(Palette*pal); + void getPalette(Palette *pal); + void setPalette(Palette *pal); void setVerticalShakePos(uint16 shakePos); -- cgit v1.2.3 From 110d644f492ce624f70c62639b5fb01832022a58 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 11:12:03 +0000 Subject: SCI: adding workaround for signature mismatch for kDoSound(fade) in kq6 floppy/demo svn-id: r50799 --- engines/sci/engine/kernel.cpp | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 7796f31047..f3f0c37391 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -255,6 +255,12 @@ static const SciWorkaroundEntry kDisposeScript_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { + { GID_KQ6, 989, 0, "globalSound", "fade", -1, 0, { 0, 0 } }, // parameter 4 is an object during the intro + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack @@ -351,7 +357,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI1LATE, 8, MAP_CALL(DoSoundPlay), NULL, NULL }, { SIG_SOUNDSCI1LATE, 9, MAP_CALL(DoSoundStop), NULL, NULL }, { SIG_SOUNDSCI1LATE, 10, MAP_CALL(DoSoundPause), NULL, NULL }, - { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), "oiiii(i)", NULL }, + { SIG_SOUNDSCI1LATE, 11, MAP_CALL(DoSoundFade), "oiiii(i)", kDoSoundFade_workarounds }, { SIG_SOUNDSCI1LATE, 12, MAP_CALL(DoSoundSetHold), NULL, NULL }, { SIG_SOUNDSCI1LATE, 13, MAP_CALL(DoSoundDummy), NULL, NULL }, { SIG_SOUNDSCI1LATE, 14, MAP_CALL(DoSoundSetVolume), "oi", NULL }, -- cgit v1.2.3 From 38d79f60e3217debbf99c971a87ea581c00f007f Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 11:52:17 +0000 Subject: SCI: changing signature for kDoSound(resume) it seems its called right after restoring to resume music - which we do already automatically svn-id: r50800 --- engines/sci/engine/kernel.cpp | 2 +- engines/sci/sound/soundcmd.cpp | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index f3f0c37391..9f6bab898f 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -323,7 +323,7 @@ static const SciKernelMapSubEntry kDoSound_subops[] = { { SIG_SOUNDSCI0, 4, MAP_CALL(DoSoundMute), "(i)", NULL }, { SIG_SOUNDSCI0, 5, MAP_CALL(DoSoundStop), "o", NULL }, { SIG_SOUNDSCI0, 6, MAP_CALL(DoSoundPause), "i", NULL }, - { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "o", NULL }, + { SIG_SOUNDSCI0, 7, MAP_CALL(DoSoundResume), "", NULL }, { SIG_SOUNDSCI0, 8, MAP_CALL(DoSoundMasterVolume), "(i)", NULL }, { SIG_SOUNDSCI0, 9, MAP_CALL(DoSoundUpdate), "o", NULL }, { SIG_SOUNDSCI0, 10, MAP_CALL(DoSoundFade), "o", NULL }, diff --git a/engines/sci/sound/soundcmd.cpp b/engines/sci/sound/soundcmd.cpp index 11b0215a32..51832af09f 100644 --- a/engines/sci/sound/soundcmd.cpp +++ b/engines/sci/sound/soundcmd.cpp @@ -251,6 +251,9 @@ reg_t SoundCommandParser::kDoSoundPause(int argc, reg_t *argv, reg_t acc) { // SCI0 only command reg_t SoundCommandParser::kDoSoundResume(int argc, reg_t *argv, reg_t acc) { + // this doesn't seem to do what we think it's doing + // it's called with no arguments at all (just restore a game in qfg1) + return acc; reg_t obj = argv[0]; MusicEntry *musicSlot = _music->getSlot(obj); -- cgit v1.2.3 From 30a28ec107dc254d8db0d9361cd0d7d34a089ec2 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 16:55:08 +0000 Subject: SCI: remove "a:" from default export hero quest 1 filename "a:hq1_hero.sav" svn-id: r50803 --- engines/sci/engine/kgraphics.cpp | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index 13f2bd4875..e621e1b85a 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -790,6 +790,11 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { mode = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(max)); cursorPos = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor)); + if (cursorPos > text.size()) { + // if cursor is outside of text, adjust accordingly + cursorPos = text.size(); + writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos); + } debugC(2, kDebugLevelGraphics, "drawing edit control %04x:%04x (text %04x:%04x, '%s') to %d,%d", PRINT_REG(controlObject), PRINT_REG(textReference), text.c_str(), x, y); g_sci->_gfxControls->kernelDrawTextEdit(rect, controlObject, g_sci->strSplit(text.c_str(), NULL).c_str(), fontId, mode, style, cursorPos, maxChars, hilite); return; @@ -880,6 +885,18 @@ reg_t kDrawControl(EngineState *s, int argc, reg_t *argv) { int state = readSelectorValue(s->_segMan, controlObject, SELECTOR(state)); writeSelectorValue(s->_segMan, controlObject, SELECTOR(state), (state | SCI_CONTROLS_STYLE_DISABLED) & ~SCI_CONTROLS_STYLE_ENABLED); } + if (objName == "DEdit") { + reg_t textReference = readSelector(s->_segMan, controlObject, SELECTOR(text)); + if (!textReference.isNull()) { + Common::String text = s->_segMan->getString(textReference); + if (text == "a:hq1_hero.sav") { + // Remove "a:" from hero quest export default filename + text.deleteChar(0); + text.deleteChar(0); + s->_segMan->strcpy(textReference, text.c_str()); + } + } + } _k_GenericDrawControl(s, controlObject, false); return NULL_REG; -- cgit v1.2.3 From 219a6627c25e4ee931e3afb1b70a0a4fe83c249d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 18:51:28 +0000 Subject: SCI: changing uninitialized workaround for lsl6 narrator svn-id: r50804 --- engines/sci/engine/vm.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 0dd82621fe..f4f8c07d48 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -312,7 +312,9 @@ static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *w do { workaround = workaroundList; while (workaround->objectName) { - if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr && (workaround->inheritanceLevel == inheritanceLevel) && (workaround->objectName == searchObjectName) + if (workaround->gameId == gameId && workaround->scriptNr == curScriptNr + && ((workaround->inheritanceLevel == -1) || (workaround->inheritanceLevel == inheritanceLevel)) + && (workaround->objectName == searchObjectName) && workaround->methodName == curMethodName && workaround->localCallOffset == lastCall->debugLocalCallOffset && workaround->index == index) { // Workaround found return workaround->newValue; @@ -347,7 +349,7 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 928, 1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_LSL6, 928, -1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio -- cgit v1.2.3 From 737f2c0fa4b44033a1f6343d5ee700228b00d10d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 19:11:48 +0000 Subject: SCI: adding signature workaround for script error in lsl6 during intro, also changing comments of other workarounds svn-id: r50805 --- engines/sci/engine/kernel.cpp | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 9f6bab898f..9006c6a646 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -243,34 +243,35 @@ reg_t kDummy(EngineState *s, int argc, reg_t *argv) { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kAbs_workarounds[] = { - { GID_HOYLE1, 1, 0, "room1", "doit", -1, 0, { 2, 0x3e9 } }, // crazy eights - called with objects instead of integers - { GID_HOYLE1, 2, 0, "room2", "doit", -1, 0, { 2, 0x3e9 } }, // old maid - called with objects instead of integers - { GID_HOYLE1, 3, 0, "room3", "doit", -1, 0, { 2, 0x3e9 } }, // hearts - called with objects instead of integers - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_HOYLE1, 1, 0, "room1", "doit", -1, 0, { 2, 0x3e9 } }, // crazy eights - called with objects instead of integers + { GID_HOYLE1, 2, 0, "room2", "doit", -1, 0, { 2, 0x3e9 } }, // old maid - called with objects instead of integers + { GID_HOYLE1, 3, 0, "room3", "doit", -1, 0, { 2, 0x3e9 } }, // hearts - called with objects instead of integers + SCI_WORKAROUNDENTRY_TERMINATOR }; // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kDisposeScript_workarounds[] = { - { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // parameter 0 is an object when leaving graveyard - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_QFG1, 64, 0, "rm64", "dispose", -1, 0, { 1, 0 } }, // when leaving graveyard, parameter 0 is an object + SCI_WORKAROUNDENTRY_TERMINATOR }; // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { - { GID_KQ6, 989, 0, "globalSound", "fade", -1, 0, { 0, 0 } }, // parameter 4 is an object during the intro - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_KQ6, 989, 0, "globalSound", "fade", -1, 0, { 0, 0 } }, // during intro, parameter 4 is an object + SCI_WORKAROUNDENTRY_TERMINATOR }; // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { - { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack + SCI_WORKAROUNDENTRY_TERMINATOR }; // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kUnLoad_workarounds[] = { - { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // parameter 1 is not passed, script error when leaving ulence flats bar - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_LSL6, 130, 0, "recruitLarryScr", "changeState", -1, 0, { 1, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error + SCI_WORKAROUNDENTRY_TERMINATOR }; struct SciKernelMapSubEntry { -- cgit v1.2.3 From a94b25f99cc29700770089982850eab9d11a3d87 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 19:16:16 +0000 Subject: SCI: kUnLoad - removing unneeded warnings (signature mismatch will happen now), added information about parameters svn-id: r50806 --- engines/sci/engine/kscripts.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kscripts.cpp b/engines/sci/engine/kscripts.cpp index 4a50553b34..029943b070 100644 --- a/engines/sci/engine/kscripts.cpp +++ b/engines/sci/engine/kscripts.cpp @@ -49,6 +49,8 @@ reg_t kLoad(EngineState *s, int argc, reg_t *argv) { } // Unloads an arbitrary resource of type 'restype' with resource numbber 'resnr' +// behaviour of this call didn't change between sci0->sci1.1 parameter wise, which means getting called with +// 1 or 3+ parameters is not right according to sierra sci reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { if (argc >= 2) { ResourceType restype = (ResourceType)(argv[0].toUint16() & 0x7f); @@ -64,11 +66,6 @@ reg_t kUnLoad(EngineState *s, int argc, reg_t *argv) { if (restype == kResourceTypeMemory) s->_segMan->freeHunkEntry(resnr); - - if (argc > 2) - warning("kUnload called with more than 2 parameters (%d)", argc); - } else { - warning("kUnload called with less than 2 parameters (%d) - ignoring", argc); } return s->r_acc; -- cgit v1.2.3 From 115d7d0132bd410f2e1f235740c3ead61de9458d Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Sun, 11 Jul 2010 21:03:23 +0000 Subject: SCI: fix signature loading for subops, fixes kq6 signature mismatch svn-id: r50807 --- engines/sci/engine/kernel.cpp | 38 ++++++++++++++++++++------------------ 1 file changed, 20 insertions(+), 18 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 9006c6a646..a72c070d33 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -1180,27 +1180,29 @@ void Kernel::mapFunctions() { if ((kernelSubMap->fromVersion == SCI_VERSION_NONE) || (kernelSubMap->fromVersion <= mySubVersion)) if ((kernelSubMap->toVersion == SCI_VERSION_NONE) || (kernelSubMap->toVersion >= mySubVersion)) { uint subId = kernelSubMap->id; - subFunctions[subId].function = kernelSubMap->function; - subFunctions[subId].name = kernelSubMap->name; - subFunctions[subId].workarounds = kernelSubMap->workarounds; - if (kernelSubMap->signature) { - subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); - } else { - // we go back the submap to find the previous signature for that kernel call - const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; - uint kernelSubLeft = kernelSubNr; - while (kernelSubLeft) { - kernelSubLeft--; - kernelSubMapBack--; - if (kernelSubMapBack->name == kernelSubMap->name) { - if (kernelSubMapBack->signature) { - subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); - break; + if (!subFunctions[subId].function) { + subFunctions[subId].function = kernelSubMap->function; + subFunctions[subId].name = kernelSubMap->name; + subFunctions[subId].workarounds = kernelSubMap->workarounds; + if (kernelSubMap->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMap->signature); + } else { + // we go back the submap to find the previous signature for that kernel call + const SciKernelMapSubEntry *kernelSubMapBack = kernelSubMap; + uint kernelSubLeft = kernelSubNr; + while (kernelSubLeft) { + kernelSubLeft--; + kernelSubMapBack--; + if (kernelSubMapBack->name == kernelSubMap->name) { + if (kernelSubMapBack->signature) { + subFunctions[subId].signature = parseKernelSignature(kernelSubMap->name, kernelSubMapBack->signature); + break; + } } } + if (!subFunctions[subId].signature) + error("k%s: no previous signatures", kernelSubMap->name); } - if (!subFunctions[subId].signature) - error("k%s: no previous signatures", kernelSubMap->name); } } kernelSubMap++; -- cgit v1.2.3 From 4c9ad98dfef2b643d14a6a55615e2a54e5822f70 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 08:38:30 +0000 Subject: SCI: returning 0 when parameter reads go out-of-bounds, onto the stack and hit an uninitialized temp, fixes pq2 .490 svn-id: r50812 --- engines/sci/engine/vm.cpp | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index f4f8c07d48..ed839654bc 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -365,13 +365,25 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) { if (validate_variable(r, stack_base, type, max, index)) { - if (type == VAR_TEMP && r[index].segment == 0xffff) { - // Uninitialized read on a temp - // We need to find correct replacements for each situation manually - SciTrackOriginReply originReply; - r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply); - if ((r[index].segment == 0xFFFF) && (r[index].offset == 0xFFFF)) - error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + if (r[index].segment == 0xffff) { + switch (type) { + case VAR_TEMP: { + // Uninitialized read on a temp + // We need to find correct replacements for each situation manually + SciTrackOriginReply originReply; + r[index] = trackOriginAndFindWorkaround(index, uninitializedReadWorkarounds, &originReply); + if ((r[index].segment == 0xFFFF) && (r[index].offset == 0xFFFF)) + error("Uninitialized read for temp %d from method %s::%s (script %d, localCall %x)", index, originReply.objectName.c_str(), originReply.methodName.c_str(), originReply.scriptNr, originReply.localCallOffset); + break; + } + case VAR_PARAM: + // Out-of-bounds read for a parameter that goes onto stack and hits an uninitialized temp + // We return 0 currently in that case + warning("Read for a parameter goes out-of-bounds, onto the stack and gets uninitialized temp"); + return NULL_REG; + default: + break; + } } return r[index]; } else -- cgit v1.2.3 From 101498e7701aec9240599122fd161c9b407f28f7 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 08:59:43 +0000 Subject: SCI: adding 3 uninitialized temp workarounds for kq6 - found and created by Ceriand, thanx svn-id: r50813 --- engines/sci/engine/vm.cpp | 45 ++++++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 21 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index ed839654bc..1ed3acbace 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -340,27 +340,30 @@ static reg_t trackOriginAndFindWorkaround(int index, const SciWorkaroundEntry *w // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { - { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu - { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu - { GID_GK2, 11, 0, "", "export 10", -1, 3, { 0, 0 } }, // called when the game starts - { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game - { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts - { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts - { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room - { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') - { GID_LSL6, 928, -1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class - { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 - { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon - { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio - { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is - { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc) - { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser - { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) - { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller - { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, // called when the game starts - { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, // called when pressing "Start game" in the main menu - SCI_WORKAROUNDENTRY_TERMINATOR + { GID_LAURABOW2, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 24, 0, "gcWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_FREDDYPHARKAS, 31, 0, "quitWin", "open", -1, 5, { 0, 0xf } }, // is used as priority for game menu + { GID_GK2, 11, 0, "", "export 10", -1, 3, { 0, 0 } }, // called when the game starts + { GID_JONES, 232, 0, "weekendText", "draw", 0x3d3, 0, { 0, 0 } }, // jones/cd only - gets called during the game + { GID_JONES, 255, 0, "", "export 0", -1, 13, { 0, 0 } }, // jones/ega&vga only - called when the game starts + { GID_JONES, 255, 0, "", "export 0", -1, 14, { 0, 0 } }, // jones/ega&vga only - called when the game starts + { GID_LSL1, 720, 0, "rm720", "init", -1, 0, { 0, 0 } }, // age check room + { GID_LSL3, 997, 0, "TheMenuBar", "handleEvent", -1, 1, { 0, 0xf } }, // when setting volume the first time, this temp is used to set volume on entry (normally it would have been initialized to 's') + { GID_LSL6, 928, -1, "Narrator", "startText", -1, 0, { 0, 0 } }, // used by various objects that are even translated in foreign versions, that's why we use the base-class + { GID_ISLANDBRAIN, 140, 0, "piece", "init", -1, 3, { 0, 1 } }, // first puzzle right at the start, some initialization variable. bnt is done on it, and it should be non-0 + { GID_ISLANDBRAIN, 268, 0, "anElement", "select", -1, 0, { 0, 0 } }, // elements puzzle, gets used before super TextIcon + { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio + { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is + { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc) + { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast + { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle + { GID_KQ6, 30, 0, "rats", "changeState", -1, 0, { 0, 0 } }, // rats in the catacombs + { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser + { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) + { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller + { GID_SQ6, 0, 0, "SQ6", "init", -1, 2, { 0, 0 } }, // called when the game starts + { GID_SQ6, 64950, 0, "View", "handleEvent", -1, 0, { 0, 0 } }, // called when pressing "Start game" in the main menu + SCI_WORKAROUNDENTRY_TERMINATOR }; static reg_t validate_read_var(reg_t *r, reg_t *stack_base, int type, int max, int index, reg_t default_value) { -- cgit v1.2.3 From c1e954bdad96b7ae8e518e92aec365c7c26377bb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 09:24:18 +0000 Subject: SCI: add workaround for lsl6 restore issue (needs to get further investigated), hunk segment is used but hunk segment isn't existant at that point when restoring the game svn-id: r50814 --- engines/sci/engine/kernel.cpp | 15 +++++++++++++-- engines/sci/engine/vm.cpp | 2 ++ 2 files changed, 15 insertions(+), 2 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index a72c070d33..c505d1916b 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -261,6 +261,13 @@ static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { + { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 1, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time + // ^^ TODO: check, if this is really a script error or an issue with our restore code + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack @@ -380,7 +387,7 @@ static const SciKernelMapSubEntry kGraph_subops[] = { // 5 - nop // 6 - draw pattern { SIG_SCIALL, 7, MAP_CALL(GraphSaveBox), "iiiii", NULL }, - { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", NULL }, + { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", kGraphRestoreBox_workarounds }, // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL }, @@ -504,7 +511,7 @@ static SciKernelMapEntry s_kernelMap[] = { { MAP_CALL(GetTime), SIG_EVERYWHERE, "(i)", NULL, NULL }, { MAP_CALL(GlobalToLocal), SIG_SCI32, SIGFOR_ALL, "oo", NULL, NULL }, { MAP_CALL(GlobalToLocal), SIG_EVERYWHERE, "o", NULL, NULL }, - { MAP_CALL(Graph), SIG_EVERYWHERE, "i([!.]*)", kGraph_subops, NULL }, + { MAP_CALL(Graph), SIG_EVERYWHERE, NULL, kGraph_subops, NULL }, { MAP_CALL(HaveMouse), SIG_EVERYWHERE, "", NULL, NULL }, { MAP_CALL(HiliteControl), SIG_EVERYWHERE, "o", NULL, NULL }, { MAP_CALL(InitBresen), SIG_EVERYWHERE, "o(i)", NULL, NULL }, @@ -726,6 +733,10 @@ static uint16 *parseKernelSignature(const char *kernelName, const char *writtenS bool optional = false; bool hadOptional = false; + // No signature given? no signature out + if (!writtenSig) + return NULL; + // First, we check how many bytes the result will be // we also check, if the written signature makes any sense curPos = writtenSig; diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 1ed3acbace..32da080e43 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -839,6 +839,8 @@ static void callKernelFunc(EngineState *s, int kernelCallNr, int argc) { // Sub-functions available, check signature and call that one directly if (argc < 1) error("[VM] k%s[%x]: no subfunction-id parameter given", kernelCall.name, kernelCallNr); + if (argv[0].segment) + error("[VM] k%s[%x]: given subfunction-id is actually a pointer", kernelCall.name, kernelCallNr); const uint16 subId = argv[0].toUint16(); // Skip over subfunction-id argc--; -- cgit v1.2.3 From 21c91066202f58ca50ff26a7c543379c53045fba Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 10:31:32 +0000 Subject: SCI: added another workaround for lsl6 kGraph(restoreBox) svn-id: r50815 --- engines/sci/engine/kernel.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index c505d1916b..e9b6787b05 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -263,8 +263,9 @@ static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { - { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 1, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time + { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 0, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time // ^^ TODO: check, if this is really a script error or an issue with our restore code + { GID_LSL6, 86, 0, "LL6Inv", "hide", -1, 0, { 0, 0 } }, // happens during the game, gets called with 1 extra parameter SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 698a347da6ceeecf922209709ac68eec9ce0e1d1 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 10:47:47 +0000 Subject: SCI: adding another restore workaround for lsl6 svn-id: r50816 --- engines/sci/engine/kernel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index e9b6787b05..be727d6f45 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -263,6 +263,7 @@ static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { + { GID_LSL6, 85, 0, "lScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 0, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time // ^^ TODO: check, if this is really a script error or an issue with our restore code { GID_LSL6, 86, 0, "LL6Inv", "hide", -1, 0, { 0, 0 } }, // happens during the game, gets called with 1 extra parameter -- cgit v1.2.3 From e782fec85aa48b8b32f4e1e1d3677411d99899ae Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 12 Jul 2010 11:09:11 +0000 Subject: SCI: Remove dead code svn-id: r50817 --- engines/sci/engine/kernel.h | 4 ---- 1 file changed, 4 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.h b/engines/sci/engine/kernel.h index a054aa2b1c..fa206e8053 100644 --- a/engines/sci/engine/kernel.h +++ b/engines/sci/engine/kernel.h @@ -150,10 +150,6 @@ struct KernelFunction { bool debugCalls; }; -enum AutoDetectedFeatures { - kFeatureOldScriptHeader = 1 << 0 -}; - class Kernel { public: /** -- cgit v1.2.3 From 20ef5c562335e1f3fa45307b3f43065da0c4dfa4 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 12 Jul 2010 11:09:29 +0000 Subject: SCI: Fix warning svn-id: r50818 --- engines/sci/engine/kgraphics.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kgraphics.cpp b/engines/sci/engine/kgraphics.cpp index e621e1b85a..29f7565ef9 100644 --- a/engines/sci/engine/kgraphics.cpp +++ b/engines/sci/engine/kgraphics.cpp @@ -790,7 +790,7 @@ void _k_GenericDrawControl(EngineState *s, reg_t controlObject, bool hilite) { mode = readSelectorValue(s->_segMan, controlObject, SELECTOR(mode)); maxChars = readSelectorValue(s->_segMan, controlObject, SELECTOR(max)); cursorPos = readSelectorValue(s->_segMan, controlObject, SELECTOR(cursor)); - if (cursorPos > text.size()) { + if (cursorPos > (int)text.size()) { // if cursor is outside of text, adjust accordingly cursorPos = text.size(); writeSelectorValue(s->_segMan, controlObject, SELECTOR(cursor), cursorPos); -- cgit v1.2.3 From ad098addd25891daf876a0ac21122d94920b2fcb Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 11:20:42 +0000 Subject: SCI: adding uninitialized workaround for lsl6 svn-id: r50819 --- engines/sci/engine/vm.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 32da080e43..42f7424bf9 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -358,6 +358,7 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle { GID_KQ6, 30, 0, "rats", "changeState", -1, 0, { 0, 0 } }, // rats in the catacombs + { GID_LSL6, 85, 0, "washcloth", "doVerb", -1, 0, { 0, 0 } }, // washcloth in inventory { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser { GID_SQ1, 703, 0, "firePulsar", "changeState", 0x18a, 0, { 0, 0 } }, // export 1, but called locally (when shooting at aliens) { GID_SQ4, 928, 0, "Narrator", "startText", -1, 1000, { 0, 1 } }, // sq4cd: method returns this to the caller -- cgit v1.2.3 From 8fa759adb3c9bcb3e8948b31d2deaabd9295dff6 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 12:31:13 +0000 Subject: SCI: adding workaround for signature mismatch when giving merrily the key to the bungee tower svn-id: r50820 --- engines/sci/engine/kernel.cpp | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index be727d6f45..892e64a0e1 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -263,6 +263,7 @@ static const SciWorkaroundEntry kDoSoundFade_workarounds[] = { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { + { GID_LSL6, 85, 0, "rScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below { GID_LSL6, 85, 0, "lScroller", "hide", -1, 0, { 0, 0 } }, // happens when restoring (sometimes), same as the one below { GID_LSL6, 86, 0, "LL6Inv", "show", -1, 0, { 0, 0 } }, // happens when restoring, is called with hunk segment, but hunk is not allocated at that time // ^^ TODO: check, if this is really a script error or an issue with our restore code @@ -270,6 +271,12 @@ static const SciWorkaroundEntry kGraphRestoreBox_workarounds[] = { SCI_WORKAROUNDENTRY_TERMINATOR }; +// gameID, scriptNr,lvl, object-name, method-name, call, index, replace +static const SciWorkaroundEntry kGraphFillBoxForeground_workarounds[] = { + { GID_LSL6, 0, 0, "LSL6", "hideControls", -1, 0, { 0, 0 } }, // happens when giving the bungee key to merrily - gets called with additional 5th parameter + SCI_WORKAROUNDENTRY_TERMINATOR +}; + // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { { GID_SQ4, 818, 0, "iconTextSwitch", "show", -1, 0, { 0, 0 } }, // game menu "text/speech" display - parameter 5 is missing, but the right color number is on the stack @@ -392,7 +399,7 @@ static const SciKernelMapSubEntry kGraph_subops[] = { { SIG_SCIALL, 8, MAP_CALL(GraphRestoreBox), "[r0!]", kGraphRestoreBox_workarounds }, // ^ this may get called with invalid references, we check them within restoreBits() and sierra sci behaves the same { SIG_SCIALL, 9, MAP_CALL(GraphFillBoxBackground), "iiii", NULL }, - { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", NULL }, + { SIG_SCIALL, 10, MAP_CALL(GraphFillBoxForeground), "iiii", kGraphFillBoxForeground_workarounds }, { SIG_SCIALL, 11, MAP_CALL(GraphFillBoxAny), "iiiiii(i)(i)", kGraphFillBoxAny_workarounds }, { SIG_SCI11, 12, MAP_CALL(GraphUpdateBox), "iiii(i)(r0)", NULL }, // kq6 hires { SIG_SCIALL, 12, MAP_CALL(GraphUpdateBox), "iiii(i)", NULL }, -- cgit v1.2.3 From 8364b0bd29ddcf68cfc9ee53d09eb326703347e9 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 17:50:36 +0000 Subject: SCI: adding kUnLoad workaround for lsl6 (during end kUnLoad is called with additional 4 parameters, someone thought the API would work differently) svn-id: r50826 --- engines/sci/engine/kernel.cpp | 1 + 1 file changed, 1 insertion(+) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 892e64a0e1..6eedc06023 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -286,6 +286,7 @@ static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kUnLoad_workarounds[] = { { GID_LSL6, 130, 0, "recruitLarryScr", "changeState", -1, 0, { 1, 0 } }, // during intro, a 3rd parameter is passed by accident + { GID_LSL6, 740, 0, "showCartoon", "changeState", -1, 0, { 1, 0 } }, // during end, intro, a 4 additional parameters are passed by accident { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 535dbb7f59afe1c0d4576ada41c73cf07632b133 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 18:22:24 +0000 Subject: SCI: fixing typo svn-id: r50827 --- engines/sci/engine/kernel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'engines') diff --git a/engines/sci/engine/kernel.cpp b/engines/sci/engine/kernel.cpp index 6eedc06023..beb1d3ce35 100644 --- a/engines/sci/engine/kernel.cpp +++ b/engines/sci/engine/kernel.cpp @@ -286,7 +286,7 @@ static const SciWorkaroundEntry kGraphFillBoxAny_workarounds[] = { // gameID, scriptNr,lvl, object-name, method-name, call, index, replace static const SciWorkaroundEntry kUnLoad_workarounds[] = { { GID_LSL6, 130, 0, "recruitLarryScr", "changeState", -1, 0, { 1, 0 } }, // during intro, a 3rd parameter is passed by accident - { GID_LSL6, 740, 0, "showCartoon", "changeState", -1, 0, { 1, 0 } }, // during end, intro, a 4 additional parameters are passed by accident + { GID_LSL6, 740, 0, "showCartoon", "changeState", -1, 0, { 1, 0 } }, // during ending, 4 additional parameters are passed by accident { GID_SQ1, 303, 0, "slotGuy", "dispose", -1, 0, { 1, 0 } }, // when leaving ulence flats bar, parameter 1 is not passed - script error SCI_WORKAROUNDENTRY_TERMINATOR }; -- cgit v1.2.3 From 0c42441426a6ade7cf659847dbffb24a63780de8 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 19:41:26 +0000 Subject: SCI: added TODO for saved games svn-id: r50828 --- engines/sci/engine/kfile.cpp | 3 +++ 1 file changed, 3 insertions(+) (limited to 'engines') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 69b80ce7ce..1b9b55c5c8 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -438,6 +438,9 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 1); } +// TODO: we need NOT to assign our own ids to saved-games, but use the filename-id and pass that to the scripts +// LSL6 is using the last used saved-game-id for quicksaving and this won't match correctly otherwise + reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); uint16 savedir_nr = argv[1].toUint16(); -- cgit v1.2.3 From d52a872724d779b12385aab2925a6b8b7bfcedb4 Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 19:55:42 +0000 Subject: SCI: changing gameid of lsl6 sci2.1 into "lsl6hires". We need to keep workarounds etc. separate, scripts are not compatible svn-id: r50829 --- engines/sci/detection.cpp | 2 ++ engines/sci/detection_tables.h | 6 +++--- engines/sci/sci.h | 1 + 3 files changed, 6 insertions(+), 3 deletions(-) (limited to 'engines') diff --git a/engines/sci/detection.cpp b/engines/sci/detection.cpp index 0932cb3fdc..eb2c989e0d 100644 --- a/engines/sci/detection.cpp +++ b/engines/sci/detection.cpp @@ -105,6 +105,7 @@ static const PlainGameDescriptor s_sciGameTitles[] = { // TODO: Inside The Chest/Behind the Developer's Shield {"kq7", "King's Quest VII: The Princeless Bride"}, // TODO: King's Questions + {"lsl6hires", "Leisure Suit Larry 6: Shape Up or Slip Out!"}, {"phantasmagoria", "Phantasmagoria"}, {"pqswat", "Police Quest: SWAT"}, {"shivers", "Shivers"}, @@ -164,6 +165,7 @@ static const GameIdStrToEnum s_gameIdStrToEnum[] = { { "lsl3", GID_LSL3 }, { "lsl5", GID_LSL5 }, { "lsl6", GID_LSL6 }, + { "lsl6hires", GID_LSL6HIRES }, { "lsl7", GID_LSL7 }, { "mothergoose", GID_MOTHERGOOSE }, { "msastrochicken", GID_MSASTROCHICKEN }, diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index e761b64991..aa1e26e0f4 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1684,7 +1684,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { #ifdef ENABLE_SCI32 // Larry 6 - English/German DOS CD - HIRES // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "0c0804434ea62278dd15032b1947426c", 8872}, {"resource.000", 0, "9a9f4870504444cda863dd14d077a680", 18520872}, {NULL, 0, NULL, 0}}, @@ -1692,7 +1692,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { // Larry 6 - German DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "badfdf446ffed569a310d2c63a249421", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18534274}, {NULL, 0, NULL, 0}}, @@ -1700,7 +1700,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { // Larry 6 - French DOS CD - HIRES (provided by richiefs in bug report #2670691) // SCI interpreter version 2.100.002 - {"lsl6", "", { + {"lsl6hires", "", { {"resource.map", 0, "d184e9aa4f2d4b5670ddb3669db82cda", 8896}, {"resource.000", 0, "bd944d2b06614a5b39f1586906f0ee88", 18538987}, {NULL, 0, NULL, 0}}, diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 8f7205ea7a..4ba6755967 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -139,6 +139,7 @@ enum SciGameId { GID_LSL3, GID_LSL5, GID_LSL6, + GID_LSL6HIRES, // We have a separate ID for LSL6 SCI32, because it's actually a completely different game GID_LSL7, GID_MOTHERGOOSE, GID_MSASTROCHICKEN, -- cgit v1.2.3 From 6ff4dd2d91d5fe05495bec81a91e5c40ccd9b8be Mon Sep 17 00:00:00 2001 From: Martin Kiewitz Date: Mon, 12 Jul 2010 22:26:48 +0000 Subject: SCI: changing how savegame ids are handled internally. Using range 0-999 so that scripts are able to signal us to create new slots, using range 1000-1999 for official slots. fixes lsl6 quicksave overwriting wrong save slots svn-id: r50831 --- engines/sci/engine/kfile.cpp | 285 ++++++++++++++++++++++++------------------- engines/sci/engine/state.cpp | 3 + engines/sci/engine/state.h | 14 +++ engines/sci/engine/vm.cpp | 4 +- 4 files changed, 178 insertions(+), 128 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index 1b9b55c5c8..807edc63a5 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -36,12 +36,9 @@ namespace Sci { -enum { - MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ -}; - struct SavegameDesc { - int id; + uint id; + int virtualId; // straight numbered, according to id but w/o gaps int date; int time; int version; @@ -249,66 +246,6 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { debugC(2, kDebugLevelFile, " -> FGets'ed \"%s\"", dest); } -static bool _savegame_index_struct_compare(const SavegameDesc &l, const SavegameDesc &r) { - if (l.date != r.date) - return (l.date > r.date); - return (l.time > r.time); -} - -void listSavegames(Common::Array &saves) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - - // Load all saves - Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); - - for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { - Common::String filename = *iter; - Common::SeekableReadStream *in; - if ((in = saveFileMan->openForLoading(filename))) { - SavegameMetadata meta; - if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) { - // invalid - delete in; - continue; - } - delete in; - - SavegameDesc desc; - desc.id = strtol(filename.end() - 3, NULL, 10); - desc.date = meta.savegame_date; - // We need to fix date in here, because we save DDMMYYYY instead of - // YYYYMMDD, so sorting wouldn't work - desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); - desc.time = meta.savegame_time; - desc.version = meta.savegame_version; - - if (meta.savegame_name.lastChar() == '\n') - meta.savegame_name.deleteLastChar(); - - Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH); - - debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); - - saves.push_back(desc); - } - } - - // Sort the list by creation date of the saves - Common::sort(saves.begin(), saves.end(), _savegame_index_struct_compare); -} - -bool Console::cmdListSaves(int argc, const char **argv) { - Common::Array saves; - listSavegames(saves); - - for (uint i = 0; i < saves.size(); i++) { - Common::String filename = g_sci->getSavegameName(saves[i].id); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); - } - - return true; -} - reg_t kFGets(EngineState *s, int argc, reg_t *argv) { int maxsize = argv[1].toUint16(); char *buf = new char[maxsize]; @@ -334,6 +271,9 @@ reg_t kGetCWD(EngineState *s, int argc, reg_t *argv) { return argv[0]; } +static void listSavegames(Common::Array &saves); +static int findSavegame(Common::Array &saves, uint saveId); + enum { K_DEVICE_INFO_GET_DEVICE = 0, K_DEVICE_INFO_GET_CURRENT_DEVICE = 1, @@ -392,17 +332,22 @@ reg_t kDeviceInfo(EngineState *s, int argc, reg_t *argv) { break; case K_DEVICE_INFO_GET_SAVEFILE_NAME: { Common::String game_prefix = s->_segMan->getString(argv[2]); - int savegame_id = argv[3].toUint16(); + uint virtualId = argv[3].toUint16(); s->_segMan->strcpy(argv[1], "__throwaway"); - debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), savegame_id, "__throwaway"); + debug(3, "K_DEVICE_INFO_GET_SAVEFILE_NAME(%s,%d) -> %s", game_prefix.c_str(), virtualId, "__throwaway"); + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kDeviceInfo(deleteSave): invalid savegame-id specified"); + uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; Common::Array saves; listSavegames(saves); - int savedir_nr = saves[savegame_id].id; - Common::String filename = g_sci->getSavegameName(savedir_nr); - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - saveFileMan->removeSavefile(filename); + if (findSavegame(saves, savegameId) != -1) { + // Confirmed that this id still lives... + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + saveFileMan->removeSavefile(filename); } break; + } default: error("Unknown DeviceInfo() sub-command: %d", mode); @@ -438,24 +383,102 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { return make_reg(0, 1); } -// TODO: we need NOT to assign our own ids to saved-games, but use the filename-id and pass that to the scripts -// LSL6 is using the last used saved-game-id for quicksaving and this won't match correctly otherwise +static bool _savegame_sort_byDate(const SavegameDesc &l, const SavegameDesc &r) { + if (l.date != r.date) + return (l.date > r.date); + return (l.time > r.time); +} + +// Create a sorted array containing all found savedgames +static void listSavegames(Common::Array &saves) { + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + + // Load all saves + Common::StringArray saveNames = saveFileMan->listSavefiles(g_sci->getSavegamePattern()); + + for (Common::StringArray::const_iterator iter = saveNames.begin(); iter != saveNames.end(); ++iter) { + Common::String filename = *iter; + Common::SeekableReadStream *in; + if ((in = saveFileMan->openForLoading(filename))) { + SavegameMetadata meta; + if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) { + // invalid + delete in; + continue; + } + delete in; + + SavegameDesc desc; + desc.id = strtol(filename.end() - 3, NULL, 10); + desc.date = meta.savegame_date; + // We need to fix date in here, because we save DDMMYYYY instead of + // YYYYMMDD, so sorting wouldn't work + desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24); + desc.time = meta.savegame_time; + desc.version = meta.savegame_version; + + if (meta.savegame_name.lastChar() == '\n') + meta.savegame_name.deleteLastChar(); + + Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH); + + debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id); + + saves.push_back(desc); + } + } + + // Sort the list by creation date of the saves + Common::sort(saves.begin(), saves.end(), _savegame_sort_byDate); +} + +// Find a savedgame according to virtualId and return the position within our array +static int findSavegame(Common::Array &saves, uint savegameId) { + for (uint saveNr = 0; saveNr < saves.size(); saveNr++) { + if (saves[saveNr].id == savegameId) + return saveNr; + } + return -1; +} + +// The scripts get IDs ranging from 1000->1999, because the scripts require us to assign unique ids THAT EVEN STAY BETWEEN +// SAVES and the scripts also use "saves-count + 1" to create a new savedgame slot. +// SCI1.1 actually recycles ids, in that case we will currently get "0". +// This behaviour is required especially for LSL6. In this game, it's possible to quick save. The scripts will use +// the last-used id for that feature. If we don't assign sticky ids, the feature will overwrite different saves all the +// time. And sadly we can't just use the actual filename ids directly, because of the creation method for new slots. + +bool Console::cmdListSaves(int argc, const char **argv) { + Common::Array saves; + listSavegames(saves); + + for (uint i = 0; i < saves.size(); i++) { + Common::String filename = g_sci->getSavegameName(saves[i].id); + DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); + } + + return true; +} reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); - uint16 savedir_nr = argv[1].toUint16(); + uint16 virtualId = argv[1].toUint16(); - debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr); + debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), virtualId); Common::Array saves; listSavegames(saves); - // Check for savegame slot being out of range - if (savedir_nr >= saves.size()) + // Find saved-game + if ((virtualId < SAVEGAMEID_OFFICIALRANGE_START) || (virtualId > SAVEGAMEID_OFFICIALRANGE_END)) + error("kCheckSaveGame: called with invalid savegameId!"); + uint savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + int savegameNr = findSavegame(saves, savegameId); + if (savegameNr == -1) return NULL_REG; // Check for compatible savegame version - int ver = saves[savedir_nr].version; + int ver = saves[savegameNr].version; if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION) return NULL_REG; @@ -468,9 +491,12 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { debug(3, "kGetSaveFiles(%s)", game_id.c_str()); + // Scripts ask for current save files, we can assume that if afterwards they ask us to create a new slot they really + // mean new slot instead of overwriting the old one + s->_lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; + Common::Array saves; listSavegames(saves); - uint totalSaves = MIN(saves.size(), MAX_SAVEGAME_NR); reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves); @@ -485,7 +511,7 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { char *saveNamePtr = saveNames; for (uint i = 0; i < totalSaves; i++) { - *slot++ = make_reg(0, i); // Store slot + *slot++ = make_reg(0, saves[i].id + SAVEGAMEID_OFFICIALRANGE_START); // Store the virtual savegame-id ffs. see above strcpy(saveNamePtr, saves[i].name); saveNamePtr += SCI_MAX_SAVENAME_LENGTH; } @@ -500,46 +526,51 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = s->_segMan->getString(argv[0]); - int savedir_nr = argv[1].toUint16(); - int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list + uint virtualId = argv[1].toUint16(); Common::String game_description = s->_segMan->getString(argv[2]); Common::String version; if (argc > 3) version = s->_segMan->getString(argv[3]); - debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), savedir_nr, game_description.c_str(), version.c_str()); + debug(3, "kSaveGame(%s,%d,%s,%s)", game_id.c_str(), virtualId, game_description.c_str(), version.c_str()); Common::Array saves; listSavegames(saves); - if (savedir_nr >= 0 && (uint)savedir_nr < saves.size()) { - // Overwrite - savedir_id = saves[savedir_nr].id; - } else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) { - uint i = 0; - - savedir_id = 0; - - // First, look for holes - while (i < saves.size()) { - if (saves[i].id == savedir_id) { - ++savedir_id; - i = 0; - } else - ++i; - } - if (savedir_id >= MAX_SAVEGAME_NR) { - warning("Internal error: Free savegame ID is %d, shouldn't happen", savedir_id); + uint savegameId; + if ((virtualId >= SAVEGAMEID_OFFICIALRANGE_START) && (virtualId <= SAVEGAMEID_OFFICIALRANGE_END)) { + // savegameId is an actual Id, so search for it just to make sure + savegameId = virtualId - SAVEGAMEID_OFFICIALRANGE_START; + if (findSavegame(saves, savegameId) != -1) return NULL_REG; + } else if (virtualId < SAVEGAMEID_OFFICIALRANGE_START) { + // virtualId is low, we assume that scripts expect us to create new slot + if (virtualId == s->_lastSaveVirtualId) { + // if last virtual id is the same as this one, we assume that caller wants to overwrite last save + savegameId = s->_lastSaveNewId; + } else { + uint savegameNr; + // savegameId is in lower range, scripts expect us to create a new slot + for (savegameId = 0; savegameId < SAVEGAMEID_OFFICIALRANGE_START; savegameId++) { + for (savegameNr = 0; savegameNr < saves.size(); savegameNr++) { + if (savegameId == saves[savegameNr].id) + break; + } + if (savegameNr == saves.size()) + break; + } + if (savegameId == SAVEGAMEID_OFFICIALRANGE_START) + error("kSavegame: no more savegame slots available"); } - - // This loop terminates when savedir_id is not in [x | ex. n. saves [n].id = x] } else { - warning("Savegame ID %d is not allowed", savedir_nr); - return NULL_REG; + error("kSaveGame: invalid savegameId used"); } - Common::String filename = g_sci->getSavegameName(savedir_id); + // Save in case caller wants to overwrite last newly created save + s->_lastSaveVirtualId = virtualId; + s->_lastSaveNewId = savegameId; + + Common::String filename = g_sci->getSavegameName(savegameId); Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); Common::OutSaveFile *out; if (!(out = saveFileMan->openForSaving(filename))) { @@ -568,35 +599,37 @@ reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) { reg_t kRestoreGame(EngineState *s, int argc, reg_t *argv) { Common::String game_id = !argv[0].isNull() ? s->_segMan->getString(argv[0]) : ""; - int savedir_nr = argv[1].toUint16(); + uint savegameId = argv[1].toUint16(); - debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savedir_nr); + debug(3, "kRestoreGame(%s,%d)", game_id.c_str(), savegameId); - if (!argv[0].isNull()) { - Common::Array saves; - listSavegames(saves); + if ((savegameId < 1000) || (savegameId > 1999)) { + warning("Savegame ID %d is not allowed", savegameId); + return TRUE_REG; + } + savegameId -= 1000; - savedir_nr = saves[savedir_nr].id; - } else { - // Loading from launcher, no change necessary + Common::Array saves; + listSavegames(saves); + if (findSavegame(saves, savegameId) == -1) { + warning("Savegame ID %d not found", savegameId); + return TRUE_REG; } - if (savedir_nr > -1) { - Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); - Common::String filename = g_sci->getSavegameName(savedir_nr); - Common::SeekableReadStream *in; - if ((in = saveFileMan->openForLoading(filename))) { - // found a savegame file + Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager(); + Common::String filename = g_sci->getSavegameName(savegameId); + Common::SeekableReadStream *in; + if ((in = saveFileMan->openForLoading(filename))) { + // found a savegame file - gamestate_restore(s, in); - delete in; + gamestate_restore(s, in); + delete in; - return s->r_acc; - } + return s->r_acc; } - s->r_acc = make_reg(0, 1); - warning("Savegame #%d not found", savedir_nr); + s->r_acc = TRUE_REG; + warning("Savegame #%d not found", savegameId); return s->r_acc; } diff --git a/engines/sci/engine/state.cpp b/engines/sci/engine/state.cpp index 245a021605..36b03c0ad9 100644 --- a/engines/sci/engine/state.cpp +++ b/engines/sci/engine/state.cpp @@ -107,6 +107,9 @@ void EngineState::reset(bool isRestoring) { _throttleLastTime = 0; _throttleTrigger = false; + _lastSaveVirtualId = SAVEGAMEID_OFFICIALRANGE_START; + _lastSaveNewId = 0; + scriptStepCounter = 0; scriptGCInterval = GC_INTERVAL; } diff --git a/engines/sci/engine/state.h b/engines/sci/engine/state.h index e304c6d889..243a460645 100644 --- a/engines/sci/engine/state.h +++ b/engines/sci/engine/state.h @@ -76,6 +76,17 @@ enum { MAX_SAVE_DIR_SIZE = MAXPATHLEN }; +enum { + MAX_SAVEGAME_NR = 20 /**< Maximum number of savegames */ +}; + +// We assume that scripts give us savegameId 0->999 for creating a new save slot +// and savegameId 1000->1999 for existing save slots ffs. kfile.cpp +enum { + SAVEGAMEID_OFFICIALRANGE_START = 1000, + SAVEGAMEID_OFFICIALRANGE_END = 1999 +}; + class FileHandle { public: Common::String _name; @@ -119,6 +130,9 @@ public: DirSeeker _dirseeker; + uint _lastSaveVirtualId; // last virtual id fed to kSaveGame, if no kGetSaveFiles was called inbetween + uint _lastSaveNewId; // last newly created filename-id by kSaveGame + public: /* VM Information */ diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 42f7424bf9..d0dd5b6ad3 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -355,8 +355,8 @@ static const SciWorkaroundEntry uninitializedReadWorkarounds[] = { { GID_KQ5, 0, 0, "", "export 29", -1, 3, { 0, 0 } }, // called when playing harp for the harpies, is used for kDoAudio { GID_KQ5, 25, 0, "rm025", "doit", -1, 0, { 0, 0 } }, // inside witch forest, where the walking rock is { GID_KQ6, 903, 0, "controlWin", "open", -1, 4, { 0, 0 } }, // when opening the controls window (save, load etc) - { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast - { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle + { GID_KQ6, 500, 0, "rm500", "init", -1, 0, { 0, 0 } }, // going to island of the beast + { GID_KQ6, 520, 0, "rm520", "init", -1, 0, { 0, 0 } }, // going to boiling water trap on beast isle { GID_KQ6, 30, 0, "rats", "changeState", -1, 0, { 0, 0 } }, // rats in the catacombs { GID_LSL6, 85, 0, "washcloth", "doVerb", -1, 0, { 0, 0 } }, // washcloth in inventory { GID_SQ1, 703, 0, "", "export 1", -1, 0, { 0, 0 } }, // sub that's called from several objects while on sarien battle cruiser -- cgit v1.2.3 From 4f914e7a9f1379f06749b1f01fa83b8464c13d7f Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 12 Jul 2010 23:19:33 +0000 Subject: TINSEL: Replace global object s_rectList by a TinselEngine member var svn-id: r50834 --- engines/tinsel/cliprect.cpp | 12 ++++++------ engines/tinsel/tinsel.h | 6 ++++++ 2 files changed, 12 insertions(+), 6 deletions(-) (limited to 'engines') diff --git a/engines/tinsel/cliprect.cpp b/engines/tinsel/cliprect.cpp index 69a71b874f..5f287d3eab 100644 --- a/engines/tinsel/cliprect.cpp +++ b/engines/tinsel/cliprect.cpp @@ -28,17 +28,15 @@ #include "tinsel/graphics.h" // normal object drawing #include "tinsel/object.h" #include "tinsel/palette.h" +#include "tinsel/tinsel.h" // for _vm namespace Tinsel { -/** list of all clip rectangles */ -static RectList s_rectList; - /** * Resets the clipping rectangle allocator. */ void ResetClipRect() { - s_rectList.clear(); + _vm->_clipRects.clear(); } /** @@ -46,11 +44,11 @@ void ResetClipRect() { * @param pClip clip rectangle dimensions to allocate */ void AddClipRect(const Common::Rect &pClip) { - s_rectList.push_back(pClip); + _vm->_clipRects.push_back(pClip); } const RectList &GetClipRects() { - return s_rectList; + return _vm->_clipRects; } /** @@ -175,6 +173,8 @@ void FindMovingObjects(OBJECT *pObjList, Common::Point *pWin, Common::Rect *pCli * the total number of clip rectangles. */ void MergeClipRect() { + RectList &s_rectList = _vm->_clipRects; + if (s_rectList.size() <= 1) return; diff --git a/engines/tinsel/tinsel.h b/engines/tinsel/tinsel.h index 0e1d705815..df27a1e0e1 100644 --- a/engines/tinsel/tinsel.h +++ b/engines/tinsel/tinsel.h @@ -61,6 +61,8 @@ class PCMMusicPlayer; class Scheduler; class SoundManager; +typedef Common::List RectList; + enum TinselGameID { GID_DW1 = 0, GID_DW2 = 1 @@ -203,6 +205,10 @@ public: /** Stack of pending keypresses. */ Common::List _keypresses; + + /** List of all clip rectangles. */ + RectList _clipRects; + private: //MidiMusicPlayer *_midiMusic; int _musicVolume; -- cgit v1.2.3 From 1d3a0f6decd54b017d2ca55a95048de4afdbd868 Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 12 Jul 2010 23:20:33 +0000 Subject: SCI: Turn global object g_debugState into SciEngine member var svn-id: r50836 --- engines/sci/console.cpp | 86 +++++++++++++++++++------------------- engines/sci/console.h | 1 + engines/sci/debug.h | 3 +- engines/sci/engine/kevent.cpp | 8 ++-- engines/sci/engine/kmisc.cpp | 4 +- engines/sci/engine/scriptdebug.cpp | 43 ++++++++++--------- engines/sci/engine/vm.cpp | 27 ++++++------ engines/sci/sci.cpp | 8 ++-- engines/sci/sci.h | 7 +++- 9 files changed, 95 insertions(+), 92 deletions(-) (limited to 'engines') diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index 3151691900..33aa5514f2 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -66,8 +66,8 @@ bool g_debug_track_mouse_clicks = false; // Refer to the "addresses" command on how to pass address parameters static int parse_reg_t(EngineState *s, const char *str, reg_t *dest, bool mayBeValue); -Console::Console(SciEngine *engine) : GUI::Debugger() { - _engine = engine; +Console::Console(SciEngine *engine) : GUI::Debugger(), + _engine(engine), _debugState(engine->_debugState) { // Variables DVar_Register("sleeptime_factor", &g_debug_sleeptime_factor, DVAR_INT, 0); @@ -196,14 +196,14 @@ Console::Console(SciEngine *engine) : GUI::Debugger() { DCmd_Register("active_object", WRAP_METHOD(Console, cmdViewActiveObject)); DCmd_Register("acc_object", WRAP_METHOD(Console, cmdViewAccumulatorObject)); - g_debugState.seeking = kDebugSeekNothing; - g_debugState.seekLevel = 0; - g_debugState.runningStep = 0; - g_debugState.stopOnEvent = false; - g_debugState.debugging = false; - g_debugState.breakpointWasHit = false; - g_debugState._breakpoints.clear(); // No breakpoints defined - g_debugState._activeBreakpointTypes = 0; + _debugState.seeking = kDebugSeekNothing; + _debugState.seekLevel = 0; + _debugState.runningStep = 0; + _debugState.stopOnEvent = false; + _debugState.debugging = false; + _debugState.breakpointWasHit = false; + _debugState._breakpoints.clear(); // No breakpoints defined + _debugState._activeBreakpointTypes = 0; } Console::~Console() { @@ -2307,31 +2307,31 @@ bool Console::cmdBacktrace(int argc, const char **argv) { bool Console::cmdTrace(int argc, const char **argv) { if (argc == 2 && atoi(argv[1]) > 0) - g_debugState.runningStep = atoi(argv[1]) - 1; - g_debugState.debugging = true; + _debugState.runningStep = atoi(argv[1]) - 1; + _debugState.debugging = true; return false; } bool Console::cmdStepOver(int argc, const char **argv) { - g_debugState.seeking = kDebugSeekStepOver; - g_debugState.seekLevel = _engine->_gamestate->_executionStack.size(); - g_debugState.debugging = true; + _debugState.seeking = kDebugSeekStepOver; + _debugState.seekLevel = _engine->_gamestate->_executionStack.size(); + _debugState.debugging = true; return false; } bool Console::cmdStepEvent(int argc, const char **argv) { - g_debugState.stopOnEvent = true; - g_debugState.debugging = true; + _debugState.stopOnEvent = true; + _debugState.debugging = true; return false; } bool Console::cmdStepRet(int argc, const char **argv) { - g_debugState.seeking = kDebugSeekLevelRet; - g_debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; - g_debugState.debugging = true; + _debugState.seeking = kDebugSeekLevelRet; + _debugState.seekLevel = _engine->_gamestate->_executionStack.size() - 1; + _debugState.debugging = true; return false; } @@ -2343,9 +2343,9 @@ bool Console::cmdStepGlobal(int argc, const char **argv) { return true; } - g_debugState.seeking = kDebugSeekGlobal; - g_debugState.seekSpecial = atoi(argv[1]); - g_debugState.debugging = true; + _debugState.seeking = kDebugSeekGlobal; + _debugState.seekSpecial = atoi(argv[1]); + _debugState.debugging = true; return false; } @@ -2373,12 +2373,12 @@ bool Console::cmdStepCallk(int argc, const char **argv) { } } - g_debugState.seeking = kDebugSeekSpecialCallk; - g_debugState.seekSpecial = callk_index; + _debugState.seeking = kDebugSeekSpecialCallk; + _debugState.seekSpecial = callk_index; } else { - g_debugState.seeking = kDebugSeekCallk; + _debugState.seeking = kDebugSeekCallk; } - g_debugState.debugging = true; + _debugState.debugging = true; return false; } @@ -2560,7 +2560,7 @@ bool Console::cmdSend(int argc, const char **argv) { bool Console::cmdGo(int argc, const char **argv) { // CHECKME: is this necessary? - g_debugState.seeking = kDebugSeekNothing; + _debugState.seeking = kDebugSeekNothing; return Cmd_Exit(argc, argv); } @@ -2571,8 +2571,8 @@ bool Console::cmdBreakpointList(int argc, const char **argv) { DebugPrintf("Breakpoint list:\n"); - Common::List::const_iterator bp = g_debugState._breakpoints.begin(); - Common::List::const_iterator end = g_debugState._breakpoints.end(); + Common::List::const_iterator bp = _debugState._breakpoints.begin(); + Common::List::const_iterator end = _debugState._breakpoints.end(); for (; bp != end; ++bp) { DebugPrintf(" #%i: ", i); switch (bp->type) { @@ -2603,16 +2603,16 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } if (strcmp(argv[1], "*") == 0) { - g_debugState._breakpoints.clear(); - g_debugState._activeBreakpointTypes = 0; + _debugState._breakpoints.clear(); + _debugState._activeBreakpointTypes = 0; return true; } const int idx = atoi(argv[1]); // Find the breakpoint at index idx. - Common::List::iterator bp = g_debugState._breakpoints.begin(); - const Common::List::iterator end = g_debugState._breakpoints.end(); + Common::List::iterator bp = _debugState._breakpoints.begin(); + const Common::List::iterator end = _debugState._breakpoints.end(); for (int i = 0; bp != end && i < idx; ++bp, ++i) { // do nothing } @@ -2623,15 +2623,15 @@ bool Console::cmdBreakpointDelete(int argc, const char **argv) { } // Delete it - g_debugState._breakpoints.erase(bp); + _debugState._breakpoints.erase(bp); // Update EngineState::_activeBreakpointTypes. int type = 0; - for (bp = g_debugState._breakpoints.begin(); bp != end; ++bp) { + for (bp = _debugState._breakpoints.begin(); bp != end; ++bp) { type |= bp->type; } - g_debugState._activeBreakpointTypes = type; + _debugState._activeBreakpointTypes = type; return true; } @@ -2653,8 +2653,8 @@ bool Console::cmdBreakpointExecMethod(int argc, const char **argv) { bp.type = BREAK_SELECTOR; bp.name = argv[1]; - g_debugState._breakpoints.push_back(bp); - g_debugState._activeBreakpointTypes |= BREAK_SELECTOR; + _debugState._breakpoints.push_back(bp); + _debugState._activeBreakpointTypes |= BREAK_SELECTOR; return true; } @@ -2674,8 +2674,8 @@ bool Console::cmdBreakpointExecFunction(int argc, const char **argv) { bp.type = BREAK_EXPORT; bp.address = (atoi(argv[1]) << 16 | atoi(argv[2])); - g_debugState._breakpoints.push_back(bp); - g_debugState._activeBreakpointTypes |= BREAK_EXPORT; + _debugState._breakpoints.push_back(bp); + _debugState._activeBreakpointTypes |= BREAK_EXPORT; return true; } @@ -2876,8 +2876,8 @@ bool Console::cmdQuit(int argc, const char **argv) { if (!scumm_stricmp(argv[1], "game")) { // Quit gracefully _engine->_gamestate->abortScriptProcessing = kAbortQuitGame; // Terminate VM - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; + _debugState.seeking = kDebugSeekNothing; + _debugState.runningStep = 0; } else if (!scumm_stricmp(argv[1], "now")) { // Quit ungracefully diff --git a/engines/sci/console.h b/engines/sci/console.h index 95947a00f3..51f02d7168 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -157,6 +157,7 @@ private: private: SciEngine *_engine; + DebugState &_debugState; bool _mouseVisible; Common::String _videoFile; int _videoFrameDelay; diff --git a/engines/sci/debug.h b/engines/sci/debug.h index d381e55dc8..5cf0e38fbc 100644 --- a/engines/sci/debug.h +++ b/engines/sci/debug.h @@ -26,8 +26,8 @@ #ifndef SCI_DEBUG_H #define SCI_DEBUG_H +#include "common/list.h" #include "sci/engine/vm_types.h" // for StackPtr -#include "sci/engine/vm.h" // for ExecStack namespace Sci { @@ -79,7 +79,6 @@ struct DebugState { extern int g_debug_sleeptime_factor; extern int g_debug_simulated_key; extern bool g_debug_track_mouse_clicks; -extern DebugState g_debugState; } // End of namespace Sci diff --git a/engines/sci/engine/kevent.cpp b/engines/sci/engine/kevent.cpp index 4086d14a25..7547ad5ab6 100644 --- a/engines/sci/engine/kevent.cpp +++ b/engines/sci/engine/kevent.cpp @@ -78,8 +78,8 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { switch (curEvent.type) { case SCI_EVENT_QUIT: s->abortScriptProcessing = kAbortQuitGame; // Terminate VM - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; + g_sci->_debugState.seeking = kDebugSeekNothing; + g_sci->_debugState.runningStep = 0; break; case SCI_EVENT_KEYBOARD: @@ -124,8 +124,8 @@ reg_t kGetEvent(EngineState *s, int argc, reg_t *argv) { s->r_acc = NULL_REG; // Unknown or no event } - if ((s->r_acc.offset) && (g_debugState.stopOnEvent)) { - g_debugState.stopOnEvent = false; + if ((s->r_acc.offset) && (g_sci->_debugState.stopOnEvent)) { + g_sci->_debugState.stopOnEvent = false; // A SCI event occurred, and we have been asked to stop, so open the debug console Console *con = g_sci->getSciDebugger(); diff --git a/engines/sci/engine/kmisc.cpp b/engines/sci/engine/kmisc.cpp index 1ed12c092e..b8c62210f9 100644 --- a/engines/sci/engine/kmisc.cpp +++ b/engines/sci/engine/kmisc.cpp @@ -154,8 +154,8 @@ reg_t kFlushResources(EngineState *s, int argc, reg_t *argv) { reg_t kSetDebug(EngineState *s, int argc, reg_t *argv) { printf("Debug mode activated\n"); - g_debugState.seeking = kDebugSeekNothing; - g_debugState.runningStep = 0; + g_sci->_debugState.seeking = kDebugSeekNothing; + g_sci->_debugState.runningStep = 0; return s->r_acc; } diff --git a/engines/sci/engine/scriptdebug.cpp b/engines/sci/engine/scriptdebug.cpp index 4813e083fd..915a6fa994 100644 --- a/engines/sci/engine/scriptdebug.cpp +++ b/engines/sci/engine/scriptdebug.cpp @@ -63,8 +63,6 @@ const char *opcodeNames[] = { "-sli", "-sti", "-spi" }; -DebugState g_debugState; // FIXME: Avoid non-const global vars - // Disassembles one command from the heap, returns address of next command or 0 if a ret was encountered. reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecode) { SegmentObj *mobj = s->_segMan->getSegment(pos.segment, SEG_TYPE_SCRIPT); @@ -277,30 +275,32 @@ reg_t disassemble(EngineState *s, reg_t pos, int print_bw_tag, int print_bytecod } -void script_debug(EngineState *s) { - if (g_debugState.seeking && !g_debugState.breakpointWasHit) { // Are we looking for something special? - if (g_debugState.seeking == kDebugSeekStepOver) { +void SciEngine::scriptDebug() { + EngineState *s = _gamestate; + if (_debugState.seeking && !_debugState.breakpointWasHit) { // Are we looking for something special? + if (_debugState.seeking == kDebugSeekStepOver) { // are we above seek-level? resume then - if (g_debugState.seekLevel < (int)s->_executionStack.size()) + if (_debugState.seekLevel < (int)s->_executionStack.size()) return; - g_debugState.seeking = kDebugSeekNothing; + _debugState.seeking = kDebugSeekNothing; } - if (g_debugState.seeking != kDebugSeekNothing) { - SegmentObj *mobj = s->_segMan->getSegment(s->xs->addr.pc.segment, SEG_TYPE_SCRIPT); + if (_debugState.seeking != kDebugSeekNothing) { + const reg_t pc = s->xs->addr.pc; + SegmentObj *mobj = s->_segMan->getSegment(pc.segment, SEG_TYPE_SCRIPT); if (mobj) { Script *scr = (Script *)mobj; const byte *code_buf = scr->getBuf(); int code_buf_size = scr->getBufSize(); - int opcode = s->xs->addr.pc.offset >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset]; + int opcode = pc.offset >= code_buf_size ? 0 : code_buf[pc.offset]; int op = opcode >> 1; - int paramb1 = s->xs->addr.pc.offset + 1 >= code_buf_size ? 0 : code_buf[s->xs->addr.pc.offset + 1]; - int paramf1 = (opcode & 1) ? paramb1 : (s->xs->addr.pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + s->xs->addr.pc.offset + 1)); + int paramb1 = pc.offset + 1 >= code_buf_size ? 0 : code_buf[pc.offset + 1]; + int paramf1 = (opcode & 1) ? paramb1 : (pc.offset + 2 >= code_buf_size ? 0 : (int16)READ_SCI11ENDIAN_UINT16(code_buf + pc.offset + 1)); - switch (g_debugState.seeking) { + switch (_debugState.seeking) { case kDebugSeekSpecialCallk: - if (paramb1 != g_debugState.seekSpecial) + if (paramb1 != _debugState.seekSpecial) return; case kDebugSeekCallk: @@ -309,7 +309,7 @@ void script_debug(EngineState *s) { break; case kDebugSeekLevelRet: - if ((op != op_ret) || (g_debugState.seekLevel < (int)s->_executionStack.size()-1)) + if ((op != op_ret) || (_debugState.seekLevel < (int)s->_executionStack.size()-1)) return; break; @@ -320,7 +320,7 @@ void script_debug(EngineState *s) { return; // param or temp if ((op & 0x3) && s->_executionStack.back().local_segment > 0) return; // locals and not running in script.000 - if (paramf1 != g_debugState.seekSpecial) + if (paramf1 != _debugState.seekSpecial) return; // CORRECT global? break; @@ -328,7 +328,7 @@ void script_debug(EngineState *s) { break; } - g_debugState.seeking = kDebugSeekNothing; + _debugState.seeking = kDebugSeekNothing; } } // OK, found whatever we were looking for @@ -337,15 +337,14 @@ void script_debug(EngineState *s) { printf("Step #%d\n", s->scriptStepCounter); disassemble(s, s->xs->addr.pc, 0, 1); - if (g_debugState.runningStep) { - g_debugState.runningStep--; + if (_debugState.runningStep) { + _debugState.runningStep--; return; } - g_debugState.debugging = false; + _debugState.debugging = false; - Console *con = ((Sci::SciEngine *)g_engine)->getSciDebugger(); - con->attach(); + _console->attach(); } void Kernel::dumpScriptObject(char *data, int seeker, int objsize) { diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index d0dd5b6ad3..57c02f8c36 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -30,7 +30,6 @@ #include "sci/sci.h" #include "sci/console.h" -#include "sci/debug.h" // for g_debugState #include "sci/resource.h" #include "sci/engine/features.h" #include "sci/engine/state.h" @@ -474,18 +473,18 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } // Check if a breakpoint is set on this method - if (g_debugState._activeBreakpointTypes & BREAK_EXPORT) { + if (g_sci->_debugState._activeBreakpointTypes & BREAK_EXPORT) { uint32 bpaddress; bpaddress = (script << 16 | pubfunct); Common::List::const_iterator bp; - for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) { + for (bp = g_sci->_debugState._breakpoints.begin(); bp != g_sci->_debugState._breakpoints.end(); ++bp) { if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { Console *con = g_sci->getSciDebugger(); con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); - g_debugState.debugging = true; - g_debugState.breakpointWasHit = true; + g_sci->_debugState.debugging = true; + g_sci->_debugState.breakpointWasHit = true; break; } } @@ -553,13 +552,13 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } // Check if a breakpoint is set on this method - if (g_debugState._activeBreakpointTypes & BREAK_SELECTOR) { + if (g_sci->_debugState._activeBreakpointTypes & BREAK_SELECTOR) { char method_name[256]; sprintf(method_name, "%s::%s", s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str()); Common::List::const_iterator bp; - for (bp = g_debugState._breakpoints.begin(); bp != g_debugState._breakpoints.end(); ++bp) { + for (bp = g_sci->_debugState._breakpoints.begin(); bp != g_sci->_debugState._breakpoints.end(); ++bp) { int cmplen = bp->name.size(); if (bp->name.lastChar() != ':') cmplen = 256; @@ -568,8 +567,8 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt Console *con = g_sci->getSciDebugger(); con->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); printSendActions = true; - g_debugState.debugging = true; - g_debugState.breakpointWasHit = true; + g_sci->_debugState.debugging = true; + g_sci->_debugState.breakpointWasHit = true; break; } } @@ -1003,8 +1002,8 @@ void run_vm(EngineState *s, bool restoring) { int var_type; // See description below int var_number; - g_debugState.old_pc_offset = s->xs->addr.pc.offset; - g_debugState.old_sp = s->xs->sp; + g_sci->_debugState.old_pc_offset = s->xs->addr.pc.offset; + g_sci->_debugState.old_sp = s->xs->sp; if (s->abortScriptProcessing != kAbortNone || g_engine->shouldQuit()) return; // Stop processing @@ -1046,9 +1045,9 @@ void run_vm(EngineState *s, bool restoring) { // Debug if this has been requested: // TODO: re-implement sci_debug_flags - if (g_debugState.debugging /* sci_debug_flags*/) { - script_debug(s); - g_debugState.breakpointWasHit = false; + if (g_sci->_debugState.debugging /* sci_debug_flags*/) { + g_sci->scriptDebug(); + g_sci->_debugState.breakpointWasHit = false; } Console *con = g_sci->getSciDebugger(); if (con->isAttached()) { diff --git a/engines/sci/sci.cpp b/engines/sci/sci.cpp index ec8f697123..1ebc6a2ba3 100644 --- a/engines/sci/sci.cpp +++ b/engines/sci/sci.cpp @@ -448,12 +448,12 @@ void SciEngine::exitGame() { GUI::Debugger *SciEngine::getDebugger() { if (_gamestate) { ExecStack *xs = &(_gamestate->_executionStack.back()); - xs->addr.pc.offset = g_debugState.old_pc_offset; - xs->sp = g_debugState.old_sp; + xs->addr.pc.offset = _debugState.old_pc_offset; + xs->sp = _debugState.old_sp; } - g_debugState.runningStep = 0; // Stop multiple execution - g_debugState.seeking = kDebugSeekNothing; // Stop special seeks + _debugState.runningStep = 0; // Stop multiple execution + _debugState.seeking = kDebugSeekNothing; // Stop special seeks return _console; } diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 4ba6755967..74c48258ef 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -28,7 +28,8 @@ #include "engines/engine.h" #include "common/util.h" -#include "engine/vm_types.h" // for Selector +#include "sci/engine/vm_types.h" // for Selector +#include "sci/debug.h" // for DebugState struct ADGameDescription; @@ -243,6 +244,8 @@ public: void sleep(uint32 msecs); + void scriptDebug(); + public: /** @@ -290,6 +293,8 @@ public: SoundCommandParser *_soundCmd; GameFeatures *_features; + DebugState _debugState; + private: /** * Initializes a SCI game -- cgit v1.2.3 From 03c0faa5d76f547603ee6389cdf958e2a6f0f43d Mon Sep 17 00:00:00 2001 From: Max Horn Date: Mon, 12 Jul 2010 23:21:03 +0000 Subject: SCI: Move breakpoint checks into SciEngine methods svn-id: r50837 --- engines/sci/engine/vm.cpp | 83 ++++++++++++++++++++++++++--------------------- engines/sci/sci.h | 2 ++ 2 files changed, 48 insertions(+), 37 deletions(-) (limited to 'engines') diff --git a/engines/sci/engine/vm.cpp b/engines/sci/engine/vm.cpp index 57c02f8c36..8108440102 100644 --- a/engines/sci/engine/vm.cpp +++ b/engines/sci/engine/vm.cpp @@ -450,6 +450,26 @@ static void validate_write_var(reg_t *r, reg_t *stack_base, int type, int max, i #define PUSH32(a) (*(validate_stack_addr(s, (s->xs->sp)++)) = (a)) #define POP32() (*(validate_stack_addr(s, --(s->xs->sp)))) +bool SciEngine::checkExportBreakpoint(uint16 script, uint16 pubfunct) { + if (_debugState._activeBreakpointTypes & BREAK_EXPORT) { + uint32 bpaddress; + + bpaddress = (script << 16 | pubfunct); + + Common::List::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { + _console->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true;; + } + } + } + + return false; +} + ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackPtr sp, reg_t calling_obj, uint16 argc, StackPtr argp) { int seg = s->_segMan->getScriptSegment(script); Script *scr = s->_segMan->getScriptIfLoaded(seg); @@ -473,22 +493,7 @@ ExecStack *execute_method(EngineState *s, uint16 script, uint16 pubfunct, StackP } // Check if a breakpoint is set on this method - if (g_sci->_debugState._activeBreakpointTypes & BREAK_EXPORT) { - uint32 bpaddress; - - bpaddress = (script << 16 | pubfunct); - - Common::List::const_iterator bp; - for (bp = g_sci->_debugState._breakpoints.begin(); bp != g_sci->_debugState._breakpoints.end(); ++bp) { - if (bp->type == BREAK_EXPORT && bp->address == bpaddress) { - Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("Break on script %d, export %d\n", script, pubfunct); - g_sci->_debugState.debugging = true; - g_sci->_debugState.breakpointWasHit = true; - break; - } - } - } + g_sci->checkExportBreakpoint(script, pubfunct); return add_exec_stack_entry(s->_executionStack, make_reg(seg, temp), sp, calling_obj, argc, argp, -1, pubfunct, -1, calling_obj, s->_executionStack.size()-1, seg); } @@ -528,6 +533,30 @@ struct CallsStruct { int type; /**< Same as ExecStack.type */ }; +bool SciEngine::checkSelectorBreakpoint(reg_t send_obj, int selector) { + if (_debugState._activeBreakpointTypes & BREAK_SELECTOR) { + char method_name[256]; + + sprintf(method_name, "%s::%s", _gamestate->_segMan->getObjectName(send_obj), getKernel()->getSelectorName(selector).c_str()); + + Common::List::const_iterator bp; + for (bp = _debugState._breakpoints.begin(); bp != _debugState._breakpoints.end(); ++bp) { + int cmplen = bp->name.size(); + if (bp->name.lastChar() != ':') + cmplen = 256; + + if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) { + _console->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); + _debugState.debugging = true; + _debugState.breakpointWasHit = true; + return true; + } + } + } + + return false; +} + ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPtr sp, int framesize, StackPtr argp) { // send_obj and work_obj are equal for anything but 'super' // Returns a pointer to the TOS exec_stack element @@ -552,27 +581,7 @@ ExecStack *send_selector(EngineState *s, reg_t send_obj, reg_t work_obj, StackPt } // Check if a breakpoint is set on this method - if (g_sci->_debugState._activeBreakpointTypes & BREAK_SELECTOR) { - char method_name[256]; - - sprintf(method_name, "%s::%s", s->_segMan->getObjectName(send_obj), g_sci->getKernel()->getSelectorName(selector).c_str()); - - Common::List::const_iterator bp; - for (bp = g_sci->_debugState._breakpoints.begin(); bp != g_sci->_debugState._breakpoints.end(); ++bp) { - int cmplen = bp->name.size(); - if (bp->name.lastChar() != ':') - cmplen = 256; - - if (bp->type == BREAK_SELECTOR && !strncmp(bp->name.c_str(), method_name, cmplen)) { - Console *con = g_sci->getSciDebugger(); - con->DebugPrintf("Break on %s (in [%04x:%04x])\n", method_name, PRINT_REG(send_obj)); - printSendActions = true; - g_sci->_debugState.debugging = true; - g_sci->_debugState.breakpointWasHit = true; - break; - } - } - } + printSendActions = g_sci->checkSelectorBreakpoint(send_obj, selector); #ifdef VM_DEBUG_SEND printf("Send to %04x:%04x, selector %04x (%s):", PRINT_REG(send_obj), selector, g_sci->getKernel()->getSelectorName(selector).c_str()); diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 74c48258ef..c15f87e4e2 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -245,6 +245,8 @@ public: void sleep(uint32 msecs); void scriptDebug(); + bool checkExportBreakpoint(uint16 script, uint16 pubfunct); + bool checkSelectorBreakpoint(reg_t send_obj, int selector); public: -- cgit v1.2.3