mirror of
https://github.com/libretro/scummvm.git
synced 2024-12-23 02:11:38 +00:00
c64c7eb4d4
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
1026 lines
24 KiB
C++
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
|