scummvm/saga/scene.cpp
Torbjörn Andersson c64c7eb4d4 First pass at migrating from the old Reinherit console to the ScummVM
console.

Some things are likely to have broken. For instance, I believe the old
console was could be visible during gameplay, while ScummVM's is modal. So
any place where we output something to the console during gameplay should
probably be removed.

Some things I've stubbed out. Basically any code that registers a variable.

Most of the debugging commands are untested.

Syntax may have changed because of different command-line parsing. (I never
actually used the old console, so I don't know for sure. :-)

Actually, I'm not that interested in reproducing the old console commands
faithfully. What we should do now is to make the immediately useful console
stuff work. Anything that remains unimplemented should probably be removed.

svn-id: r15976
2004-12-03 19:15:44 +00:00

1026 lines
24 KiB
C++

/* 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/interface.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 {
Scene::Scene(SagaEngine *vm) : _vm(vm), _initialized(false) {
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
_sceneContext = GAME_GetFileContext(GAME_RESOURCEFILE, 0);
if (_sceneContext == NULL) {
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 != 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(SCENE_QUEUE *scene_queue) {
assert(_initialized);
assert(scene_queue != NULL);
ys_dll_add_tail(_sceneQueue, scene_queue, sizeof *scene_queue);
return SUCCESS;
}
int Scene::clearSceneQueue() {
assert(_initialized);
ys_dll_delete_all(_sceneQueue);
return SUCCESS;
}
int Scene::startScene() {
YS_DL_NODE *node;
SCENE_QUEUE *scene_qdat;
EVENT event;
assert(_initialized);
if (_sceneLoaded) {
warning("Scene::start(): Error: Can't start game...scene already loaded");
return FAILURE;
}
if (_inGame) {
warning("Scene::start(): Error: Can't start game...game already started");
return FAILURE;
}
// Hide cursor during intro
event.type = ONESHOT_EVENT;
event.code = CURSOR_EVENT;
event.op = EVENT_HIDE;
_vm->_events->queue(&event);
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 SUCCESS;
}
scene_qdat = (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 SUCCESS;
}
int Scene::nextScene() {
YS_DL_NODE *node;
SCENE_QUEUE *scene_qdat;
assert(_initialized);
if (!_sceneLoaded) {
warning("Scene::next(): Error: Can't advance scene...no scene loaded");
return FAILURE;
}
if (_inGame) {
warning("Scene::next(): Error: Can't advance scene...game already started");
return FAILURE;
}
endScene();
// Delete the current head node in scene queue
node = ys_dll_head(_sceneQueue);
if (node == NULL) {
return SUCCESS;
}
ys_dll_delete(node);
// Load the head node in scene queue
node = ys_dll_head(_sceneQueue);
if (node == NULL) {
return SUCCESS;
}
scene_qdat = (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 SUCCESS;
}
int Scene::skipScene() {
YS_DL_NODE *node;
YS_DL_NODE *prev_node;
YS_DL_NODE *skip_node = NULL;
SCENE_QUEUE *scene_qdat = NULL;
SCENE_QUEUE *skip_qdat = NULL;
assert(_initialized);
if (!_sceneLoaded) {
warning("Scene::skip(): Error: Can't skip scene...no scene loaded");
return FAILURE;
}
if (_inGame) {
warning("Scene::skip(): Error: Can't skip scene...game already started");
return 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 FAILURE;
}
for (node = ys_dll_next(node); node != NULL; node = ys_dll_next(node)) {
scene_qdat = (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 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 FAILURE;
}
if ((scene_num < 0) || (scene_num > _sceneMax)) {
warning("Scene::changeScene(): Error: Can't change scene. Invalid scene number");
return FAILURE;
}
if (_sceneLUT[scene_num] == 0) {
warning("Scene::changeScene(): Error: Can't change scene; invalid scene descriptor resource number (0)");
return FAILURE;
}
endScene();
loadScene(scene_num, BY_SCENE, SC_defaultScene, NULL, false);
return 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 SUCCESS;
}
int Scene::getBGInfo(SCENE_BGINFO *bginfo) {
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 SUCCESS;
}
int Scene::getBGPal(PALENTRY **pal) {
assert(_initialized);
*pal = _bg.pal;
return SUCCESS;
}
int Scene::getBGMaskInfo(int *w, int *h, byte **buf, size_t *buf_len) {
assert(_initialized);
if (!_bgMask.loaded) {
return FAILURE;
}
*w = _bgMask.w;
*h = _bgMask.h;
*buf = _bgMask.buf;
*buf_len = _bgMask.buf_len;
return SUCCESS;
}
int Scene::isBGMaskPresent() {
assert(_initialized);
return _bgMask.loaded;
}
int Scene::getInfo(SCENE_INFO *si) {
assert(_initialized);
assert(si != NULL);
si->text_list = _textList;
return SUCCESS;
}
int Scene::getSceneLUT(int scene_num) {
assert((scene_num > 0) && (scene_num < _sceneMax));
return _sceneLUT[scene_num];
}
int Scene::loadScene(int scene_num, int load_flag, SCENE_PROC scene_proc, SCENE_DESC *scene_desc_param, int fadeType) {
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 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 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) != SUCCESS) {
warning("Scene::loadScene(): Error reading scene descriptor");
return FAILURE;
}
if (loadSceneResourceList(_desc.resListRN) != SUCCESS) {
warning("Scene::loadScene(): Error reading scene resource list");
return 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 != SUCCESS) {
warning("Scene::loadScene(): Error: Allocation failure loading scene resource list");
return FAILURE;
}
}
// Process resources from scene resource list
if (processSceneResources() != SUCCESS) {
warning("Scene::loadScene(): Error loading scene resources");
return FAILURE;
}
// Load scene script data
if (_desc.scriptNum > 0) {
if (_vm->_script->loadScript(_desc.scriptNum) != SUCCESS) {
warning("Scene::loadScene(): Error loading scene script");
return FAILURE;
}
}
_sceneLoaded = true;
if (fadeType == SCENE_FADE || fadeType == SCENE_FADE_NO_INTERFACE) {
EVENT event;
EVENT *q_event;
static PALENTRY current_pal[PAL_ENTRIES];
// Fade to black out
_vm->_gfx->getCurrentPal(current_pal);
event.type = IMMEDIATE_EVENT;
event.code = 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 = IMMEDIATE_EVENT;
event.code = 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 = IMMEDIATE_EVENT;
event.code = 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);
// Start the scene pre script, but stay with black palette
if (_desc.startScriptNum > 0) {
event.type = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_BLOCKING;
event.time = 0;
event.param = _desc.startScriptNum;
event.param2 = 0; // Action
event.param3 = _sceneNumber; // Object
event.param4 = 0; // With Object - TODO: should be 'entrance'
event.param5 = 0; // Actor
_vm->_events->chain(q_event, &event);
}
// Fade in from black to the scene background palette
event.type = IMMEDIATE_EVENT;
event.code = 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 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 != SUCCESS) {
warning("Scene::loadSceneDescriptor(): Error: couldn't load scene descriptor");
return FAILURE;
}
if (scene_desc_len != SAGA_SCENE_DESC_LEN) {
warning("Scene::loadSceneDescriptor(): Error: scene descriptor length invalid");
return 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 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 != SUCCESS) {
warning("Scene::loadSceneResourceList(): Error: couldn't load scene resource list");
return 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 = (SCENE_RESLIST *)calloc(_resListEntries, sizeof *_resList);
if (_resList == NULL) {
warning("Scene::loadSceneResourceList(): Error: Memory allocation failed");
return 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 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 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) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading background resource: %u", _resList[i].res_number);
return FAILURE;
}
pal_p = _vm->getImagePal(_bg.res_buf, _bg.res_len);
memcpy(_bg.pal, pal_p, sizeof _bg.pal);
_sceneMode = 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) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading object map resource");
return 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 == SCENE_MODE_NORMAL) {
warning("Scene::ProcessSceneResources(): Isometric tileset incompatible with normal scene mode");
return FAILURE;
}
debug(0, "Loading isometric tileset resource.");
if (_vm->_isoMap->loadTileset(res_data, res_data_len) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading isometric tileset resource");
return FAILURE;
}
_sceneMode = SCENE_MODE_ISO;
break;
case SAGA_ISO_METAMAP:
if (_sceneMode == SCENE_MODE_NORMAL) {
warning("Scene::ProcessSceneResources(): Isometric metamap incompatible with normal scene mode");
return FAILURE;
}
debug(0, "Loading isometric metamap resource.");
if (_vm->_isoMap->loadMetamap(res_data, res_data_len) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading isometric metamap resource");
return FAILURE;
}
_sceneMode = SCENE_MODE_ISO;
break;
case SAGA_ISO_METATILESET:
if (_sceneMode == SCENE_MODE_NORMAL) {
warning("Scene::ProcessSceneResources(): Isometric metatileset incompatible with normal scene mode");
return FAILURE;
}
debug(0, "Loading isometric metatileset resource.");
if (_vm->_isoMap->loadMetaTileset(res_data, res_data_len) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading isometric tileset resource");
return FAILURE;
}
_sceneMode = 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 MEM;
}
if (_vm->_anim->load(_resList[i].res_data,
_resList[i].res_data_len, &new_anim_id) != SUCCESS) {
warning("Scene::ProcessSceneResources(): Error loading animation resource");
return 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:
_vm->_interface->loadScenePortraits(_resList[i].res_number);
break;
default:
warning("Scene::ProcessSceneResources(): Encountered unknown resource type: %d", _resList[i].res_type);
break;
}
}
return SUCCESS;
}
int Scene::draw(SURFACE *dst_s) {
GAME_DISPLAYINFO disp_info;
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 SCENE_MODE_NORMAL:
bufToSurface(dst_s, buf_info.bg_buf, disp_info.logical_w,
MAX(disp_info.scene_h, _bg.h), NULL, &bg_pt);
break;
case SCENE_MODE_ISO:
_vm->_isoMap->draw(dst_s);
break;
default:
// Unknown scene mode
return FAILURE;
break;
};
return SUCCESS;
}
int Scene::endScene() {
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 SUCCESS;
}
void Scene::sceneChangeCmd(int argc, const char **argv) {
int scene_num = 0;
scene_num = atoi(argv[1]);
if ((scene_num < 1) || (scene_num > _sceneMax)) {
_vm->_console->DebugPrintf("Invalid scene number.\n");
return;
}
clearSceneQueue();
if (changeScene(scene_num) == SUCCESS) {
_vm->_console->DebugPrintf("Scene changed.\n");
} else {
_vm->_console->DebugPrintf("Couldn't change scene!\n");
}
}
void Scene::sceneInfoCmd() {
const char *fmt = "%-20s %d\n";
_vm->_console->DebugPrintf(fmt, "Scene number:", _sceneNumber);
_vm->_console->DebugPrintf(fmt, "Descriptor R#:", _sceneResNum);
_vm->_console->DebugPrintf("-------------------------\n");
_vm->_console->DebugPrintf(fmt, "Flags:", _desc.flags);
_vm->_console->DebugPrintf(fmt, "Resource list R#:", _desc.resListRN);
_vm->_console->DebugPrintf(fmt, "End slope:", _desc.endSlope);
_vm->_console->DebugPrintf(fmt, "Begin slope:", _desc.beginSlope);
_vm->_console->DebugPrintf(fmt, "Script resource:", _desc.scriptNum);
_vm->_console->DebugPrintf(fmt, "Scene script:", _desc.sceneScriptNum);
_vm->_console->DebugPrintf(fmt, "Start script:", _desc.startScriptNum);
_vm->_console->DebugPrintf(fmt, "Music R#", _desc.musicRN);
}
int Scene::SC_defaultScene(int param, SCENE_INFO *scene_info, void *refCon) {
return ((Scene *)refCon)->defaultScene(param, scene_info);
}
void Scene::CF_actioninfo() {
_actionMap->info();
}
void Scene::CF_objectinfo() {
_objectMap->info();
}
int Scene::defaultScene(int param, SCENE_INFO *scene_info) {
EVENT event;
EVENT *q_event;
switch (param) {
case SCENE_BEGIN:
_vm->_sound->stopVoice();
_vm->_sound->stopSound();
if (_desc.musicRN >= 0) {
event.type = ONESHOT_EVENT;
event.code = MUSIC_EVENT;
event.param = _desc.musicRN;
event.param2 = MUSIC_DEFAULT;
event.op = EVENT_PLAY;
event.time = 0;
_vm->_events->queue(&event);
} else {
event.type = ONESHOT_EVENT;
event.code = MUSIC_EVENT;
event.op = EVENT_STOP;
event.time = 0;
_vm->_events->queue(&event);
}
// Set scene background
event.type = ONESHOT_EVENT;
event.code = BG_EVENT;
event.op = EVENT_DISPLAY;
event.param = SET_PALETTE;
event.time = 0;
_vm->_events->queue(&event);
// Activate user interface
event.type = ONESHOT_EVENT;
event.code = INTERFACE_EVENT;
event.op = EVENT_ACTIVATE;
event.time = 0;
_vm->_events->queue(&event);
// Begin palette cycle animation if present
event.type = ONESHOT_EVENT;
event.code = PALANIM_EVENT;
event.op = EVENT_CYCLESTART;
event.time = 0;
q_event = _vm->_events->queue(&event);
// Show cursor
event.type = ONESHOT_EVENT;
event.code = CURSOR_EVENT;
event.op = EVENT_SHOW;
_vm->_events->chain(q_event, &event);
// Start scene animations
_vm->_anim->setFlag(0, ANIM_LOOP);
_vm->_anim->play(0, 0);
// Start the scene main script
if (_desc.sceneScriptNum > 0) {
event.type = ONESHOT_EVENT;
event.code = SCRIPT_EVENT;
event.op = EVENT_NONBLOCKING;
event.time = 0;
event.param = _desc.sceneScriptNum;
event.param2 = 0; // Action
event.param3 = _sceneNumber; // Object
event.param4 = 0; // With Object - TODO: should be 'entrance'
event.param5 = 0; // Actor - TODO: should be VERB_ENTER
_vm->_events->queue(&event);
}
debug(0, "Scene started");
break;
case SCENE_END:
break;
default:
warning("Scene::defaultScene(): Illegal scene procedure parameter");
break;
}
return 0;
}
} // End of namespace Saga