2014-02-25 09:21:19 -05:00
|
|
|
/* 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.
|
|
|
|
*
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "common/scummsys.h"
|
2014-02-25 19:52:35 -05:00
|
|
|
#include "mads/scene_data.h"
|
2014-02-25 09:21:19 -05:00
|
|
|
#include "mads/mads.h"
|
2014-02-28 20:37:42 -05:00
|
|
|
#include "mads/compression.h"
|
2014-03-02 16:42:39 -05:00
|
|
|
#include "mads/graphics.h"
|
2014-02-25 23:10:51 -05:00
|
|
|
#include "mads/resources.h"
|
2014-02-25 09:21:19 -05:00
|
|
|
#include "mads/nebular/nebular_scenes.h"
|
|
|
|
|
|
|
|
namespace MADS {
|
|
|
|
|
2014-03-02 23:09:17 -05:00
|
|
|
ScreenObject::ScreenObject() {
|
|
|
|
_category = CAT_NONE;
|
|
|
|
_descId = 0;
|
|
|
|
_layer = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
ScreenObjects::ScreenObjects(MADSEngine *vm): _vm(vm) {
|
|
|
|
_v8333C = false;
|
|
|
|
_v832EC = 0;
|
|
|
|
_yp = 0;
|
|
|
|
_v7FECA = 0;
|
|
|
|
_v7FED6 = 0;
|
|
|
|
_v8332A = 0;
|
|
|
|
_selectedObject = 0;
|
|
|
|
_category = CAT_NONE;
|
|
|
|
_objectIndex = 0;
|
|
|
|
_released = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScreenObjects::add(const Common::Rect &bounds, ScrCategory category, int descId) {
|
|
|
|
assert(size() < 100);
|
|
|
|
|
|
|
|
ScreenObject so;
|
|
|
|
so._bounds = bounds;
|
|
|
|
so._category = category;
|
|
|
|
so._descId = descId;
|
|
|
|
so._layer = 0x1413;
|
|
|
|
|
|
|
|
push_back(so);
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScreenObjects::check(bool scanFlag) {
|
|
|
|
Scene &scene = _vm->_game->_scene;
|
|
|
|
|
|
|
|
if (!_vm->_events->_mouseButtons || _v832EC)
|
|
|
|
_v7FECA = false;
|
|
|
|
|
|
|
|
if ((_vm->_events->_vD6 || _v8332A || _yp || _v8333C) && scanFlag) {
|
|
|
|
_selectedObject = scanBackwards(_vm->_events->currentPos(), LAYER_GUI);
|
|
|
|
if (_selectedObject > 0) {
|
|
|
|
_category = (ScrCategory)((*this)[_selectedObject - 1]._category & 7);
|
|
|
|
_objectIndex = (*this)[_selectedObject - 1]._descId;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Handling for easy mouse
|
|
|
|
ScrCategory category = scene._interface._category;
|
|
|
|
if (_vm->_easyMouse && !_vm->_events->_vD4 && category != _category
|
|
|
|
&& scene._interface._category != CAT_NONE) {
|
|
|
|
_released = true;
|
|
|
|
if (category >= CAT_ACTION && category <= CAT_6) {
|
|
|
|
scene._interface.elementHighlighted();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
_released = _vm->_events->_mouseReleased;
|
|
|
|
if (_vm->_events->_vD2 || (_vm->_easyMouse && !_vm->_events->_vD4))
|
|
|
|
scene._interface._category = _category;
|
|
|
|
|
|
|
|
if (!_vm->_events->_mouseButtons || _vm->_easyMouse) {
|
|
|
|
if (category >= CAT_ACTION && category <= CAT_6) {
|
|
|
|
scene._interface.elementHighlighted();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vm->_events->_mouseButtons || (_vm->_easyMouse && scene._action._v83338 > 1
|
|
|
|
&& scene._interface._category == CAT_INV_LIST) ||
|
|
|
|
(_vm->_easyMouse && scene._interface._category == CAT_HOTSPOT)) {
|
|
|
|
scene._action.checkActionAtMousePos();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vm->_events->_mouseReleased) {
|
|
|
|
scene.leftClick();
|
|
|
|
scene._interface._category = CAT_NONE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_vm->_events->_mouseButtons || _vm->_easyMouse || _yp)
|
|
|
|
proc1();
|
|
|
|
|
|
|
|
if (_vm->_events->_mouseButtons || _vm->_easyMouse)
|
|
|
|
scene._action.set();
|
|
|
|
|
|
|
|
_v8333C = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
scene._action.refresh();
|
|
|
|
|
|
|
|
// Loop through image inter list
|
|
|
|
warning("TODO: iimageInterList loop");
|
|
|
|
}
|
|
|
|
|
|
|
|
int ScreenObjects::scanBackwards(const Common::Point &pt, int layer) {
|
|
|
|
for (int i = (int)size() - 1; i >= 0; --i) {
|
|
|
|
if ((*this)[i]._bounds.contains(pt) && ((*this)[i]._layer == layer))
|
|
|
|
return i + 1;
|
|
|
|
}
|
|
|
|
|
|
|
|
// Entry not found
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
void ScreenObjects::proc1() {
|
|
|
|
warning("TODO: ScreenObjects::proc1");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-02-25 09:21:19 -05:00
|
|
|
SpriteSlot::SpriteSlot() {
|
|
|
|
_spriteType = ST_NONE;
|
|
|
|
_seqIndex = 0;
|
2014-02-25 19:52:35 -05:00
|
|
|
_spritesIndex = 0;
|
2014-02-25 09:21:19 -05:00
|
|
|
_frameNumber = 0;
|
|
|
|
_depth = 0;
|
|
|
|
_scale = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
SpriteSlot::SpriteSlot(SpriteType type, int seqIndex) {
|
|
|
|
_spriteType = type;
|
|
|
|
_seqIndex = seqIndex;
|
2014-02-25 19:52:35 -05:00
|
|
|
_spritesIndex = 0;
|
2014-02-25 09:21:19 -05:00
|
|
|
_frameNumber = 0;
|
|
|
|
_depth = 0;
|
|
|
|
_scale = 0;
|
|
|
|
}
|
|
|
|
|
2014-02-25 19:52:35 -05:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
void SpriteSlots::clear(bool flag) {
|
|
|
|
_vm->_game->_scene._textDisplay.clear();
|
|
|
|
|
|
|
|
if (flag)
|
|
|
|
_vm->_game->_scene._sprites.clear();
|
|
|
|
|
|
|
|
Common::Array<SpriteSlot>::clear();
|
|
|
|
push_back(SpriteSlot(ST_FULL_SCREEN_REFRESH, -1));
|
|
|
|
}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Releases any sprites used by the player
|
|
|
|
*/
|
|
|
|
void SpriteSlots::releasePlayerSprites() {
|
2014-03-02 23:09:17 -05:00
|
|
|
Player &player = _vm->_game->_player;
|
2014-02-25 19:52:35 -05:00
|
|
|
|
|
|
|
if (player._spritesLoaded && player._numSprites > 0) {
|
|
|
|
int spriteEnd = player._spritesStart + player._numSprites - 1;
|
|
|
|
do {
|
|
|
|
deleteEntry(spriteEnd);
|
|
|
|
} while (--spriteEnd >= player._spritesStart);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
void SpriteSlots::deleteEntry(int index) {
|
|
|
|
remove_at(index);
|
|
|
|
}
|
|
|
|
|
2014-03-02 17:49:52 -05:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
int SpriteSets::add(SpriteAsset *asset, int idx) {
|
|
|
|
if (!idx)
|
|
|
|
idx = size();
|
|
|
|
|
2014-03-02 18:37:09 -05:00
|
|
|
if (idx >= (int)(size() + 1))
|
2014-03-02 17:49:52 -05:00
|
|
|
resize(idx + 1);
|
|
|
|
delete (*this)[idx];
|
|
|
|
(*this)[idx] = asset;
|
|
|
|
|
|
|
|
return idx;
|
|
|
|
}
|
2014-02-25 19:52:35 -05:00
|
|
|
|
2014-02-25 09:21:19 -05:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
TextDisplay::TextDisplay() {
|
|
|
|
_active = false;
|
|
|
|
_spacing = 0;
|
|
|
|
_expire = 0;
|
|
|
|
_col1 = _col2 = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
DynamicHotspot::DynamicHotspot() {
|
|
|
|
_seqIndex = 0;
|
|
|
|
_facing = 0;
|
|
|
|
_descId = 0;
|
|
|
|
_field14 = 0;
|
|
|
|
_articleNumber = 0;
|
2014-03-03 00:42:41 -05:00
|
|
|
_cursor = CURSOR_NONE;
|
2014-02-25 09:21:19 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-02 23:09:17 -05:00
|
|
|
DynamicHotspots::DynamicHotspots(MADSEngine *vm): _vm(vm) {
|
2014-03-03 20:53:27 -05:00
|
|
|
for (int i = 0; i < DYNAMIC_HOTSPOTS_SIZE; ++i) {
|
|
|
|
DynamicHotspot rec;
|
|
|
|
rec._active = false;
|
|
|
|
_entries.push_back(rec);
|
|
|
|
}
|
|
|
|
|
|
|
|
_changed = true;
|
|
|
|
_count = 0;
|
2014-03-02 23:09:17 -05:00
|
|
|
}
|
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
int DynamicHotspots::add(int descId, int field14, int seqIndex, const Common::Rect &bounds) {
|
|
|
|
// Find a free slot
|
|
|
|
uint idx = 0;
|
|
|
|
while ((idx < _entries.size()) && _entries[idx]._active)
|
|
|
|
++idx;
|
|
|
|
if (idx == _entries.size())
|
|
|
|
error("DynamicHotspots overflow");
|
|
|
|
|
|
|
|
_entries[idx]._active = true;
|
|
|
|
_entries[idx]._descId = descId;
|
|
|
|
_entries[idx]._seqIndex = seqIndex;
|
|
|
|
_entries[idx]._bounds = bounds;
|
|
|
|
_entries[idx]._feetPos.x = -3;
|
|
|
|
_entries[idx]._feetPos.y = 0;
|
|
|
|
_entries[idx]._facing = 5;
|
|
|
|
_entries[idx]._field14 = field14;
|
|
|
|
_entries[idx]._articleNumber = 6;
|
|
|
|
_entries[idx]._cursor = CURSOR_NONE;
|
|
|
|
|
|
|
|
++_count;
|
|
|
|
_changed = true;
|
|
|
|
|
|
|
|
if (seqIndex >= 0)
|
|
|
|
_vm->_game->_scene._sequences[seqIndex]._dynamicHotspotIndex = idx;
|
|
|
|
|
|
|
|
return idx;
|
2014-03-02 23:09:17 -05:00
|
|
|
}
|
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
int DynamicHotspots::setPosition(int index, int xp, int yp, int facing) {
|
|
|
|
if (index >= 0) {
|
|
|
|
_entries[index]._feetPos.x = xp;
|
|
|
|
_entries[index]._feetPos.y = yp;
|
|
|
|
_entries[index]._facing = facing;
|
|
|
|
}
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
int DynamicHotspots::setCursor(int index, CursorType cursor) {
|
|
|
|
if (index >= 0)
|
|
|
|
_entries[index]._cursor = cursor;
|
|
|
|
|
|
|
|
return index;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DynamicHotspots::remove(int index) {
|
2014-03-02 23:09:17 -05:00
|
|
|
Scene &scene = _vm->_game->_scene;
|
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
if (_entries[index]._active) {
|
|
|
|
if (_entries[index]._seqIndex >= 0)
|
|
|
|
scene._sequences[_entries[index]._seqIndex]._dynamicHotspotIndex = -1;
|
|
|
|
_entries[index]._active = false;
|
2014-03-02 23:09:17 -05:00
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
--_count;
|
|
|
|
_changed = true;
|
2014-03-02 23:09:17 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
void DynamicHotspots::clear() {
|
|
|
|
for (uint i = 0; i < _entries.size(); ++i)
|
|
|
|
_entries[i]._active = false;
|
2014-03-02 23:09:17 -05:00
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
_changed = false;
|
|
|
|
_count = 0;
|
2014-02-25 09:21:19 -05:00
|
|
|
}
|
|
|
|
|
2014-03-03 20:53:27 -05:00
|
|
|
void DynamicHotspots::reset() {
|
|
|
|
for (uint i = 0; i < _entries.size(); ++i)
|
|
|
|
remove(i);
|
|
|
|
|
|
|
|
_count = 0;
|
|
|
|
_changed = false;
|
|
|
|
}
|
|
|
|
|
|
|
|
void DynamicHotspots::refresh() {
|
|
|
|
error("DynamicHotspots::refresh");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-02-25 09:21:19 -05:00
|
|
|
KernelMessage::KernelMessage() {
|
|
|
|
_flags = 0;
|
|
|
|
_seqInex = 0;
|
|
|
|
_asciiChar = '\0';
|
|
|
|
_asciiChar2 = '\0';
|
|
|
|
_colors = 0;
|
|
|
|
_msgOffset = 0;
|
|
|
|
_numTicks = 0;
|
|
|
|
_frameTimer2 = 0;
|
|
|
|
_frameTimer = 0;
|
|
|
|
_timeout = 0;
|
|
|
|
_field1C = 0;
|
|
|
|
_abortMode = 0;
|
|
|
|
_nounList[0] = _nounList[1] = _nounList[2] = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
|
|
|
Hotspot::Hotspot() {
|
|
|
|
_facing = 0;
|
|
|
|
_articleNumber = 0;
|
2014-03-03 00:42:41 -05:00
|
|
|
_cursor = CURSOR_NONE;
|
2014-02-25 09:21:19 -05:00
|
|
|
_vocabId = 0;
|
|
|
|
_verbId = 0;
|
|
|
|
}
|
|
|
|
|
|
|
|
Hotspot::Hotspot(Common::SeekableReadStream &f) {
|
|
|
|
_bounds.left = f.readSint16LE();
|
|
|
|
_bounds.top = f.readSint16LE();
|
|
|
|
_bounds.right = f.readSint16LE();
|
|
|
|
_bounds.bottom = f.readSint16LE();
|
|
|
|
_feetPos.x = f.readSint16LE();
|
|
|
|
_feetPos.y = f.readSint16LE();
|
|
|
|
_facing = f.readByte();
|
|
|
|
_articleNumber = f.readByte();
|
|
|
|
f.skip(1);
|
2014-03-03 00:42:41 -05:00
|
|
|
_cursor = (CursorType)f.readByte();
|
2014-02-25 09:21:19 -05:00
|
|
|
_vocabId = f.readUint16LE();
|
|
|
|
_verbId = f.readUint16LE();
|
|
|
|
}
|
|
|
|
|
2014-02-25 23:10:51 -05:00
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-02-28 20:37:42 -05:00
|
|
|
void ARTHeader::load(Common::SeekableReadStream *f) {
|
|
|
|
// Read in dimensions of image
|
|
|
|
_width = f->readUint16LE();
|
|
|
|
_height = f->readUint16LE();
|
2014-02-25 23:10:51 -05:00
|
|
|
|
2014-02-28 20:37:42 -05:00
|
|
|
// Read in palette information
|
|
|
|
int palCount = f->readUint16LE();
|
|
|
|
for (int i = 0; i < palCount; ++i) {
|
2014-02-25 23:10:51 -05:00
|
|
|
RGB6 rgb;
|
2014-02-28 20:37:42 -05:00
|
|
|
rgb.load(f);
|
2014-02-25 23:10:51 -05:00
|
|
|
_palette.push_back(rgb);
|
|
|
|
}
|
2014-02-28 20:37:42 -05:00
|
|
|
f->skip(6 * (256 - palCount));
|
2014-02-25 23:10:51 -05:00
|
|
|
|
2014-02-28 20:37:42 -05:00
|
|
|
// Read unknown???
|
|
|
|
palCount = f->readUint16LE();
|
2014-02-25 23:10:51 -05:00
|
|
|
for (int i = 0; i < palCount; ++i) {
|
|
|
|
RGB4 rgb;
|
2014-02-28 20:37:42 -05:00
|
|
|
rgb.r = f->readByte();
|
|
|
|
rgb.g = f->readByte();
|
|
|
|
rgb.b = f->readByte();
|
|
|
|
rgb.u = f->readByte();
|
2014-02-25 23:10:51 -05:00
|
|
|
|
2014-03-02 10:49:20 -05:00
|
|
|
_palAnimData.push_back(rgb);
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-02 10:49:20 -05:00
|
|
|
void SceneNode::load(Common::SeekableReadStream *f) {
|
|
|
|
_walkPos.x = f->readSint16LE();
|
|
|
|
_walkPos.y = f->readSint16LE();
|
|
|
|
for (int i = 0; i < MAX_ROUTE_NODES; ++i)
|
|
|
|
_indexes[i] = f->readUint16LE();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-02 23:09:17 -05:00
|
|
|
InterfaceSurface::InterfaceSurface(MADSEngine *vm): _vm(vm) {
|
|
|
|
_category = CAT_NONE;
|
2014-03-03 00:42:41 -05:00
|
|
|
_screenObjectsCount = 0;
|
2014-03-02 23:09:17 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void InterfaceSurface::elementHighlighted() {
|
|
|
|
warning("TODO: InterfaceSurface::elementHighlighted");
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
void SceneInfo::SpriteInfo::load(Common::SeekableReadStream *f) {
|
|
|
|
f->skip(3);
|
|
|
|
_spriteSetIndex = f->readByte();
|
|
|
|
f->skip(2);
|
|
|
|
_position.x = f->readSint16LE();
|
|
|
|
_position.y = f->readSint16LE();
|
|
|
|
_depth = f->readByte();
|
|
|
|
_scale = f->readByte();
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-02 23:09:17 -05:00
|
|
|
void InterfaceSurface::load(const Common::String &resName) {
|
2014-03-02 16:42:39 -05:00
|
|
|
File f(resName);
|
|
|
|
MadsPack madsPack(&f);
|
|
|
|
|
|
|
|
// Load in the palette
|
|
|
|
Common::SeekableReadStream *palStream = madsPack.getItemStream(0);
|
|
|
|
|
2014-03-02 23:09:17 -05:00
|
|
|
RGB4 *gamePalP = &_vm->_palette->_gamePalette[0];
|
|
|
|
byte *palP = &_vm->_palette->_mainPalette[0];
|
2014-03-02 16:42:39 -05:00
|
|
|
|
|
|
|
for (int i = 0; i < 16; ++i, gamePalP++, palP += 3) {
|
|
|
|
palP[0] = palStream->readByte();
|
|
|
|
palP[1] = palStream->readByte();
|
|
|
|
palP[2] = palStream->readByte();
|
|
|
|
gamePalP->r |= 1;
|
|
|
|
palStream->skip(3);
|
|
|
|
}
|
|
|
|
delete palStream;
|
|
|
|
|
|
|
|
// set the size for the interface
|
|
|
|
setSize(MADS_SCREEN_WIDTH, MADS_INTERFACE_HEIGHT);
|
|
|
|
Common::SeekableReadStream *pixelsStream = madsPack.getItemStream(1);
|
|
|
|
pixelsStream->read(getData(), MADS_SCREEN_WIDTH * MADS_INTERFACE_HEIGHT);
|
|
|
|
delete pixelsStream;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-01 22:53:08 -05:00
|
|
|
SceneInfo *SceneInfo::init(MADSEngine *vm) {
|
|
|
|
if (vm->getGameID() == GType_RexNebular) {
|
|
|
|
return new SceneInfoNebular(vm);
|
|
|
|
}
|
|
|
|
else {
|
|
|
|
return new SceneInfo(vm);
|
|
|
|
}
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
|
2014-03-01 22:53:08 -05:00
|
|
|
void SceneInfo::load(int sceneId, int v1, const Common::String &resName,
|
2014-02-25 23:10:51 -05:00
|
|
|
int flags, MSurface &depthSurface, MSurface &bgSurface) {
|
|
|
|
bool sceneFlag = sceneId >= 0;
|
|
|
|
|
|
|
|
// Figure out the resource to use
|
|
|
|
Common::String resourceName;
|
|
|
|
if (sceneFlag) {
|
|
|
|
resourceName = Resources::formatName(RESPREFIX_RM, sceneId, ".DAT");
|
|
|
|
} else {
|
|
|
|
resourceName = "*" + Resources::formatResource(resName, resName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Open the scene info resource for access
|
2014-03-01 20:19:02 -05:00
|
|
|
File infoFile(resourceName);
|
|
|
|
MadsPack infoPack(&infoFile);
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
// Read in basic data
|
2014-03-01 20:19:02 -05:00
|
|
|
Common::SeekableReadStream *infoStream = infoPack.getItemStream(0);
|
|
|
|
_sceneId = infoStream->readUint16LE();
|
|
|
|
_artFileNum = infoStream->readUint16LE();
|
|
|
|
_depthStyle = infoStream->readUint16LE();
|
|
|
|
_width = infoStream->readUint16LE();
|
|
|
|
_height = infoStream->readUint16LE();
|
2014-03-02 10:49:20 -05:00
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
infoStream->skip(24);
|
2014-03-02 10:49:20 -05:00
|
|
|
|
|
|
|
int nodeCount = infoStream->readUint16LE();
|
2014-03-01 20:19:02 -05:00
|
|
|
_yBandsEnd = infoStream->readUint16LE();
|
|
|
|
_yBandsStart = infoStream->readUint16LE();
|
|
|
|
_maxScale = infoStream->readUint16LE();
|
|
|
|
_minScale = infoStream->readUint16LE();
|
2014-03-02 10:49:20 -05:00
|
|
|
for (int i = 0; i < DEPTH_BANDS_SIZE; ++i)
|
2014-03-01 20:19:02 -05:00
|
|
|
_depthList[i] = infoStream->readUint16LE();
|
|
|
|
_field4A = infoStream->readUint16LE();
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
// Load the set of objects that are associated with the scene
|
|
|
|
for (int i = 0; i < 20; ++i) {
|
2014-03-02 10:49:20 -05:00
|
|
|
SceneNode node;
|
|
|
|
node.load(infoStream);
|
|
|
|
|
|
|
|
if (i < nodeCount)
|
|
|
|
_nodes.push_back(node);
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
int spriteSetsCount = infoStream->readUint16LE();
|
|
|
|
int spriteInfoCount = infoStream->readUint16LE();
|
2014-02-25 23:10:51 -05:00
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
// Load in sprite sets
|
|
|
|
Common::StringArray setNames;
|
|
|
|
for (int i = 0; i < 10; ++i) {
|
2014-02-25 23:10:51 -05:00
|
|
|
char name[64];
|
2014-03-01 20:19:02 -05:00
|
|
|
infoStream->read(name, 64);
|
|
|
|
|
|
|
|
if (i < spriteSetsCount)
|
|
|
|
setNames.push_back(Common::String(name));
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
// Load in sprite draw information
|
|
|
|
Common::Array<SpriteInfo> spriteInfo;
|
|
|
|
for (int i = 0; i < 50; ++i) {
|
|
|
|
SpriteInfo info;
|
|
|
|
info.load(infoStream);
|
|
|
|
|
|
|
|
if (i < spriteInfoCount)
|
|
|
|
spriteInfo.push_back(info);
|
|
|
|
}
|
|
|
|
|
|
|
|
delete infoStream;
|
2014-02-25 23:10:51 -05:00
|
|
|
infoFile.close();
|
2014-03-01 20:19:02 -05:00
|
|
|
|
2014-02-25 23:10:51 -05:00
|
|
|
int width = _width;
|
|
|
|
int height = _height;
|
|
|
|
|
|
|
|
if (!bgSurface.getPixels()) {
|
|
|
|
bgSurface.setSize(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_depthStyle == 2)
|
|
|
|
width >>= 2;
|
|
|
|
if (!depthSurface.getPixels()) {
|
|
|
|
depthSurface.setSize(width, height);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load the depth surface with the scene codes
|
|
|
|
loadCodes(depthSurface);
|
|
|
|
|
|
|
|
// Get the ART resource
|
|
|
|
if (sceneFlag) {
|
2014-03-01 20:19:02 -05:00
|
|
|
resourceName = Resources::formatName(RESPREFIX_RM, _artFileNum, ".ART");
|
2014-02-25 23:10:51 -05:00
|
|
|
} else {
|
|
|
|
resourceName = "*" + Resources::formatResource(resName, resName);
|
|
|
|
}
|
|
|
|
|
|
|
|
// Load in the ART header and palette
|
|
|
|
File artFile(resourceName);
|
2014-02-28 20:37:42 -05:00
|
|
|
MadsPack artResource(&artFile);
|
|
|
|
Common::SeekableReadStream *stream = artResource.getItemStream(0);
|
|
|
|
|
2014-02-25 23:10:51 -05:00
|
|
|
ARTHeader artHeader;
|
2014-02-28 20:37:42 -05:00
|
|
|
artHeader.load(stream);
|
2014-03-01 20:19:02 -05:00
|
|
|
delete stream;
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
// Copy out the palette data
|
2014-03-02 10:49:20 -05:00
|
|
|
for (uint i = 0; i < artHeader._palAnimData.size(); ++i)
|
|
|
|
_palAnimData.push_back(artHeader._palAnimData[i]);
|
2014-02-28 20:37:42 -05:00
|
|
|
|
2014-02-25 23:10:51 -05:00
|
|
|
if (!(flags & 1)) {
|
2014-02-28 20:37:42 -05:00
|
|
|
if (!_vm->_palette->_paletteUsage.empty()) {
|
|
|
|
_vm->_palette->_paletteUsage.getKeyEntries(artHeader._palette);
|
|
|
|
_vm->_palette->_paletteUsage.prioritize(artHeader._palette);
|
|
|
|
}
|
|
|
|
|
|
|
|
_field4C = _vm->_palette->_paletteUsage.process(artHeader._palette, 0xF800);
|
|
|
|
if (_field4C > 0) {
|
|
|
|
_vm->_palette->_paletteUsage.transform(artHeader._palette);
|
|
|
|
|
2014-03-02 10:49:20 -05:00
|
|
|
for (uint i = 0; i < _palAnimData.size(); ++i) {
|
|
|
|
byte g = _palAnimData[i].g;
|
|
|
|
_palAnimData[g].b = artHeader._palAnimData[g].u;
|
2014-02-28 20:37:42 -05:00
|
|
|
}
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
}
|
2014-02-28 20:37:42 -05:00
|
|
|
|
|
|
|
// Read in the background surface data
|
|
|
|
assert(_width == bgSurface.w && _height == bgSurface.h);
|
2014-03-01 22:53:08 -05:00
|
|
|
stream = artResource.getItemStream(1);
|
2014-02-28 20:37:42 -05:00
|
|
|
stream->read(bgSurface.getPixels(), bgSurface.w * bgSurface.h);
|
|
|
|
|
2014-03-01 22:53:08 -05:00
|
|
|
// Close the ART file
|
|
|
|
delete stream;
|
|
|
|
artFile.close();
|
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
Common::Array<SpriteAsset *> spriteSets;
|
2014-03-02 16:42:39 -05:00
|
|
|
Common::Array<int> indexList;
|
2014-03-01 20:19:02 -05:00
|
|
|
|
2014-02-28 20:37:42 -05:00
|
|
|
if (flags & 1) {
|
2014-03-01 20:19:02 -05:00
|
|
|
for (uint i = 0; i < setNames.size(); ++i) {
|
2014-02-28 20:37:42 -05:00
|
|
|
Common::String setResName;
|
|
|
|
if (sceneFlag || resName.hasPrefix("*"))
|
|
|
|
setResName += "*";
|
2014-03-01 20:19:02 -05:00
|
|
|
setResName += setNames[i];
|
2014-02-28 20:37:42 -05:00
|
|
|
|
|
|
|
SpriteAsset *sprites = new SpriteAsset(_vm, setResName, flags);
|
|
|
|
spriteSets.push_back(sprites);
|
2014-03-02 16:42:39 -05:00
|
|
|
indexList.push_back(-1); // TODO:: sprites->_field6
|
2014-02-28 20:37:42 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2014-03-02 16:42:39 -05:00
|
|
|
warning("TODO: sub_201E4(indexList, namesCount, &pal data2");
|
2014-03-01 20:19:02 -05:00
|
|
|
|
|
|
|
for (uint i = 0; i < spriteInfo.size(); ++i) {
|
|
|
|
SpriteInfo &si = spriteInfo[i];
|
|
|
|
SpriteAsset *asset = spriteSets[si._spriteSetIndex];
|
|
|
|
assert(asset && _depthStyle != 2);
|
2014-02-28 20:37:42 -05:00
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
asset->drawScaled(asset->getCount(), depthSurface, bgSurface,
|
|
|
|
si._scale, si._depth, si._position);
|
|
|
|
}
|
2014-02-28 20:37:42 -05:00
|
|
|
|
2014-03-01 20:19:02 -05:00
|
|
|
// Free the sprite sets
|
|
|
|
for (int i = (int)spriteSets.size() - 1; i >= 0; --i) {
|
|
|
|
warning("TODO: sub_201C8 SPRITE_SET.field_6");
|
|
|
|
delete spriteSets[i];
|
|
|
|
}
|
2014-02-25 23:10:51 -05:00
|
|
|
}
|
|
|
|
|
|
|
|
void SceneInfo::loadCodes(MSurface &depthSurface) {
|
|
|
|
File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT"));
|
2014-03-01 22:53:08 -05:00
|
|
|
MadsPack codesPack(&f);
|
|
|
|
Common::SeekableReadStream *stream = codesPack.getItemStream(0);
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
uint16 width = _width;
|
|
|
|
uint16 height = _height;
|
2014-03-01 22:53:08 -05:00
|
|
|
byte *walkMap = new byte[stream->size()];
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
depthSurface.setSize(width, height);
|
2014-03-01 22:53:08 -05:00
|
|
|
stream->read(walkMap, f.size());
|
|
|
|
delete stream;
|
|
|
|
f.close();
|
2014-02-25 23:10:51 -05:00
|
|
|
|
|
|
|
byte *ptr = (byte *)depthSurface.getPixels();
|
|
|
|
|
|
|
|
for (int y = 0; y < height; y++) {
|
|
|
|
for (int x = 0; x < width; x++) {
|
|
|
|
int ofs = x + (y * width);
|
|
|
|
if ((walkMap[ofs / 8] << (ofs % 8)) & 0x80)
|
|
|
|
*ptr++ = 1; // walkable
|
|
|
|
else
|
|
|
|
*ptr++ = 0;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
delete[] walkMap;
|
|
|
|
}
|
|
|
|
|
|
|
|
/*------------------------------------------------------------------------*/
|
|
|
|
|
2014-03-01 22:53:08 -05:00
|
|
|
void SceneInfoNebular::loadCodes(MSurface &depthSurface) {
|
|
|
|
File f(Resources::formatName(RESPREFIX_RM, _sceneId, ".DAT"));
|
|
|
|
MadsPack codesPack(&f);
|
|
|
|
Common::SeekableReadStream *stream = codesPack.getItemStream(0);
|
|
|
|
|
|
|
|
byte *destP = depthSurface.getData();
|
|
|
|
byte *endP = depthSurface.getBasePtr(0, depthSurface.h);
|
|
|
|
|
|
|
|
byte runLength = stream->readByte();
|
|
|
|
while (destP < endP && runLength > 0) {
|
|
|
|
byte runValue = stream->readByte();
|
|
|
|
|
|
|
|
// Write out the run length
|
|
|
|
Common::fill(destP, destP + runLength, runValue);
|
|
|
|
destP += runLength;
|
|
|
|
|
|
|
|
// Get the next run length
|
|
|
|
runLength = stream->readByte();
|
|
|
|
}
|
|
|
|
|
|
|
|
if (destP < endP)
|
|
|
|
Common::fill(destP, endP, 0);
|
|
|
|
delete stream;
|
|
|
|
f.close();
|
|
|
|
}
|
|
|
|
|
2014-02-25 09:21:19 -05:00
|
|
|
} // End of namespace MADS
|