/* ScummVM - Scumm Interpreter * Copyright (C) 2004 The ScummVM project * * The ReInherit Engine is (C)2000-2003 by Daniel Balsom. * * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. * * $Header$ * */ // Scene management module #include "saga/saga.h" #include "saga/yslib.h" #include "saga/gfx.h" #include "saga/game_mod.h" #include "saga/animation.h" #include "saga/console.h" #include "saga/cvar_mod.h" #include "saga/events.h" #include "saga/actionmap.h" #include "saga/isomap.h" #include "saga/objectmap.h" #include "saga/palanim.h" #include "saga/render.h" #include "saga/rscfile_mod.h" #include "saga/script.h" #include "saga/text.h" #include "saga/sound.h" #include "saga/music.h" #include "saga/scene.h" namespace Saga { static void CF_scenechange(int argc, char *argv[], void *refCon); static void CF_sceneinfo(int argc, char *argv[], void *refCon); static void CF_actioninfo(int argc, char *argv[], void *refCon); static void CF_objectinfo(int argc, char *argv[], void *refCon); int Scene::reg() { CVAR_Register_I(&_sceneNumber, "scene", NULL, R_CVAR_READONLY, 0, 0); CVAR_RegisterFunc(CF_scenechange, "scene_change", "", R_CVAR_NONE, 1, 1, this); CVAR_RegisterFunc(CF_sceneinfo, "scene_info", NULL, R_CVAR_NONE, 0, 0, this); CVAR_RegisterFunc(CF_actioninfo, "action_info", NULL, R_CVAR_NONE, 0, 0, this); CVAR_RegisterFunc(CF_objectinfo, "object_info", NULL, R_CVAR_NONE, 0, 0, this); return R_SUCCESS; } Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) { R_GAME_SCENEDESC gs_desc; byte *scene_lut_p; size_t scene_lut_len; int result; int i; // Load game-specific scene data GAME_GetSceneInfo(&gs_desc); // Load scene module resource context result = GAME_GetFileContext(&_sceneContext, R_GAME_RESOURCEFILE, 0); if (result != R_SUCCESS) { warning("Scene::Scene(): Couldn't load scene resource context"); return; } // Initialize scene queue _sceneQueue = ys_dll_create(); if (_sceneQueue == NULL) { return; } // Load scene lookup table debug(0, "Loading scene LUT from resource %u.", gs_desc.scene_lut_rn); result = RSC_LoadResource(_sceneContext, gs_desc.scene_lut_rn, &scene_lut_p, &scene_lut_len); if (result != R_SUCCESS) { warning("Scene::Scene(): Error: couldn't load scene LUT"); return; } _sceneCount = scene_lut_len / 2; _sceneMax = _sceneCount - 1; _sceneLUT = (int *)malloc(_sceneMax * sizeof *_sceneLUT); if (_sceneLUT == NULL) { warning("Scene::Scene(): Memory allocation failed"); return; } MemoryReadStream readS(scene_lut_p, scene_lut_len); for (i = 0; i < _sceneMax; i++) { _sceneLUT[i] = readS.readUint16LE(); } free(scene_lut_p); if (gs_desc.first_scene != 0) { _firstScene = gs_desc.first_scene; } debug(0, "First scene set to %d.", _firstScene); debug(0, "LUT has %d entries.", _sceneMax); // Create scene module text list _textList = _vm->textCreateList(); if (_textList == NULL) { warning("Scene::Scene(): Error: Couldn't create scene text list"); return; } _sceneLoaded = false; _sceneMode = 0; _sceneNumber = 0; _sceneResNum = 0; _inGame = false; _loadDesc = false; memset(&_desc, 0, sizeof(_desc)); _resListEntries = 0; _resList = NULL; _animEntries = 0; _animList = NULL; _sceneProc = NULL; _objectMap = NULL; _actionMap = NULL; memset(&_bg, 0, sizeof(_bg)); memset(&_bgMask, 0, sizeof(_bgMask)); _initialized = true; } Scene::~Scene() { if (_initialized) { endScene(); free(_sceneLUT); } } int Scene::queueScene(R_SCENE_QUEUE *scene_queue) { assert(_initialized); assert(scene_queue != NULL); ys_dll_add_tail(_sceneQueue, scene_queue, sizeof *scene_queue); return R_SUCCESS; } int Scene::clearSceneQueue() { assert(_initialized); ys_dll_delete_all(_sceneQueue); return R_SUCCESS; } int Scene::startScene() { YS_DL_NODE *node; R_SCENE_QUEUE *scene_qdat; assert(_initialized); if (_sceneLoaded) { warning("Scene::start(): Error: Can't start game...scene already loaded"); return R_FAILURE; } if (_inGame) { warning("Scene::start(): Error: Can't start game...game already started"); return R_FAILURE; } switch (GAME_GetGameType()) { case GID_ITE: ITEStartProc(); break; case GID_IHNM: IHNMStartProc(); break; default: warning("Scene::start(): Error: Can't start game... gametype not supported"); break; } // Load the head node in scene queue node = ys_dll_head(_sceneQueue); if (node == NULL) { return R_SUCCESS; } scene_qdat = (R_SCENE_QUEUE *)ys_dll_get_data(node); assert(scene_qdat != NULL); loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType); return R_SUCCESS; } int Scene::nextScene() { YS_DL_NODE *node; R_SCENE_QUEUE *scene_qdat; assert(_initialized); if (!_sceneLoaded) { warning("Scene::next(): Error: Can't advance scene...no scene loaded"); return R_FAILURE; } if (_inGame) { warning("Scene::next(): Error: Can't advance scene...game already started"); return R_FAILURE; } endScene(); // Delete the current head node in scene queue node = ys_dll_head(_sceneQueue); if (node == NULL) { return R_SUCCESS; } ys_dll_delete(node); // Load the head node in scene queue node = ys_dll_head(_sceneQueue); if (node == NULL) { return R_SUCCESS; } scene_qdat = (R_SCENE_QUEUE *)ys_dll_get_data(node); assert(scene_qdat != NULL); loadScene(scene_qdat->scene_n, scene_qdat->load_flag, scene_qdat->scene_proc, scene_qdat->scene_desc, scene_qdat->fadeType); return R_SUCCESS; } int Scene::skipScene() { YS_DL_NODE *node; YS_DL_NODE *prev_node; YS_DL_NODE *skip_node = NULL; R_SCENE_QUEUE *scene_qdat = NULL; R_SCENE_QUEUE *skip_qdat = NULL; assert(_initialized); if (!_sceneLoaded) { warning("Scene::skip(): Error: Can't skip scene...no scene loaded"); return R_FAILURE; } if (_inGame) { warning("Scene::skip(): Error: Can't skip scene...game already started"); return R_FAILURE; } // Walk down scene queue and try to find a skip target node = ys_dll_head(_sceneQueue); if (node == NULL) { warning("Scene::skip(): Error: Can't skip scene...no scenes in queue"); return R_FAILURE; } for (node = ys_dll_next(node); node != NULL; node = ys_dll_next(node)) { scene_qdat = (R_SCENE_QUEUE *)ys_dll_get_data(node); assert(scene_qdat != NULL); if (scene_qdat->scene_skiptarget) { skip_node = node; skip_qdat = scene_qdat; break; } } // If skip target found, remove preceding scenes and load if (skip_node != NULL) { for (node = ys_dll_prev(skip_node); node != NULL; node = prev_node) { prev_node = ys_dll_prev(node); ys_dll_delete(node); } endScene(); loadScene(skip_qdat->scene_n, skip_qdat->load_flag, skip_qdat->scene_proc, skip_qdat->scene_desc, skip_qdat->fadeType); } // Search for a scene to skip to return R_SUCCESS; } int Scene::changeScene(int scene_num) { assert(_initialized); if (!_sceneLoaded) { warning("Scene::changeScene(): Error: Can't change scene. No scene currently loaded. Game in invalid state"); return R_FAILURE; } if ((scene_num < 0) || (scene_num > _sceneMax)) { warning("Scene::changeScene(): Error: Can't change scene. Invalid scene number"); return R_FAILURE; } if (_sceneLUT[scene_num] == 0) { warning("Scene::changeScene(): Error: Can't change scene; invalid scene descriptor resource number (0)"); return R_FAILURE; } endScene(); loadScene(scene_num, BY_SCENE, SC_defaultScene, NULL, false); return R_SUCCESS; } int Scene::getMode() { assert(_initialized); return _sceneMode; } int Scene::getZInfo(SCENE_ZINFO *zinfo) { assert(_initialized); zinfo->beginSlope = _desc.beginSlope; zinfo->endSlope = _desc.endSlope; return R_SUCCESS; } int Scene::getBGInfo(SCENE_BGINFO *bginfo) { R_GAME_DISPLAYINFO di; int x, y; assert(_initialized); bginfo->bg_buf = _bg.buf; bginfo->bg_buflen = _bg.buf_len; bginfo->bg_w = _bg.w; bginfo->bg_h = _bg.h; bginfo->bg_p = _bg.p; GAME_GetDisplayInfo(&di); x = 0; y = 0; if (_bg.w < di.logical_w) { x = (di.logical_w - _bg.w) / 2; } if (_bg.h < di.scene_h) { y = (di.scene_h - _bg.h) / 2; } bginfo->bg_x = x; bginfo->bg_y = y; return R_SUCCESS; } int Scene::getBGPal(PALENTRY **pal) { assert(_initialized); *pal = _bg.pal; return R_SUCCESS; } int Scene::getBGMaskInfo(int *w, int *h, byte **buf, size_t *buf_len) { assert(_initialized); if (!_bgMask.loaded) { return R_FAILURE; } *w = _bgMask.w; *h = _bgMask.h; *buf = _bgMask.buf; *buf_len = _bgMask.buf_len; return R_SUCCESS; } int Scene::isBGMaskPresent() { assert(_initialized); return _bgMask.loaded; } int Scene::getInfo(R_SCENE_INFO *si) { assert(_initialized); assert(si != NULL); si->text_list = _textList; return R_SUCCESS; } int Scene::loadScene(int scene_num, int load_flag, R_SCENE_PROC scene_proc, R_SCENE_DESC *scene_desc_param, int fadeType) { R_SCENE_INFO scene_info; uint32 res_number = 0; int result; int i; assert(_initialized); if (_sceneLoaded) { warning("Scene::loadScene(): Error, a scene is already loaded"); return R_FAILURE; } _animList = ys_dll_create(); _sceneMode = 0; _loadDesc = true; switch (load_flag) { case BY_RESOURCE: res_number = scene_num; break; case BY_SCENE: assert((scene_num > 0) && (scene_num < _sceneMax)); res_number = _sceneLUT[scene_num]; _sceneNumber = scene_num; break; case BY_DESC: assert(scene_desc_param != NULL); assert(scene_desc_param->resList != NULL); _loadDesc = false; _desc = *scene_desc_param; _resList = scene_desc_param->resList; _resListEntries = scene_desc_param->resListCnt; break; default: warning("Scene::loadScene(): Error: Invalid scene load flag"); return R_FAILURE; break; } // Load scene descriptor and resource list resources if (_loadDesc) { _sceneResNum = res_number; assert(_sceneResNum != 0); debug(0, "Loading scene resource %u:", res_number); if (loadSceneDescriptor(res_number) != R_SUCCESS) { warning("Scene::loadScene(): Error reading scene descriptor"); return R_FAILURE; } if (loadSceneResourceList(_desc.resListRN) != R_SUCCESS) { warning("Scene::loadScene(): Error reading scene resource list"); return R_FAILURE; } } else { debug(0, "Loading memory scene resource."); } // Load resources from scene resource list for (i = 0; i < _resListEntries; i++) { result = RSC_LoadResource(_sceneContext, _resList[i].res_number, &_resList[i].res_data, &_resList[i].res_data_len); if (result != R_SUCCESS) { warning("Scene::loadScene(): Error: Allocation failure loading scene resource list"); return R_FAILURE; } } // Process resources from scene resource list if (processSceneResources() != R_SUCCESS) { warning("Scene::loadScene(): Error loading scene resources"); return R_FAILURE; } // Load scene script data if (_desc.scriptNum > 0) { if (_vm->_script->loadScript(_desc.scriptNum) != R_SUCCESS) { warning("Scene::loadScene(): Error loading scene script"); return R_FAILURE; } } _sceneLoaded = true; if (fadeType == SCENE_FADE || fadeType == SCENE_FADE_NO_INTERFACE) { R_EVENT event; R_EVENT *q_event; static PALENTRY current_pal[R_PAL_ENTRIES]; // Fade to black out _vm->_gfx->getCurrentPal(current_pal); event.type = R_IMMEDIATE_EVENT; event.code = R_PAL_EVENT; event.op = EVENT_PALTOBLACK; event.time = 0; event.duration = PALETTE_FADE_DURATION; event.data = current_pal; q_event = _vm->_events->queue(&event); if (fadeType != SCENE_FADE_NO_INTERFACE) { // Activate user interface event.type = R_IMMEDIATE_EVENT; event.code = R_INTERFACE_EVENT; event.op = EVENT_ACTIVATE; event.time = 0; event.duration = 0; q_event = _vm->_events->chain(q_event, &event); } // Display scene background, but stay with black palette event.type = R_IMMEDIATE_EVENT; event.code = R_BG_EVENT; event.op = EVENT_DISPLAY; event.param = NO_SET_PALETTE; event.time = 0; event.duration = 0; q_event = _vm->_events->chain(q_event, &event); // Fade in from black to the scene background palette event.type = R_IMMEDIATE_EVENT; event.code = R_PAL_EVENT; event.op = EVENT_BLACKTOPAL; event.time = 0; event.duration = PALETTE_FADE_DURATION; event.data = _bg.pal; q_event = _vm->_events->chain(q_event, &event); } if (scene_proc == NULL) { _sceneProc = SC_defaultScene; } else { _sceneProc = scene_proc; } getInfo(&scene_info); _sceneProc(SCENE_BEGIN, &scene_info, this); return R_SUCCESS; } int Scene::loadSceneDescriptor(uint32 res_number) { byte *scene_desc_data; size_t scene_desc_len; int result; result = RSC_LoadResource(_sceneContext, res_number, &scene_desc_data, &scene_desc_len); if (result != R_SUCCESS) { warning("Scene::loadSceneDescriptor(): Error: couldn't load scene descriptor"); return R_FAILURE; } if (scene_desc_len != SAGA_SCENE_DESC_LEN) { warning("Scene::loadSceneDescriptor(): Error: scene descriptor length invalid"); return R_FAILURE; } MemoryReadStream readS(scene_desc_data, scene_desc_len); _desc.flags = readS.readSint16LE(); _desc.resListRN = readS.readSint16LE(); _desc.endSlope = readS.readSint16LE(); _desc.beginSlope = readS.readSint16LE(); _desc.scriptNum = readS.readUint16LE(); _desc.sceneScriptNum = readS.readUint16LE(); _desc.startScriptNum = readS.readUint16LE(); _desc.musicRN = readS.readSint16LE(); RSC_FreeResource(scene_desc_data); return R_SUCCESS; } int Scene::loadSceneResourceList(uint32 reslist_rn) { byte *resource_list; size_t resource_list_len; int result; int i; // Load the scene resource table result = RSC_LoadResource(_sceneContext, reslist_rn, &resource_list, &resource_list_len); if (result != R_SUCCESS) { warning("Scene::loadSceneResourceList(): Error: couldn't load scene resource list"); return R_FAILURE; } MemoryReadStream readS(resource_list, resource_list_len); // Allocate memory for scene resource list _resListEntries = resource_list_len / SAGA_RESLIST_ENTRY_LEN; debug(0, "Scene resource list contains %d entries.", _resListEntries); _resList = (R_SCENE_RESLIST *)calloc(_resListEntries, sizeof *_resList); if (_resList == NULL) { warning("Scene::loadSceneResourceList(): Error: Memory allocation failed"); return R_MEM; } // Load scene resource list from raw scene // resource table debug(0, "Loading scene resource list..."); for (i = 0; i < _resListEntries; i++) { _resList[i].res_number = readS.readUint16LE(); _resList[i].res_type = readS.readUint16LE(); } RSC_FreeResource(resource_list); return R_SUCCESS; } int Scene::processSceneResources() { const byte *res_data; size_t res_data_len; const byte *pal_p; int i; _objectMap = new ObjectMap(_vm); // Process the scene resource list for (i = 0; i < _resListEntries; i++) { res_data = _resList[i].res_data; res_data_len = _resList[i].res_data_len; switch (_resList[i].res_type) { case SAGA_BG_IMAGE: // Scene background resource if (_bg.loaded) { warning("Scene::processSceneResources(): Multiple background resources encountered"); return R_FAILURE; } debug(0, "Loading background resource."); _bg.res_buf = _resList[i].res_data; _bg.res_len = _resList[i].res_data_len; _bg.loaded = 1; if (_vm->decodeBGImage(_bg.res_buf, _bg.res_len, &_bg.buf, &_bg.buf_len, &_bg.w, &_bg.h) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading background resource: %u", _resList[i].res_number); return R_FAILURE; } pal_p = _vm->getImagePal(_bg.res_buf, _bg.res_len); memcpy(_bg.pal, pal_p, sizeof _bg.pal); _sceneMode = R_SCENE_MODE_NORMAL; break; case SAGA_BG_MASK: // Scene background mask resource if (_bgMask.loaded) { warning("Scene::ProcessSceneResources(): Duplicate background mask resource encountered"); } debug(0, "Loading BACKGROUND MASK resource."); _bgMask.res_buf = _resList[i].res_data; _bgMask.res_len = _resList[i].res_data_len; _bgMask.loaded = 1; _vm->decodeBGImage(_bgMask.res_buf, _bgMask.res_len, &_bgMask.buf, &_bgMask.buf_len, &_bgMask.w, &_bgMask.h); break; case SAGA_OBJECT_NAME_LIST: debug(0, "Loading object name list resource..."); _objectMap->loadNames(_resList[i].res_data, _resList[i].res_data_len); break; case SAGA_OBJECT_MAP: debug(0, "Loading object map resource..."); if (_objectMap->load(res_data, res_data_len) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading object map resource"); return R_FAILURE; } break; case SAGA_ACTION_MAP: debug(0, "Loading exit map resource..."); _actionMap = new ActionMap(_vm, res_data, res_data_len); break; case SAGA_ISO_TILESET: if (_sceneMode == R_SCENE_MODE_NORMAL) { warning("Scene::ProcessSceneResources(): Isometric tileset incompatible with normal scene mode"); return R_FAILURE; } debug(0, "Loading isometric tileset resource."); if (_vm->_isoMap->loadTileset(res_data, res_data_len) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading isometric tileset resource"); return R_FAILURE; } _sceneMode = R_SCENE_MODE_ISO; break; case SAGA_ISO_METAMAP: if (_sceneMode == R_SCENE_MODE_NORMAL) { warning("Scene::ProcessSceneResources(): Isometric metamap incompatible with normal scene mode"); return R_FAILURE; } debug(0, "Loading isometric metamap resource."); if (_vm->_isoMap->loadMetamap(res_data, res_data_len) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading isometric metamap resource"); return R_FAILURE; } _sceneMode = R_SCENE_MODE_ISO; break; case SAGA_ISO_METATILESET: if (_sceneMode == R_SCENE_MODE_NORMAL) { warning("Scene::ProcessSceneResources(): Isometric metatileset incompatible with normal scene mode"); return R_FAILURE; } debug(0, "Loading isometric metatileset resource."); if (_vm->_isoMap->loadMetaTileset(res_data, res_data_len) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading isometric tileset resource"); return R_FAILURE; } _sceneMode = R_SCENE_MODE_ISO; break; case SAGA_ANIM_1: case SAGA_ANIM_2: case SAGA_ANIM_3: case SAGA_ANIM_4: case SAGA_ANIM_5: case SAGA_ANIM_6: case SAGA_ANIM_7: { SCENE_ANIMINFO *new_animinfo; uint16 new_anim_id; debug(0, "Loading animation resource..."); new_animinfo = (SCENE_ANIMINFO *)malloc(sizeof *new_animinfo); if (new_animinfo == NULL) { warning("Scene::ProcessSceneResources(): Memory allocation error"); return R_MEM; } if (_vm->_anim->load(_resList[i].res_data, _resList[i].res_data_len, &new_anim_id) != R_SUCCESS) { warning("Scene::ProcessSceneResources(): Error loading animation resource"); return R_FAILURE; } new_animinfo->anim_handle = new_anim_id; new_animinfo->anim_res_number = _resList[i].res_number; ys_dll_add_tail(_animList, new_animinfo, sizeof *new_animinfo); _animEntries++; } break; case SAGA_PAL_ANIM: debug(0, "Loading palette animation resource."); _vm->_palanim->loadPalAnim(_resList[i].res_data, _resList[i].res_data_len); break; case SAGA_ENTRY: warning("Scene::ProcessSceneResources(): Loading scene entries is not implemented"); break; case SAGA_FACES: warning("Scene::ProcessSceneResources(): Loading scene faces is not implemented"); break; default: warning("Scene::ProcessSceneResources(): Encountered unknown resource type: %d", _resList[i].res_type); break; } } return R_SUCCESS; } int Scene::draw(R_SURFACE *dst_s) { R_GAME_DISPLAYINFO disp_info; R_BUFFER_INFO buf_info; Point bg_pt; assert(_initialized); _vm->_render->getBufferInfo(&buf_info); GAME_GetDisplayInfo(&disp_info); bg_pt.x = 0; bg_pt.y = 0; switch (_sceneMode) { case R_SCENE_MODE_NORMAL: _vm->_gfx->bufToSurface(dst_s, buf_info.r_bg_buf, disp_info.logical_w, MAX(disp_info.scene_h, _bg.h), NULL, &bg_pt); break; case R_SCENE_MODE_ISO: _vm->_isoMap->draw(dst_s); break; default: // Unknown scene mode return R_FAILURE; break; }; return R_SUCCESS; } int Scene::endScene() { R_SCENE_INFO scene_info; assert(_initialized); if (!_sceneLoaded) { warning("Scene::endScene(): No scene to end"); return -1; } debug(0, "Ending scene..."); getInfo(&scene_info); _sceneProc(SCENE_END, &scene_info, this); if (_desc.scriptNum > 0) { _vm->_script->freeScript(); } // Free scene background if (_bg.loaded) { free(_bg.buf); _bg.loaded = 0; } // Free scene background mask if (_bgMask.loaded) { free(_bgMask.buf); _bgMask.loaded = 0; } // Free scene resource list if (_loadDesc) { free(_resList); } // Free animation info list _vm->_anim->reset(); _vm->_palanim->freePalAnim(); delete _objectMap; delete _actionMap; _objectMap = NULL; _actionMap = NULL; ys_dll_destroy(_animList); _animEntries = 0; _vm->_events->clearList(); _vm->textClearList(_textList); _sceneLoaded = false; return R_SUCCESS; } void Scene::sceneChangeCmd(int argc, char *argv[]) { int scene_num = 0; if ((argc == 0) || (argc > 1)) { return; } scene_num = atoi(argv[0]); if ((scene_num < 1) || (scene_num > _sceneMax)) { _vm->_console->print("Invalid scene number."); return; } clearSceneQueue(); if (changeScene(scene_num) == R_SUCCESS) { _vm->_console->print("Scene changed."); } else { _vm->_console->print("Couldn't change scene!"); } } static void CF_scenechange(int argc, char *argv[], void *refCon) { ((Scene *)refCon)->sceneChangeCmd(argc, argv); } void Scene::sceneInfoCmd(int argc, char *argv[]) { const char *fmt = "%-20s %d"; _vm->_console->print(fmt, "Scene number:", _sceneNumber); _vm->_console->print(fmt, "Descriptor R#:", _sceneResNum); _vm->_console->print("-------------------------"); _vm->_console->print(fmt, "Flags:", _desc.flags); _vm->_console->print(fmt, "Resource list R#:", _desc.resListRN); _vm->_console->print(fmt, "End slope:", _desc.endSlope); _vm->_console->print(fmt, "Begin slope:", _desc.beginSlope); _vm->_console->print(fmt, "Script resource:", _desc.scriptNum); _vm->_console->print(fmt, "Scene script:", _desc.sceneScriptNum); _vm->_console->print(fmt, "Start script:", _desc.startScriptNum); _vm->_console->print(fmt, "Music R#", _desc.musicRN); } static void CF_sceneinfo(int argc, char *argv[], void *refCon) { ((Scene *)refCon)->sceneInfoCmd(argc, argv); } int Scene::SC_defaultScene(int param, R_SCENE_INFO *scene_info, void *refCon) { return ((Scene *)refCon)->defaultScene(param, scene_info); } static void CF_actioninfo(int argc, char *argv[], void *refCon) { (void)(argc); (void)(argv); ((Scene *)refCon)->_actionMap->info(); } static void CF_objectinfo(int argc, char *argv[], void *refCon) { (void)(argc); (void)(argv); ((Scene *)refCon)->_objectMap->info(); } int Scene::defaultScene(int param, R_SCENE_INFO *scene_info) { R_EVENT event; switch (param) { case SCENE_BEGIN: _vm->_music->stop(); _vm->_sound->stopVoice(); // Set scene background event.type = R_ONESHOT_EVENT; event.code = R_BG_EVENT; event.op = EVENT_DISPLAY; event.param = SET_PALETTE; event.time = 0; _vm->_events->queue(&event); // Activate user interface event.type = R_ONESHOT_EVENT; event.code = R_INTERFACE_EVENT; event.op = EVENT_ACTIVATE; event.time = 0; _vm->_events->queue(&event); // Begin palette cycle animation if present event.type = R_ONESHOT_EVENT; event.code = R_PALANIM_EVENT; event.op = EVENT_CYCLESTART; event.time = 0; _vm->_events->queue(&event); // Start scene animations _vm->_anim->setFlag(0, ANIM_LOOP); _vm->_anim->play(0, 0); // Start scene scripts if (_desc.startScriptNum > 0) { R_SCRIPT_THREAD *_startScriptThread; debug(0, "Starting start script #%d", _desc.startScriptNum); _startScriptThread = _vm->_script->SThreadCreate(); if (_startScriptThread == NULL) { _vm->_console->print("Thread creation failed."); break; } _startScriptThread->threadVars[kVarAction] = 0; _startScriptThread->threadVars[kVarObject] = TO_LE_16(_sceneNumber); _startScriptThread->threadVars[kVarWithObject] = 0; // TOTO: entrance _startScriptThread->threadVars[kVarActor] = 0; _vm->_script->SThreadExecute(_startScriptThread, _desc.startScriptNum); _vm->_script->SThreadCompleteThread(); } if (_desc.musicRN >= 0) { event.type = R_ONESHOT_EVENT; event.code = R_MUSIC_EVENT; event.param = _desc.musicRN; event.op = EVENT_PLAY; event.time = 0; _vm->_events->queue(&event); } else _vm->_music->stop(); if (_desc.sceneScriptNum > 0) { R_SCRIPT_THREAD *_sceneScriptThread; debug(0, "Starting scene script #%d", _desc.sceneScriptNum); _sceneScriptThread = _vm->_script->SThreadCreate(); if (_sceneScriptThread == NULL) { _vm->_console->print("Thread creation failed."); break; } _sceneScriptThread->threadVars[kVarAction] = 0; _sceneScriptThread->threadVars[kVarObject] = TO_LE_16(_sceneNumber); _sceneScriptThread->threadVars[kVarWithObject] = 0; // TODO: entrance _sceneScriptThread->threadVars[kVarActor] = 0; // TODO: VERB_ENTER _vm->_script->SThreadExecute(_sceneScriptThread, _desc.sceneScriptNum); } debug(0, "Scene started"); break; case SCENE_END: break; default: warning("Scene::defaultScene(): Illegal scene procedure parameter"); break; } return 0; } } // End of namespace Saga