[Scummvm-cvs-logs] SF.net SVN: scummvm: [31600] scummvm/trunk/engines
thebluegr at users.sourceforge.net
thebluegr at users.sourceforge.net
Sun Apr 20 16:47:37 CEST 2008
Revision: 31600
http://scummvm.svn.sourceforge.net/scummvm/?rev=31600&view=rev
Author: thebluegr
Date: 2008-04-20 07:47:37 -0700 (Sun, 20 Apr 2008)
Log Message:
-----------
Initial import of the work in progress M4 engine
Added Paths:
-----------
scummvm/trunk/engines/m4/
scummvm/trunk/engines/m4/actor.cpp
scummvm/trunk/engines/m4/actor.h
scummvm/trunk/engines/m4/animation.cpp
scummvm/trunk/engines/m4/animation.h
scummvm/trunk/engines/m4/assets.cpp
scummvm/trunk/engines/m4/assets.h
scummvm/trunk/engines/m4/burger_data.h
scummvm/trunk/engines/m4/compression.cpp
scummvm/trunk/engines/m4/compression.h
scummvm/trunk/engines/m4/console.cpp
scummvm/trunk/engines/m4/console.h
scummvm/trunk/engines/m4/converse.cpp
scummvm/trunk/engines/m4/converse.h
scummvm/trunk/engines/m4/detection.cpp
scummvm/trunk/engines/m4/events.cpp
scummvm/trunk/engines/m4/events.h
scummvm/trunk/engines/m4/font.cpp
scummvm/trunk/engines/m4/font.h
scummvm/trunk/engines/m4/globals.cpp
scummvm/trunk/engines/m4/globals.h
scummvm/trunk/engines/m4/graphics.cpp
scummvm/trunk/engines/m4/graphics.h
scummvm/trunk/engines/m4/gui.cpp
scummvm/trunk/engines/m4/gui.h
scummvm/trunk/engines/m4/hotspot.cpp
scummvm/trunk/engines/m4/hotspot.h
scummvm/trunk/engines/m4/m4.cpp
scummvm/trunk/engines/m4/m4.h
scummvm/trunk/engines/m4/m4_menus.cpp
scummvm/trunk/engines/m4/m4_menus.h
scummvm/trunk/engines/m4/m4_views.cpp
scummvm/trunk/engines/m4/m4_views.h
scummvm/trunk/engines/m4/mads_anim.cpp
scummvm/trunk/engines/m4/mads_anim.h
scummvm/trunk/engines/m4/mads_menus.cpp
scummvm/trunk/engines/m4/mads_menus.h
scummvm/trunk/engines/m4/midi.cpp
scummvm/trunk/engines/m4/midi.h
scummvm/trunk/engines/m4/module.mk
scummvm/trunk/engines/m4/rails.cpp
scummvm/trunk/engines/m4/rails.h
scummvm/trunk/engines/m4/resource.cpp
scummvm/trunk/engines/m4/resource.h
scummvm/trunk/engines/m4/saveload.cpp
scummvm/trunk/engines/m4/saveload.h
scummvm/trunk/engines/m4/scene.cpp
scummvm/trunk/engines/m4/scene.h
scummvm/trunk/engines/m4/script.cpp
scummvm/trunk/engines/m4/script.h
scummvm/trunk/engines/m4/scripttab.h
scummvm/trunk/engines/m4/sound.cpp
scummvm/trunk/engines/m4/sound.h
scummvm/trunk/engines/m4/sprite.cpp
scummvm/trunk/engines/m4/sprite.h
scummvm/trunk/engines/m4/viewmgr.cpp
scummvm/trunk/engines/m4/viewmgr.h
scummvm/trunk/engines/m4/woodscript.cpp
scummvm/trunk/engines/m4/woodscript.h
scummvm/trunk/engines/m4/ws_machine.cpp
scummvm/trunk/engines/m4/ws_sequence.cpp
Added: scummvm/trunk/engines/m4/actor.cpp
===================================================================
--- scummvm/trunk/engines/m4/actor.cpp (rev 0)
+++ scummvm/trunk/engines/m4/actor.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,202 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/system.h"
+#include "common/array.h"
+#include "m4/actor.h"
+#include "m4/m4_views.h"
+#include "m4/assets.h"
+
+namespace M4 {
+
+#define WALKER_BURGER "Wilbur0%i" // wilbur, with a number denoting his current direction
+
+Actor::Actor(M4Engine *vm) : _vm(vm) {
+ _scaling = 100;
+ _direction = 5;
+ _walkerSprites.resize(10);
+ loadWalkers();
+}
+
+Actor::~Actor() {
+ unloadWalkers();
+}
+
+int Actor::getWalkerWidth() { return _walkerSprites[kFacingSouth]->getFrame(0)->w; }
+int Actor::getWalkerHeight() { return _walkerSprites[kFacingSouth]->getFrame(0)->h; }
+
+void Actor::placeWalkerSpriteAt(int spriteNum, int x, int y) {
+ if (_direction < 1 || _direction > 9) {
+ warning("Direction is %i, fixing", _direction);
+ _direction = 1; // TODO: this is a temporary fix
+ }
+ SpriteInfo info;
+ info.sprite = _walkerSprites[_direction]->getFrame(spriteNum);
+ info.hotX = info.hotY = 0;
+ info.width = info.sprite->w;
+ info.height = info.sprite->h;
+ info.scaleX = info.scaleY = _scaling;
+ info.palette = _walkerSprites[_direction]->getPalette();
+ info.inverseColorTable = _vm->_scene->getInverseColorTable();
+
+ _vm->_scene->drawSprite(x, y, info, Common::Rect(640, 400));
+}
+
+void Actor::loadWalkers() {
+ for (uint8 i = 1; i < 10; i++) {
+ if (i == 6)
+ continue; // walker sprite 6 is unused
+ loadWalkerDirection(i);
+ }
+}
+
+void Actor::loadWalkerDirection(uint8 direction) {
+ char name[20];
+ Common::SeekableReadStream *walkerS;
+
+ if (_vm->getGameType() == GType_Burger) {
+ sprintf(name, WALKER_BURGER, direction);
+ } else {
+ //warning("Actor::loadWalkerDirection: unspecified walker type, not loading walker");
+ // TODO: Master Lu walkers
+ return;
+ }
+
+ walkerS = _vm->res()->get(name);
+ _walkerSprites.insert_at(direction, new SpriteAsset(_vm, walkerS, walkerS->size(), name));
+ _vm->res()->toss(name);
+}
+
+void Actor::unloadWalkers() {
+ for (uint8 i = 9; i > 0; i--) {
+ if (i == 6)
+ continue; // walker sprite 6 is unused
+ SpriteAsset *tempSprite = _walkerSprites[i];
+ _walkerSprites.remove_at(i);
+ if (tempSprite)
+ delete tempSprite;
+ }
+}
+
+void Actor::setWalkerPalette() {
+ _vm->_palette->setPalette(_walkerSprites[kFacingSouthEast]->getPalette(), 0,
+ _walkerSprites[kFacingSouthEast]->getColorCount());
+}
+
+Inventory::Inventory(M4Engine *vm) : _vm(vm) {
+}
+
+Inventory::~Inventory() {
+ _inventory.clear();
+}
+
+void Inventory::registerObject(char* name, int32 scene, int32 icon) {
+ InventoryObject *newObject = new InventoryObject();
+ int newObjectIndex = 0;
+
+ // Capitalize registered inventory object names
+ str_upper(name);
+
+ newObject->name = strdup(name);
+ newObject->scene = scene;
+ newObject->icon = icon;
+
+ newObjectIndex = _inventory.size();
+
+ _inventory.push_back(newObject);
+
+ if (scene == BACKPACK)
+ addToBackpack(newObjectIndex);
+}
+
+void Inventory::moveObject(char* name, int32 scene) {
+ uint i = 0;
+
+ for (i = 0; i < _inventory.size(); i++) {
+ if (!scumm_stricmp(_inventory[i]->name, name)) {
+ if (_inventory[i]->scene == BACKPACK && scene != BACKPACK)
+ removeFromBackpack(i);
+
+ _inventory[i]->scene = scene;
+
+ if (scene == BACKPACK)
+ addToBackpack(i);
+
+ return;
+ }
+ }
+}
+
+void Inventory::addToBackpack(uint32 objectIndex) {
+ _vm->_interfaceView->inventoryAdd(_inventory[objectIndex]->name, "", _inventory[objectIndex]->icon);
+}
+
+void Inventory::removeFromBackpack(uint32 objectIndex) {
+ _vm->_interfaceView->inventoryRemove(_inventory[objectIndex]->name);
+}
+
+bool Inventory::isInCurrentScene(char* name) {
+ return (getScene(name) == _vm->_scene->getCurrentScene());
+}
+
+int Inventory::getScene(char* name) {
+ uint i = 0;
+
+ for (i = 0; i < _inventory.size(); i++) {
+ if (!scumm_stricmp(_inventory[i]->name, name))
+ return _inventory[i]->scene;
+ }
+ return UNKNOWN_OBJECT;
+}
+
+int Inventory::getIcon(char* name) {
+ uint i = 0;
+
+ for (i = 0; i < _inventory.size(); i++) {
+ if (!scumm_stricmp(_inventory[i]->name, name))
+ return _inventory[i]->icon;
+ }
+ return UNKNOWN_OBJECT;
+}
+
+int Inventory::getIndex(char* name) {
+ uint i = 0;
+
+ for (i = 0; i < _inventory.size(); i++) {
+ if (!scumm_stricmp(_inventory[i]->name, name))
+ return i;
+ }
+ return UNKNOWN_OBJECT;
+}
+
+void Inventory::clear() {
+ for (uint i = 0; i < _inventory.size(); i++) {
+ delete _inventory[i]->name;
+ delete _inventory[i];
+ _inventory.remove_at(i);
+ }
+}
+
+} // End of namespace M4
Property changes on: scummvm/trunk/engines/m4/actor.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/actor.h
===================================================================
--- scummvm/trunk/engines/m4/actor.h (rev 0)
+++ scummvm/trunk/engines/m4/actor.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,117 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_ACTOR_H
+#define M4_ACTOR_H
+
+#include "common/array.h"
+
+#include "m4/m4.h"
+#include "m4/scene.h"
+#include "m4/graphics.h"
+#include "m4/assets.h"
+
+namespace M4 {
+
+struct InventoryObject {
+ const char* name;
+ int32 scene;
+ int32 icon;
+};
+
+enum inventoryObjectFlags {
+ UNKNOWN_OBJECT = 997,
+ BACKPACK = 998,
+ NOWHERE = 999
+};
+
+enum WalkerDirection {
+ kFacingNorth = 1, // has shadow
+ kFacingNorthEast = 2, // has shadow
+ kFacingEast = 3, // has shadow
+ kFacingSouthEast = 4, // has shadow
+ kFacingSouth = 5, // has shadow
+ // 6 is unused
+ kFacingSouthAlt = 7, // no shadow
+ kFacingSouthWest = 8, // no shadow
+ kFacingWest = 9 // no shadow
+};
+
+class Actor {
+public:
+ Actor(M4Engine *vm);
+ ~Actor();
+ void placeWalkerSpriteAt(int spriteNum, int x, int y);
+ void setWalkerScaling(int scaling) { _scaling = scaling; }
+ int getWalkerScaling() { return _scaling; }
+ void setWalkerDirection(uint8 direction) { _direction = direction; }
+ uint8 getWalkerDirection() { return _direction; }
+ void setWalkerPalette();
+ int getWalkerWidth();
+ int getWalkerHeight();
+private:
+ M4Engine *_vm;
+ int _scaling;
+ uint8 _direction;
+ Common::Array<SpriteAsset*> _walkerSprites;
+
+ void loadWalkers();
+ void loadWalkerDirection(uint8 direction);
+ void unloadWalkers();
+};
+
+// TODO: perhaps the inventory and its view could be merged?
+// TODO: the original game capitalizes all inventory object names
+// internally, which we do as well, but perhaps we could make sure
+// that all object names are parsed with the same case and avoid
+// case-insensitive string comparing through scumm_stricmp, using
+// the normal strcmp method instead
+class Inventory {
+public:
+ Inventory(M4Engine *vm);
+ ~Inventory();
+ void clear();
+ void registerObject(char* name, int32 scene, int32 icon);
+ void moveObject(char* name, int32 scene);
+ void giveToPlayer(char* name) { moveObject(name, BACKPACK); }
+ void addToBackpack(uint32 objectIndex);
+ void removeFromBackpack(uint32 objectIndex);
+ bool isInBackpack(char* name) { return (getScene(name) == BACKPACK); }
+ bool isInScene(char* name, int32 scene) { return (getScene(name) == scene); }
+ bool isInCurrentScene(char* name);
+ int getScene(char* name);
+ int getIcon(char* name);
+ int getIndex(char* name);
+ int getTotalItems() { return _inventory.size(); }
+
+private:
+ M4Engine *_vm;
+ Common::Array<InventoryObject *> _inventory;
+};
+
+} // End of namespace M4
+
+
+#endif
Property changes on: scummvm/trunk/engines/m4/actor.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/animation.cpp
===================================================================
--- scummvm/trunk/engines/m4/animation.cpp (rev 0)
+++ scummvm/trunk/engines/m4/animation.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,210 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/assets.h"
+#include "m4/animation.h"
+#include "m4/compression.h"
+
+namespace M4 {
+
+// TODO: this code needs cleanup
+
+Animation::Animation(M4Engine *vm) {
+ _vm = vm;
+ _playing = false;
+}
+
+void Animation::loadFullScreen(const char *filename) {
+ _vm->_palette->deleteAllRanges();
+ load(filename);
+}
+
+void Animation::load(const char *filename) {
+ MadsPack anim(filename, _vm);
+ char buffer[20];
+
+ // Chunk 1: header
+ // header
+ // TODO: there are some unknown fields here, plus we don't read
+ // the entire chunk
+ Common::SeekableReadStream *animStream = anim.getItemStream(0);
+ Common::SeekableReadStream *spriteSeriesStream;
+ //printf("Chunk 0, size %i\n", animStream->size());
+ _seriesCount = animStream->readUint16LE();
+ _frameCount = animStream->readUint16LE();
+ _frameEntryCount = animStream->readUint16LE();
+
+ // Unknown
+ for (int i = 0; i < 43; i++)
+ animStream->readByte();
+
+ _spriteSeriesNames = new Common::String[_seriesCount];
+ printf("%i sprite series\n", _seriesCount);
+
+ // TODO: for now, we only load the first sprite series
+ if (_seriesCount > 1)
+ printf("TODO: Anim has %i sprite series, for now, we only load the first one\n", _seriesCount);
+ _seriesCount = 1; // TODO
+
+ for (int i = 0; i < _seriesCount; i++) {
+ animStream->read(buffer, 13);
+ _spriteSeriesNames[i] = Common::String(buffer);
+ //printf("%03d: %s\n", i, _spriteSeriesNames[i].c_str());
+
+ spriteSeriesStream = _vm->res()->get(_spriteSeriesNames[i].c_str());
+ _spriteSeries = new SpriteAsset(_vm, spriteSeriesStream,
+ spriteSeriesStream->size(), _spriteSeriesNames[i].c_str());
+ _vm->res()->toss(_spriteSeriesNames[i].c_str());
+
+ // Adjust the palette of the sprites in the sprite series
+ // so that they can be displayed on screen correctly
+ RGBList *palData = new RGBList(_spriteSeries->getColorCount(), _spriteSeries->getPalette(), true);
+ _vm->_palette->addRange(palData);
+
+ for (int k = 0; k < _spriteSeries->getCount(); k++) {
+ M4Sprite *spr = _spriteSeries->getFrame(k);
+ spr->translate(palData); // sprite pixel translation
+ }
+ }
+
+ //printf("End pos: %i\n", animStream->pos());
+
+ delete animStream;
+
+ // ------------------
+
+ // Chunk 2: anim info
+ AnimationFrame frame;
+ animStream = anim.getItemStream(1);
+ //printf("Chunk 1, size %i\n", animStream->size());
+
+ _frameEntries = new AnimationFrame[_frameEntryCount];
+
+ for (int i = 0; i < _frameEntryCount; i++) {
+
+ frame.animFrameIndex = animStream->readUint16LE();
+ frame.u = animStream->readByte();
+ frame.seriesIndex = animStream->readByte();
+ frame.seriesFrameIndex = animStream->readUint16LE();
+ frame.x = animStream->readUint16LE();
+ frame.y = animStream->readUint16LE();
+ frame.v = animStream->readByte();
+ frame.w = animStream->readByte();
+
+ _frameEntries[i] = frame;
+
+ /*
+ printf(
+ "animFrameIndex = %4d, "
+ "u = %3d, "
+ "seriesIndex = %3d, "
+ "seriesFrameIndex = %6d, "
+ "x = %3d, "
+ "y = %3d, "
+ "v = %3d, "
+ "w = %3d\n",
+
+ frame.animFrameIndex,
+ frame.u,
+ frame.seriesIndex,
+ frame.seriesFrameIndex,
+ frame.x,
+ frame.y,
+ frame.v,
+ frame.w
+ );
+ */
+ }
+ //printf("End pos: %i\n", animStream->pos());
+
+ delete animStream;
+
+ // Chunk 3: unknown (seems to be sound data?)
+ // TODO
+}
+
+Animation::~Animation() {
+ //delete[] _spriteSeriesNames;
+ //delete[] _spriteSeries;
+ //delete[] _frameEntries;
+}
+
+void Animation::start() {
+ _curFrame = 0;
+ _curFrameEntry = 0;
+ //for (int i = 0; i < _seriesCount; i++) {
+ //_spriteSeries[i] = new SpriteSeries((char*)_spriteSeriesNames[i].c_str());
+ //}
+ _playing = true;
+ updateAnim();
+}
+
+bool Animation::updateAnim() {
+ if (!_playing)
+ return true;
+
+ // Get the scene background surface
+ M4Surface *bg = _vm->_scene->getBackgroundSurface();
+
+ while (_frameEntries[_curFrameEntry].animFrameIndex == _curFrame) {
+ AnimationFrame *frame = &_frameEntries[_curFrameEntry];
+ int seriesFrameIndex = (frame->seriesFrameIndex & 0x7FFF) - 1;
+
+ // Write the sprite onto the screen
+ M4Sprite *spr = _spriteSeries->getFrame(seriesFrameIndex);
+
+ // FIXME: We assume that the transparent color is the color of the top left pixel
+ byte *transparentColor = (byte *)spr->pixels;
+
+ // FIXME: correct x, y
+ spr->copyTo(bg, frame->x, frame->y, (int)*transparentColor);
+
+ // HACK: wait a bit
+ g_system->delayMillis(100);
+
+ //printf("_curFrameEntry = %d\n", _curFrameEntry);
+ _curFrameEntry++;
+ }
+
+ //printf("_curFrame = %d\n", _curFrame);
+
+ _curFrame++;
+ if (_curFrame >= _frameCount) // anim done
+ stop();
+
+ return _curFrame >= _frameCount;
+}
+
+void Animation::stop() {
+ _playing = false;
+
+ for (int i = 0; i < _seriesCount; i++) {
+ // TODO: cleanup
+ //delete _spriteSeries[i];
+ //_spriteSeries[i] = NULL;
+ }
+}
+
+} // End of namespace M4
Property changes on: scummvm/trunk/engines/m4/animation.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/animation.h
===================================================================
--- scummvm/trunk/engines/m4/animation.h (rev 0)
+++ scummvm/trunk/engines/m4/animation.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,69 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_ANIMATION_H
+#define M4_ANIMATION_H
+
+#include "m4/m4.h"
+#include "m4/graphics.h"
+#include "m4/assets.h"
+
+namespace M4 {
+
+struct AnimationFrame {
+ uint16 animFrameIndex;
+ byte u;
+ byte seriesIndex;
+ uint16 seriesFrameIndex;
+ uint16 x, y;
+ byte v, w;
+};
+
+class Animation {
+ public:
+ Animation(M4Engine *vm);
+ ~Animation();
+
+ void load(const char *filename);
+ void loadFullScreen(const char *filename);
+ void start();
+ bool updateAnim();
+ void stop();
+
+ private:
+ bool _playing;
+ M4Engine *_vm;
+ int _seriesCount;
+ int _frameCount;
+ int _frameEntryCount;
+ AnimationFrame *_frameEntries;
+ Common::String *_spriteSeriesNames;
+ SpriteAsset *_spriteSeries;
+ int _curFrame, _curFrameEntry;
+};
+
+} // End of namespace M4
+
+#endif
Property changes on: scummvm/trunk/engines/m4/animation.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/assets.cpp
===================================================================
--- scummvm/trunk/engines/m4/assets.cpp (rev 0)
+++ scummvm/trunk/engines/m4/assets.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,544 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/assets.h"
+#include "m4/globals.h"
+#include "m4/compression.h"
+
+namespace M4 {
+
+BaseAsset::BaseAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : _vm(vm) {
+}
+
+BaseAsset::~BaseAsset() {
+}
+
+MachineAsset::MachineAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+ uint32 stateCount = stream->readUint32LE();
+ for (uint32 curState = 0; curState < stateCount; curState++) {
+ uint32 stateOffset = stream->readUint32LE();
+ _stateTable.push_back(stateOffset);
+ }
+ _codeSize = size - 4 - 4 * stateCount;
+ _code = new byte[_codeSize];
+ stream->read(_code, _codeSize);
+}
+
+MachineAsset::~MachineAsset() {
+ delete[] _code;
+}
+
+void MachineAsset::getCode(byte *&code, uint32 &codeSize) {
+ code = _code;
+ codeSize = _codeSize;
+}
+
+uint32 MachineAsset::getStateOffset(uint32 state) {
+ assert(state < _stateTable.size());
+ return _stateTable[state];
+}
+
+SequenceAsset::SequenceAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+ _localVarCount = stream->readUint32LE();
+ _codeSize = size - 4;
+ _code = new byte[_codeSize];
+ stream->read(_code, _codeSize);
+}
+
+SequenceAsset::~SequenceAsset() {
+ delete[] _code;
+}
+
+void SequenceAsset::getCode(byte *&code, uint32 &codeSize) {
+ code = _code;
+ codeSize = _codeSize;
+}
+
+
+DataAsset::DataAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name) : BaseAsset(vm, stream, size, name) {
+
+ _recCount = stream->readUint32LE();
+ _recSize = stream->readUint32LE();
+ _dataSize = _recCount * _recSize;
+ _data = new long[_dataSize];
+ for (uint32 i = 0; i < _dataSize; i++)
+ _data[i] = (long)stream->readUint32LE();
+
+}
+
+DataAsset::~DataAsset() {
+ delete _data;
+}
+
+long *DataAsset::getRow(int index) {
+ assert(index < _recCount);
+ return &_data[_recSize * index];
+}
+
+SpriteAsset::SpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream) : BaseAsset(vm, stream, size, name) {
+ _stream = stream;
+
+ if (_vm->isM4()) {
+ loadM4SpriteAsset(vm, stream, asStream);
+ } else {
+ loadMadsSpriteAsset(vm, stream);
+ }
+}
+
+void SpriteAsset::loadM4SpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream, bool asStream) {
+ bool isBigEndian = false;
+ uint32 frameOffset;
+
+ uint32 header = _stream->readUint32LE();
+ if (header == HEAD_M4SS) {
+ printf("LE-encoded sprite\n");
+ } else {
+ printf("BE-encoded sprite\n");
+ isBigEndian = true;
+ }
+
+ _srcSize = parseSprite(isBigEndian);
+
+ _stream->readUint32LE();
+ _frameRate = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ _pixelSpeed = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ _maxWidth = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ _maxHeight = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ _stream->skip(6 * 4);
+ _frameCount = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+
+ printf("SpriteAsset::SpriteAsset() srcSize = %d; frameRate = %04X; pixelSpeed = %04X; maxWidth = %d; maxHeight = %d; frameCount = %d\n", _srcSize, _frameRate, _pixelSpeed, _maxWidth, _maxHeight, _frameCount);
+
+ for (int curFrame = 0; curFrame < _frameCount; curFrame++) {
+ frameOffset = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ _frameOffsets.push_back(frameOffset);
+ }
+ _frameOffsets.push_back(_srcSize - 48 - _frameCount * 4);
+
+ _frameStartOffset = _stream->pos();
+
+ // We don't need to load frames when streaming
+ if (asStream)
+ return;
+
+ for (int curFrame = 0; curFrame < _frameCount; curFrame++) {
+ frameOffset = _frameStartOffset + _frameOffsets[curFrame];
+ _stream->seek(frameOffset);
+
+ SpriteAssetFrame frame;
+ loadFrameHeader(frame, isBigEndian);
+
+ // Load & unpack RLE data if it's not a streaming animation
+ if (frame.stream != 1) {
+
+ frame.frame = new M4Sprite(stream, frame.x, frame.y, frame.w, frame.h, true, frame.comp);
+#if 0
+ char fn[512];
+ sprintf(fn, "%04d.raw", curFrame);
+ FILE *h = fopen(fn, "wb");
+ fwrite((byte*)frame.frame->getData(), frame.w * frame.h, 1, h);
+ fclose(h);
+#endif
+ }
+
+ _frames.push_back(frame);
+
+ }
+
+}
+
+void SpriteAsset::loadMadsSpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream) {
+ int curFrame = 0;
+ uint32 frameOffset = 0;
+ MadsPack sprite(stream);
+ _frameRate = 0;
+ _pixelSpeed = 0;
+ _maxWidth = 0;
+ _maxHeight = 0;
+
+ Common::SeekableReadStream *spriteStream = sprite.getItemStream(0);
+ for (int i = 0; i < 19; i++) {
+ spriteStream->readUint16LE();
+ }
+ _frameCount = spriteStream->readUint16LE();
+ // we skip the rest of the data
+ delete spriteStream;
+
+ // Get the palette data
+ spriteStream = sprite.getItemStream(2);
+ int numColors = 0;
+ RGB8 *palData = Palette::decodeMadsPalette(spriteStream, &numColors);
+ Common::copy(palData, &palData[numColors], &_palette[0]);
+ if (numColors < 256)
+ Common::set_to((byte *)&_palette[numColors], (byte *)&_palette[256], 0);
+ _colorCount = numColors;
+ delete[] palData;
+ delete spriteStream;
+
+ spriteStream = sprite.getItemStream(1);
+ Common::SeekableReadStream *spriteDataStream = sprite.getItemStream(3);
+ SpriteAssetFrame frame;
+ for (curFrame = 0; curFrame < _frameCount; curFrame++) {
+ frame.comp = 0;
+ frameOffset = spriteStream->readUint32LE();
+ _frameOffsets.push_back(frameOffset);
+ spriteStream->readUint32LE(); // frame size
+ frame.x = spriteStream->readUint16LE();
+ frame.y = spriteStream->readUint16LE();
+ frame.w = spriteStream->readUint16LE();
+ frame.h = spriteStream->readUint16LE();
+ if (curFrame == 0)
+ printf("%i frames, x = %i, y = %i, w = %i, h = %i\n", _frameCount, frame.x, frame.y, frame.w, frame.h);
+
+ frame.frame = new M4Sprite(spriteDataStream, frame.x, frame.y, frame.w, frame.h, false);
+ _frames.push_back(frame);
+ }
+ delete spriteStream;
+ delete spriteDataStream;
+}
+
+SpriteAsset::~SpriteAsset() {
+ for (Common::Array<SpriteAssetFrame>::iterator it = _frames.begin(); it != _frames.end(); it++) {
+ delete (*it).frame;
+ }
+}
+
+int32 SpriteAsset::parseSprite(bool isBigEndian) {
+
+ uint32 format, chunkType, chunkSize = 0;
+
+ _colorCount = 0;
+
+ format = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+
+ chunkType = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+
+ if (chunkType == CELS__PAL) {
+ chunkSize = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ uint32 numColors = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ // TODO
+ //if (palette) {
+ // TODO: A sprite set palette specifies the indexes, which need not start at
+ // index 0. For now, I'm simply preloading the currently active palette
+ // before starting to replace existing entries
+
+ _vm->_palette->grabPalette((byte *) _palette, 0, 256);
+ _colorCount = 0;
+
+ for (uint32 i = 0; i < numColors; i++) {
+ uint32 paletteEntry = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ uint index = (paletteEntry >> 24) & 0xFF;
+
+ _palette[index].r = ((paletteEntry >> 16) & 0xFF) << 2;
+ _palette[index].g = ((paletteEntry >> 8) & 0xFF) << 2;
+ _palette[index].b = (paletteEntry & 0xFF) << 2;
+
+ _colorCount = MAX(_colorCount, index);
+ }
+
+ /*
+ } else {
+ stream.seek(colorCount, )
+ data += colorCount * 4;
+ }
+ */
+ chunkType = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ }
+
+ if (chunkType == CELS___SS) {
+ chunkSize = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ } else {
+ warning("SpriteAsset::parseSprite() Expected chunk type %08X, got %08X", CELS___SS, chunkType);
+ }
+
+ return chunkSize;
+
+}
+
+void SpriteAsset::loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian) {
+ _stream->readUint32LE();
+ frameHeader.stream = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.x = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.y = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.w = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.h = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.comp = (!isBigEndian) ? _stream->readUint32LE() : _stream->readUint32BE();
+ frameHeader.frame = NULL;
+ _stream->seek(8 * 4, SEEK_CUR);
+ //printf("SpriteAsset::loadFrameHeader() stream = %d; x = %d; y = %d; w = %d; h = %d; comp = %d\n", frameHeader.stream, frameHeader.x, frameHeader.y, frameHeader.w, frameHeader.h, frameHeader.comp);
+}
+
+M4Sprite *SpriteAsset::getFrame(int frameIndex) {
+ return _frames[frameIndex].frame;
+}
+
+void SpriteAsset::loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY) {
+ uint32 frameOffset = _frameStartOffset + _frameOffsets[frameIndex];
+ _stream->seek(frameOffset);
+
+ SpriteAssetFrame frameHeader;
+ loadFrameHeader(frameHeader);
+
+ if (frameHeader.w > 0 && frameHeader.h > 0) {
+ Common::MemoryReadStream *frameData = _stream->readStream(getFrameSize(frameIndex));
+ if (frameHeader.stream) {
+ frame->loadDeltaRle(frameData, destX - frameHeader.x, destY - frameHeader.y);
+ } else {
+ frame->loadRle(frameData);
+ }
+ delete frameData;
+ }
+
+}
+
+RGBList *SpriteAsset::getRgbList() {
+ RGBList *result = new RGBList(_colorCount);
+ Common::copy((byte *)&_palette[0], (byte *)&_palette[_colorCount], (byte *)result->data());
+ return result;
+}
+
+void SpriteAsset::translate(RGBList *list, bool isTransparent) {
+ for (int frameIndex = 0; frameIndex < _frameCount; ++frameIndex)
+ _frames[frameIndex].frame->translate(list, isTransparent);
+}
+
+int32 SpriteAsset::getFrameSize(int index) {
+ /*
+ if (index + 1 == _frameCount) {
+ } else {
+
+ }
+ */
+ return _frameOffsets[index + 1] - _frameOffsets[index];
+}
+
+AssetManager::AssetManager(M4Engine *vm) {
+
+ _vm = vm;
+
+ /* Initialize asset arrays */
+ for (int i = 0; i < 256; i++) {
+ _MACH[i] = NULL;
+ _SEQU[i] = NULL;
+ _DATA[i] = NULL;
+ _CELS[i] = NULL;
+ }
+
+}
+
+AssetManager::~AssetManager() {
+ // unload all remaining assets
+ clearAssets(kAssetTypeMACH, 0, 255);
+ clearAssets(kAssetTypeSEQU, 0, 255);
+ clearAssets(kAssetTypeCELS, 0, 255);
+ clearAssets(kAssetTypeDATA, 0, 255);
+}
+
+bool AssetManager::clearAssets(AssetType assetType, int32 minHash, int32 maxHash) {
+
+ minHash = MAX(0, minHash);
+ maxHash = MIN(maxHash, 255);
+
+ switch (assetType) {
+ case kAssetTypeMACH:
+ for (int i = minHash; i <= maxHash; i++)
+ if (_MACH[i]) {
+ delete _MACH[i];
+ _MACH[i] = NULL;
+ }
+ break;
+ case kAssetTypeSEQU:
+ for (int i = minHash; i <= maxHash; i++)
+ if (_SEQU[i]) {
+ delete _SEQU[i];
+ _SEQU[i] = NULL;
+ }
+ break;
+ case kAssetTypeDATA:
+ for (int i = minHash; i <= maxHash; i++)
+ if (_DATA[i]) {
+ delete _DATA[i];
+ _DATA[i] = NULL;
+ }
+ break;
+ case kAssetTypeCELS:
+ for (int i = minHash; i <= maxHash; i++)
+ if (_CELS[i]) {
+ delete _CELS[i];
+ _CELS[i] = NULL;
+ }
+ break;
+ }
+
+ // FIXME: no value is returned, returning true for now
+ return true;
+}
+
+bool AssetManager::loadAsset(const char *assetName, RGB8 *palette) {
+
+ printf("AssetManager::loadAsset() %s\n", assetName);
+
+ // TODO, better use MemoryReadStreamEndian?
+ //convertAssetToLE(assetData, assetSize);
+
+ Common::SeekableReadStream *assetS = _vm->res()->get(assetName);
+
+ while (assetS->pos() + 12 < assetS->size()) {
+ uint32 chunkType, chunkSize, chunkHash;
+
+ chunkType = assetS->readUint32LE();
+ chunkSize = assetS->readUint32LE() - 12; // sub 12 for the chunk header
+ chunkHash = assetS->readUint32LE();
+
+ printf("hash = %d\n", chunkHash);
+
+ // Until loading code is complete, so that chunks not fully read are skipped correctly
+ uint32 nextOfs = assetS->pos() + chunkSize;
+
+ switch (chunkType) {
+ case CHUNK_MACH:
+ printf("MACH\n");
+ clearAssets(kAssetTypeMACH, chunkHash, chunkHash);
+ _MACH[chunkHash] = new MachineAsset(_vm, assetS, chunkSize, assetName);
+ break;
+ case CHUNK_SEQU:
+ printf("SEQU\n");
+ clearAssets(kAssetTypeSEQU, chunkHash, chunkHash);
+ _SEQU[chunkHash] = new SequenceAsset(_vm, assetS, chunkSize, assetName);
+ break;
+ case CHUNK_DATA:
+ printf("DATA\n");
+ clearAssets(kAssetTypeDATA, chunkHash, chunkHash);
+ _DATA[chunkHash] = new DataAsset(_vm, assetS, chunkSize, assetName);
+ break;
+ case CHUNK_CELS:
+ printf("CELS\n");
+ clearAssets(kAssetTypeCELS, chunkHash, chunkHash);
+ _CELS[chunkHash] = new SpriteAsset(_vm, assetS, chunkSize, assetName);
+ break;
+ default:
+ printf("AssetManager::loadAsset() Unknown chunk type %08X\n", chunkType);
+ }
+
+ // Until loading code is complete (see above)
+ assetS->seek(nextOfs);
+
+ }
+
+ _vm->res()->toss(assetName);
+
+ // FIXME: no value is returned, returning true for now
+ return true;
+}
+
+int32 AssetManager::addSpriteAsset(const char *assetName, int32 hash, RGB8 *palette) {
+
+ bool alreadyLoaded = false;
+
+ if (hash < 0) {
+ for (int i = 0; i <= 255; i++) {
+ if (_CELS[i] != NULL) {
+ if (_CELS[i]->getName() == assetName) {
+ alreadyLoaded = true;
+ hash = i;
+ break;
+ }
+ } else {
+ hash = i;
+ break;
+ }
+ }
+ } else {
+ alreadyLoaded = _CELS[hash] != NULL && _CELS[hash]->getName() == assetName;
+ }
+
+ /* Not loaded and no empty slots */
+ if (hash < 0)
+ return -1;
+
+ if (!alreadyLoaded) {
+
+ printf("AssetManager::addSpriteAsset() asset %s not loaded, loading into %d\n", assetName, hash);
+
+ clearAssets(kAssetTypeCELS, hash, hash);
+
+ Common::SeekableReadStream *assetS = _vm->res()->get(assetName);
+ _CELS[hash] = new SpriteAsset(_vm, assetS, assetS->size(), assetName);
+ _vm->res()->toss(assetName);
+
+ } else {
+
+ printf("AssetManager::addSpriteAsset() asset %s already loaded in %d\n", assetName, hash);
+
+ /* TODO/FIXME
+ if (_CELS[hash].palOffset >= 0 && palette)
+ restorePalette(palette, _CELS[hash].data + _CELS[hash].palOffset);
+ */
+
+ }
+
+ return hash;
+
+}
+
+void AssetManager::restorePalette(RGB8 *palette, byte *data) {
+ // TODO
+}
+
+void AssetManager::convertAssetToLE(byte *assetData, uint32 assetSize) {
+
+}
+
+MachineAsset *AssetManager::getMachine(int32 hash) {
+ assert(_MACH[hash] != NULL);
+ return _MACH[hash];
+}
+
+SequenceAsset *AssetManager::getSequence(int32 hash) {
+ assert(_SEQU[hash] != NULL);
+ return _SEQU[hash];
+}
+
+DataAsset *AssetManager::getData(int32 hash) {
+ assert(_DATA[hash] != NULL);
+ return _DATA[hash];
+}
+
+SpriteAsset *AssetManager::getSprite(int32 hash) {
+ assert(_CELS[hash] != NULL);
+ return _CELS[hash];
+}
+
+M4Sprite *AssetManager::getSpriteFrame(int32 hash, int frameIndex) {
+ assert(_CELS[hash] != NULL);
+ return _CELS[hash]->getFrame(frameIndex);
+}
+
+int32 AssetManager::getSpriteFrameCount(int32 hash) {
+ assert(_CELS[hash] != NULL);
+ return _CELS[hash]->getCount();
+}
+
+} // End of namespace M4
Property changes on: scummvm/trunk/engines/m4/assets.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/assets.h
===================================================================
--- scummvm/trunk/engines/m4/assets.h (rev 0)
+++ scummvm/trunk/engines/m4/assets.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,184 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+#ifndef M4_ASSETS_H
+#define M4_ASSETS_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+
+#include "m4/sprite.h"
+
+namespace M4 {
+
+// Sequence chunks
+#define CHUNK_SCEN MKID_BE('SCEN')
+#define CHUNK_MACH MKID_BE('MACH')
+#define CHUNK_SEQU MKID_BE('SEQU')
+#define CHUNK_DATA MKID_BE('DATA')
+#define CHUNK_CELS MKID_BE('CELS')
+
+// Sprite chunks
+#define HEAD_M4SS MKID_BE('M4SS') //'M4SS'
+#define CELS__PAL MKID_BE(' PAL') //' PAL'
+#define CELS___SS MKID_BE(' SS') //' SS'
+
+class M4Engine;
+
+class BaseAsset {
+public:
+ BaseAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
+ ~BaseAsset();
+ const Common::String getName() const { return _name; }
+protected:
+ M4Engine *_vm;
+ Common::String _name;
+};
+
+class MachineAsset : public BaseAsset {
+public:
+ MachineAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
+ ~MachineAsset();
+ void getCode(byte *&code, uint32 &codeSize);
+ uint32 getStateOffset(uint32 state);
+protected:
+ Common::Array<uint32> _stateTable;
+ byte *_code;
+ uint32 _codeSize;
+};
+
+class SequenceAsset : public BaseAsset {
+public:
+ SequenceAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
+ ~SequenceAsset();
+ void getCode(byte *&code, uint32 &codeSize);
+ int localVarCount() const { return _localVarCount; }
+protected:
+ int _localVarCount;
+ byte *_code;
+ uint32 _codeSize;
+};
+
+class DataAsset : public BaseAsset {
+public:
+ DataAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name);
+ ~DataAsset();
+ int getCount() const { return _recCount; }
+ long *getRow(int index);
+protected:
+ long *_data;
+ uint32 _recSize, _dataSize;
+ int _recCount;
+};
+
+struct SpriteAssetFrame {
+ uint32 stream;
+ int x, y, w, h;
+ uint32 comp;
+ M4Sprite *frame;
+};
+
+class SpriteAsset : public BaseAsset {
+public:
+ SpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream, int size, const char *name, bool asStream = false);
+ ~SpriteAsset();
+ void loadM4SpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream, bool asStream);
+ void loadMadsSpriteAsset(M4Engine *vm, Common::SeekableReadStream* stream);
+ int32 getCount() { return _frameCount; }
+ int32 getFrameRate() const { return _frameRate; }
+ int32 getPixelSpeed() const { return _pixelSpeed; }
+ int32 getFrameWidth(int index);
+ int32 getFrameHeight(int index);
+ int32 getMaxFrameWidth() const { return _maxWidth; }
+ int32 getMaxFrameHeight() const { return _maxHeight; }
+ M4Sprite *getFrame(int frameIndex);
+ void loadStreamingFrame(M4Sprite *frame, int frameIndex, int destX, int destY);
+ RGB8* getPalette() { return _palette; }
+ int getColorCount() { return _colorCount; }
+ RGBList *getRgbList();
+ void translate(RGBList *list, bool isTransparent = false);
+ int32 getFrameSize(int index);
+ M4Sprite *operator[](int index) { return getFrame(index); }
+protected:
+ RGB8 _palette[256];
+ uint32 _colorCount;
+ uint32 _srcSize;
+ int32 _frameRate, _pixelSpeed;
+ int _maxWidth, _maxHeight;
+ int _frameCount;
+ Common::Array<uint32> _frameOffsets;
+ Common::Array<SpriteAssetFrame> _frames;
+ uint32 _frameStartOffset;
+ Common::SeekableReadStream *_stream;
+ int32 parseSprite(bool isBigEndian = false);
+ void loadFrameHeader(SpriteAssetFrame &frameHeader, bool isBigEndian = false);
+};
+
+enum AssetType {
+ kAssetTypeMACH,
+ kAssetTypeSEQU,
+ kAssetTypeDATA,
+ kAssetTypeCELS
+};
+
+enum CallbackHandlers {
+ kCallbackTriggerDispatch
+};
+
+class AssetManager {
+public:
+
+ AssetManager(M4Engine *vm);
+ ~AssetManager();
+
+ bool clearAssets(AssetType assetType, int32 minHash, int32 maxHash);
+ bool loadAsset(const char *assetName, RGB8 *palette);
+ int32 addSpriteAsset(const char *assetName, int32 hash, RGB8 *palette);
+
+ // TODO: Move to Palette class
+ void restorePalette(RGB8 *palette, byte *data);
+
+ MachineAsset *getMachine(int32 hash);
+ SequenceAsset *getSequence(int32 hash);
+ DataAsset *getData(int32 hash);
+ SpriteAsset *getSprite(int32 hash);
+ M4Sprite *getSpriteFrame(int32 hash, int frameIndex);
+ int32 getSpriteFrameCount(int32 hash);
+
+protected:
+ // TODO: Check if we need _vm
+ M4Engine *_vm;
+
+ MachineAsset *_MACH[256];
+ SequenceAsset *_SEQU[256];
+ DataAsset *_DATA[256];
+ SpriteAsset *_CELS[256];
+
+ void convertAssetToLE(byte *assetData, uint32 assetSize);
+
+};
+
+} // End of namespace M4
+
+#endif
Property changes on: scummvm/trunk/engines/m4/assets.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/burger_data.h
===================================================================
--- scummvm/trunk/engines/m4/burger_data.h (rev 0)
+++ scummvm/trunk/engines/m4/burger_data.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,85 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_BURGER_DATA_H
+#define M4_BURGER_DATA_H
+
+#include "m4/graphics.h"
+#include "m4/actor.h"
+
+namespace M4 {
+
+InventoryObject burger_inventory [] = {
+ // name scene icon
+ //-------------------- ----- -----
+ { "empty jug", 303, 14 },
+ { "distilled juice", 999, 15 },
+ { "broken puz dispenser", 999, 16 },
+ { "puz dispenser", 999, 17 },
+ { "broken mouse trap", 999, 18 },
+ { "mouse trap", 999, 19 },
+ { "kindling", 999, 20 },
+ { "burning kindling", 999, 21 },
+ { "lights", 508, 22 },
+ { "lights on", 508, 23 },
+ { "bottle", 999, 24 },
+ { "carrot juice", 999, 25 },
+ { "soapy water", 999, 26 },
+ { "iron filings", 999, 27 },
+ { "waxed hair", 999, 28 },
+ { "fish", 999, 29 },
+ { "hook", 999, 30 },
+ { "keys", 999, 31 },
+ { "records", 999, 32 },
+ { "collar", 999, 33 },
+ { "amp", 999, 34 },
+ { "rubber gloves", 999, 35 },
+ { "sock", 504, 36 },
+ { "jaws of life", 999, 37 },
+ { "deed", 999, 38 },
+ { "burger morsel", 999, 39 },
+ { "whistle", 999, 40 },
+ { "coin", 999, 41 },
+ { "matches", 999, 42 },
+ { "phone cord", 999, 43 },
+ { "kibble", 602, 44 }, // picked up from tray
+ { "pantyhose", 999, 45 },
+ { "fan belt", 999, 46 },
+ { "spring", 999, 47 },
+ { "mirror", 999, 48 },
+ { "grate", 999, 49 },
+ { "ray gun", 604, 50 }, // given to Wilbur when he enters 604
+ { "grasshoppers", 999, 51 },
+ { "rolling pin", 999, 52 },
+ { "rubber duck", 999, 53 },
+ { "ladder", 999, 54 },
+ { "money", 999, 55 },
+ { "crow bar", 999, 56 },
+ { "Wilbur", 999, 57 }
+};
+
+} // End of namespace M4
+
+#endif
Property changes on: scummvm/trunk/engines/m4/burger_data.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/compression.cpp
===================================================================
--- scummvm/trunk/engines/m4/compression.cpp (rev 0)
+++ scummvm/trunk/engines/m4/compression.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,189 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/compression.h"
+#include "m4/m4.h"
+
+namespace M4 {
+
+const char *madsPackString = "MADSPACK";
+
+bool MadsPack::isCompressed(Common::SeekableReadStream *stream) {
+ // Check whether the passed stream is packed
+
+ char tempBuffer[8];
+ stream->seek(0);
+ if (stream->read(tempBuffer, 8) == 8) {
+ if (!strncmp(tempBuffer, madsPackString, 8))
+ return true;
+ }
+
+ return false;
+}
+
+MadsPack::MadsPack(Common::SeekableReadStream *stream) {
+ initialise(stream);
+}
+
+MadsPack::MadsPack(const char *resourceName, M4Engine* vm) {
+ Common::SeekableReadStream *stream = vm->_resourceManager->get(resourceName);
+ initialise(stream);
+ vm->_resourceManager->toss(resourceName);
+}
+
+void MadsPack::initialise(Common::SeekableReadStream *stream) {
+ if (!MadsPack::isCompressed(stream))
+ error("Attempted to decompress a resource that was not MadsPacked");
+
+ stream->seek(14);
+ _count = stream->readUint16LE();
+ _items = new MadsPackEntry[_count];
+
+ byte *headerData = new byte[0xA0];
+ byte *header = headerData;
+ stream->read(headerData, 0xA0);
+
+ for (int i = 0; i < _count; ++i, header += 10) {
+ // Get header data
+ _items[i].hash = READ_LE_UINT16(header);
+ _items[i].size = READ_LE_UINT32(header + 2);
+ _items[i].compressedSize = READ_LE_UINT32(header + 6);
+
+ _items[i].data = new byte[_items[i].size];
+ if (_items[i].size == _items[i].compressedSize) {
+ // Entry isn't compressed
+ stream->read(_items[i].data, _items[i].size);
+ } else {
+ // Decompress the entry
+ byte *compressedData = new byte[_items[i].compressedSize];
+ stream->read(compressedData, _items[i].compressedSize);
+
+ FabDecompressor fab;
+ fab.decompress(compressedData, _items[i].compressedSize, _items[i].data, _items[i].size);
+ delete[] compressedData;
+ }
+ }
+
+ delete[] headerData;
+ _dataOffset = stream->pos();
+}
+
+MadsPack::~MadsPack() {
+ for (int i = 0; i < _count; ++i)
+ delete[] _items[i].data;
+ delete[] _items;
+}
+
+//--------------------------------------------------------------------------
+
+const char *FabInputExceededError = "FabDecompressor - Passed end of input buffer during decompression";
+const char *FabOutputExceededError = "FabDecompressor - Decompressed data exceeded specified size";
+
+void FabDecompressor::decompress(const byte *srcData, int srcSize, byte *destData, int destSize) {
+ byte copyLen, copyOfsShift, copyOfsMask, copyLenMask;
+ unsigned long copyOfs;
+ byte *destP;
+
+ // Validate that the data starts with the FAB header
+ if (strncmp((const char *)srcData, "FAB", 3) != 0)
+ error("FabDecompressor - Invalid compressed data");
+
+ int shiftVal = srcData[3];
+ if ((shiftVal < 10) || (shiftVal > 13))
+ error("FabDecompressor - Invalid shift start");
+
+ copyOfsShift = 16 - shiftVal;
+ copyOfsMask = 0xFF << (shiftVal - 8);
+ copyLenMask = (1 << copyOfsShift) - 1;
+ copyOfs = 0xFFFF0000;
+ destP = destData;
+
+ // Initialise data fields
+ _srcData = srcData;
+ _srcP = _srcData + 6;
+ _srcSize = srcSize;
+ _bitsLeft = 16;
+ _bitBuffer = READ_LE_UINT16(srcData + 4);
+
+ for (;;) {
+ if (getBit() == 0) {
+ if (getBit() == 0) {
+ copyLen = ((getBit() << 1) | getBit()) + 2;
+ copyOfs = *_srcP++ | 0xFFFFFF00;
+ } else {
+ copyOfs = (((_srcP[1] >> copyOfsShift) | copyOfsMask) << 8) | _srcP[0];
+ copyLen = _srcP[1] & copyLenMask;
+ _srcP += 2;
+ if (copyLen == 0) {
+ copyLen = *_srcP++;
+ if (copyLen == 0)
+ break;
+ else if (copyLen == 1)
+ continue;
+ else
+ copyLen++;
+ } else {
+ copyLen += 2;
+ }
+ copyOfs |= 0xFFFF0000;
+ }
+ while (copyLen-- > 0) {
+ if (destP - destData == destSize)
+ error(FabOutputExceededError);
+
+ *destP = destP[(signed int)copyOfs];
+ destP++;
+ }
+ } else {
+ if (_srcP - srcData == srcSize)
+ error(FabInputExceededError);
+ if (destP - destData == destSize)
+ error(FabOutputExceededError);
+
+ *destP++ = *_srcP++;
+ }
+ }
+
+ if (destP - destData != destSize)
+ error("FabDecompressor - Decompressed data does not match header decompressed size");
+}
+
+int FabDecompressor::getBit() {
+ _bitsLeft--;
+ if (_bitsLeft == 0) {
+ if (_srcP - _srcData == _srcSize)
+ error(FabInputExceededError);
+
+ _bitBuffer = (READ_LE_UINT16(_srcP) << 1) | (_bitBuffer & 1);
+ _srcP += 2;
+ _bitsLeft = 16;
+ }
+
+ int bit = _bitBuffer & 1;
+ _bitBuffer >>= 1;
+ return bit;
+}
+
+} // End of namespace M4
Property changes on: scummvm/trunk/engines/m4/compression.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/compression.h
===================================================================
--- scummvm/trunk/engines/m4/compression.h (rev 0)
+++ scummvm/trunk/engines/m4/compression.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,82 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_COMPRESSION_H
+#define M4_COMPRESSION_H
+
+#include "common/scummsys.h"
+#include "common/stream.h"
+#include "common/endian.h"
+
+#include "m4/m4.h"
+
+namespace M4 {
+
+struct MadsPackEntry {
+public:
+ uint16 hash;
+ uint32 size;
+ uint32 compressedSize;
+ byte *data;
+};
+
+class MadsPack {
+private:
+ MadsPackEntry *_items;
+ int _count;
+ int _dataOffset;
+
+ void initialise(Common::SeekableReadStream *stream);
+public:
+ static bool isCompressed(Common::SeekableReadStream *stream);
+ MadsPack(Common::SeekableReadStream *stream);
+ MadsPack(const char *resourceName, M4Engine* _vm);
+ ~MadsPack();
+
+ int getCount() const { return _count; }
+ MadsPackEntry &getItem(int index) const { return _items[index]; }
+ MadsPackEntry &operator[](int index) const { return _items[index]; }
+ Common::MemoryReadStream *getItemStream(int index) {
+ return new Common::MemoryReadStream(_items[index].data, _items[index].size, false);
+ }
+ int getDataOffset() const { return _dataOffset; }
+};
+
+class FabDecompressor {
+private:
+ int _bitsLeft;
+ uint32 _bitBuffer;
+ const byte *_srcData, *_srcP;
+ int _srcSize;
+
+ int getBit();
+public:
+ void decompress(const byte *srcData, int srcSize, byte *destData, int destSize);
+};
+
+} // End of namespace M4
+
+
+#endif
Property changes on: scummvm/trunk/engines/m4/compression.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/console.cpp
===================================================================
--- scummvm/trunk/engines/m4/console.cpp (rev 0)
+++ scummvm/trunk/engines/m4/console.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,287 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "m4/m4.h"
+#include "m4/console.h"
+#include "m4/scene.h"
+
+namespace M4 {
+
+Console::Console(M4Engine *vm) : GUI::Debugger() {
+ _vm = vm;
+
+ DCmd_Register("scene", WRAP_METHOD(Console, cmdLoadScene));
+ DCmd_Register("start", WRAP_METHOD(Console, cmdStartingScene));
+ DCmd_Register("scene_info", WRAP_METHOD(Console, cmdSceneInfo));
+ DCmd_Register("show_hotspots", WRAP_METHOD(Console, cmdShowHotSpots));
+ DCmd_Register("list_hotspots", WRAP_METHOD(Console, cmdListHotSpots));
+ DCmd_Register("play_sound", WRAP_METHOD(Console, cmdPlaySound));
+ DCmd_Register("play_dsr_sound", WRAP_METHOD(Console, cmdPlayDSRSound));
+ DCmd_Register("show_resources", WRAP_METHOD(Console, cmdShowResources));
+ DCmd_Register("show_codes", WRAP_METHOD(Console, cmdShowCodes));
+ DCmd_Register("dump_file", WRAP_METHOD(Console, cmdDumpFile));
+ DCmd_Register("sprite", WRAP_METHOD(Console, cmdShowSprite));
+ DCmd_Register("start_conv", WRAP_METHOD(Console, cmdStartConversation));
+ DCmd_Register("textview", WRAP_METHOD(Console, cmdShowTextview));
+ DCmd_Register("animview", WRAP_METHOD(Console, cmdShowAnimview));
+ DCmd_Register("anim", WRAP_METHOD(Console, cmdPlayAnimation));
+}
+
+Console::~Console() {
+}
+
+bool Console::cmdLoadScene(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <scene number>\n", argv[0]);
+ return true;
+ } else {
+ if (_vm->isM4())
+ _vm->_kernel->newRoom = atoi(argv[1]);
+ else
+ _vm->_scene->loadScene(atoi(argv[1]));
+ return false;
+ }
+}
+
+bool Console::cmdStartingScene(int argc, const char **argv) {
+ if (_vm->getGameType() != GType_Riddle) {
+ if (_vm->isM4())
+ _vm->_kernel->newRoom = FIRST_SCENE;
+ else
+ _vm->_scene->loadScene(FIRST_SCENE);
+ return false;
+ } else {
+ DebugPrintf("%s: Riddle of Master Lu is not supported", argv[0]);
+ return true;
+ }
+}
+
+bool Console::cmdShowHotSpots(int argc, const char **argv) {
+ _vm->_scene->showHotSpots();
+ return false;
+}
+
+bool Console::cmdSceneInfo(int argc, const char **argv) {
+ DebugPrintf("Current scene is: %i\n", _vm->_scene->getCurrentScene());
+ if (_vm->isM4()) {
+ DebugPrintf("Scene resources:\n");
+ DebugPrintf("artBase: %s\n", _vm->_scene->getSceneResources().artBase);
+ DebugPrintf("pictureBase: %s\n", _vm->_scene->getSceneResources().pictureBase);
+ DebugPrintf("hotspotCount: %i\n", _vm->_scene->getSceneResources().hotspotCount);
+ DebugPrintf("parallaxCount: %i\n", _vm->_scene->getSceneResources().parallaxCount);
+ DebugPrintf("propsCount: %i\n", _vm->_scene->getSceneResources().propsCount);
+ DebugPrintf("frontY: %i\n", _vm->_scene->getSceneResources().frontY);
+ DebugPrintf("backY: %i\n", _vm->_scene->getSceneResources().backY);
+ DebugPrintf("frontScale: %i\n", _vm->_scene->getSceneResources().frontScale);
+ DebugPrintf("backScale: %i\n", _vm->_scene->getSceneResources().backScale);
+ DebugPrintf("depthTable: ");
+ for (uint i = 0; i < 16; i++)
+ DebugPrintf("%i ", _vm->_scene->getSceneResources().depthTable[i]);
+ DebugPrintf("\n");
+ DebugPrintf("railNodeCount: %i\n", _vm->_scene->getSceneResources().railNodeCount);
+ }
+ return true;
+}
+
+bool Console::cmdListHotSpots(int argc, const char **argv) {
+ DebugPrintf("Scene hotspots\n");
+ _vm->_scene->getSceneResources().hotspots->dump();
+ if (_vm->isM4()) {
+ DebugPrintf("Scene parallax\n");
+ _vm->_scene->getSceneResources().parallax->dump();
+ DebugPrintf("Scene props\n");
+ _vm->_scene->getSceneResources().props->dump();
+ }
+ return true;
+}
+
+bool Console::cmdPlaySound(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <sound file>\n", argv[0]);
+ } else {
+ _vm->_sound->playSound(argv[1], 255, false);
+ }
+ return true;
+}
+
+bool Console::cmdPlayDSRSound(int argc, const char **argv) {
+ if (argc != 2 && argc != 3) {
+ DebugPrintf("Usage: %s <sound index> <DSR file>\n", argv[0]);
+ DebugPrintf("The DSR file parameter is optional, and specifies which DSR to load\n", argv[0]);
+ } else {
+ if (argc == 3)
+ _vm->_sound->loadDSRFile(argv[2]);
+ _vm->_sound->playDSRSound(atoi(argv[1]), 255, false);
+ }
+ return true;
+}
+
+bool Console::cmdShowResources(int argc, const char **argv) {
+ _vm->res()->dump();
+ return true;
+}
+
+bool Console::cmdShowCodes(int argc, const char **argv) {
+ if (_vm->getGameType() != GType_RexNebular)
+ _vm->_scene->showCodes();
+ else
+ DebugPrintf("Pathfinding codes not done yet for Rex Nebular");
+ return false;
+}
+
+bool Console::cmdDumpFile(int argc, const char **argv) {
+ if (argc != 2 && argc != 3) {
+ DebugPrintf("Usage: %s <file> <uncompress>\n", argv[0]);
+ DebugPrintf("If uncompress is 1, the file is uncompressed (for MADS games)\n");
+ } else {
+ if (argc == 2) {
+ _vm->dumpFile(strdup(argv[1]));
+ } else {
+ if (argc == 3 && atoi(argv[2]) == 1)
+ _vm->dumpFile(strdup(argv[1]), true);
+ else
+ _vm->dumpFile(strdup(argv[1]));
+ }
+ }
+ return true;
+}
+
+bool Console::cmdShowSprite(int argc, const char **argv) {
+ View *view = _vm->_viewManager->getView(VIEWID_SCENE);
+ if (view == NULL)
+ DebugPrintf("The scene view isn't currently active\n");
+ else if (argc < 2)
+ DebugPrintf("Usage: %s resource_name\n", argv[0]);
+ else {
+ char resourceName[20];
+ strncpy(resourceName, argv[1], 15);
+ resourceName[15] = '\0';
+ if (!strchr(resourceName, '.'))
+ strcat(resourceName, ".SS");
+
+ _vm->_viewManager->moveToFront(view);
+ Common::SeekableReadStream *data = _vm->res()->get(resourceName);
+ SpriteAsset *asset = new SpriteAsset(_vm, data, data->size(), resourceName);
+ _vm->res()->toss(resourceName);
+
+ RGBList *palData = new RGBList(asset->getColorCount(), asset->getPalette(), true);
+ _vm->_palette->addRange(palData);
+
+ // Get the scene background surface
+ M4Surface *bg = _vm->_scene->getBackgroundSurface();
+
+ // Write the sprite onto the screen
+ int x = 0, y = 0, yMax = 0;
+ for (int index = 0; index < asset->getCount(); index++) {
+ M4Sprite *spr = asset->getFrame(index);
+ spr->translate(palData); // sprite pixel translation
+
+ if ((x + spr->width() >= bg->width()) && (yMax != 0)) {
+ x = 0;
+ y += yMax;
+ yMax = 0;
+ }
+
+ if (y >= bg->height())
+ break;
+
+ // FIXME: We assume that the transparent color is the color of the top left pixel
+ byte *transparentColor = (byte *)spr->pixels;
+
+ spr->copyTo(bg, x, y, (int)*transparentColor);
+
+ x += spr->width();
+ yMax = MAX(yMax, spr->height());
+ }
+
+ view->restore(0, 0, view->width(), view->height());
+ return false;
+ }
+
+ return true;
+}
+
+bool Console::cmdStartConversation(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <conversation file name>\n", argv[0]);
+ return true;
+ } else {
+ _vm->_converse->startConversation(argv[1]);
+ return false;
+ }
+}
+
+bool Console::cmdShowTextview(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <txr resource>\n", argv[0]);
+ return true;
+ }
+
+ _vm->_viewManager->showTextView(argv[1], false);
+ return false;
+}
+
+bool Console::cmdShowAnimview(int argc, const char **argv) {
+ if (argc != 2) {
+ DebugPrintf("Usage: %s <res resource>\n", argv[0]);
+ return true;
+ }
+
+ char resName[80];
+ strcpy(resName, "@");
+ strcat(resName, *argv[1] == '@' ? argv[1] + 1 : argv[1]);
+
+ _vm->_viewManager->showAnimView(resName, false);
+ return false;
+}
+
+bool Console::cmdPlayAnimation(int argc, const char **argv) {
+ View *view = _vm->_viewManager->getView(VIEWID_SCENE);
+ if (view == NULL) {
+ DebugPrintf("The scene view isn't currently active\n");
+ } else if (argc != 2 && argc != 3) {
+ DebugPrintf("Usage: %s <anim resource (*.aa)> <fullscreen>\n", argv[0]);
+ DebugPrintf("If fullscreen is 1, the screen palette is replaced with the palette of the animation\n");
+ } else {
+ char resourceName[20];
+ strncpy(resourceName, argv[1], 15);
+ resourceName[15] = '\0';
+ if (!strchr(resourceName, '.'))
+ strcat(resourceName, ".AA");
+
+ _vm->_viewManager->moveToFront(view);
+ if (argc == 3 && atoi(argv[2]) == 1)
+ _vm->_animation->loadFullScreen(resourceName);
+ else
+ _vm->_animation->load(resourceName);
+ _vm->_animation->start();
+ view->restore(0, 0, view->width(), view->height());
+ return false;
+ }
+
+ return true;
+}
+
+} // End of namespace M4
Property changes on: scummvm/trunk/engines/m4/console.cpp
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/console.h
===================================================================
--- scummvm/trunk/engines/m4/console.h (rev 0)
+++ scummvm/trunk/engines/m4/console.h 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,64 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#ifndef M4_CONSOLE_H
+#define M4_CONSOLE_H
+
+#include "gui/debugger.h"
+
+namespace M4 {
+
+class M4Engine;
+
+class Console : public GUI::Debugger {
+public:
+ Console(M4Engine *vm);
+ virtual ~Console(void);
+
+private:
+ bool cmdLoadScene(int argc, const char **argv);
+ bool cmdStartingScene(int argc, const char **argv);
+ bool cmdSceneInfo(int argc, const char **argv);
+ bool cmdShowHotSpots(int argc, const char **argv);
+ bool cmdListHotSpots(int argc, const char **argv);
+ bool cmdPlaySound(int argc, const char **argv);
+ bool cmdPlayDSRSound(int argc, const char **argv);
+ bool cmdShowResources(int argc, const char **argv);
+ bool cmdShowCodes(int argc, const char **argv);
+ bool cmdDumpFile(int argc, const char **argv);
+ bool cmdShowSprite(int argc, const char **argv);
+ bool cmdStartConversation(int argc, const char **argv);
+ bool cmdShowTextview(int argc, const char **argv);
+ bool cmdShowAnimview(int argc, const char **argv);
+ bool cmdPlayAnimation(int argc, const char **argv);
+
+private:
+ M4Engine *_vm;
+};
+
+} // End of namespace M4
+
+
+#endif
Property changes on: scummvm/trunk/engines/m4/console.h
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Rev Author URL Id
Name: svn:eol-style
+ native
Added: scummvm/trunk/engines/m4/converse.cpp
===================================================================
--- scummvm/trunk/engines/m4/converse.cpp (rev 0)
+++ scummvm/trunk/engines/m4/converse.cpp 2008-04-20 14:47:37 UTC (rev 31600)
@@ -0,0 +1,1211 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ * $URL$
+ * $Id$
+ *
+ */
+
+#include "common/array.h"
+#include "common/hashmap.h"
+
+#include "m4/converse.h"
+#include "m4/resource.h"
+#include "m4/globals.h"
+#include "m4/m4_views.h"
+#include "m4/compression.h"
+
+namespace M4 {
+
+#define CONV_ENTRIES_X_OFFSET 20
+#define CONV_ENTRIES_Y_OFFSET 4
+#define CONV_ENTRIES_HEIGHT 20
+#define CONV_MAX_SHOWN_ENTRIES 5
+
+#define CONVERSATION_ENTRY_HIGHLIGHTED 22
+#define CONVERSATION_ENTRY_NORMAL 3
+
+// Conversation chunks
+// Header
+#define HEAD_CONV MKID_BE('CONV') // conversation
+#define CHUNK_DECL MKID_BE('DECL') // declaration
+#define CHUNK_NODE MKID_BE('NODE') // node
+#define CHUNK_LNOD MKID_BE('LNOD') // linear node
+#define CHUNK_ETRY MKID_BE('ETRY') // entry
+#define CHUNK_TEXT MKID_BE('TEXT') // text
+#define CHUNK_MESG MKID_BE('MESG') // message
+// Conversation chunks - entry related (unconditional)
+#define CHUNK_RPLY MKID_BE('RPLY') // reply
+#define CHUNK_HIDE MKID_BE('HIDE') // hide entry
+#define CHUNK_UHID MKID_BE('UHID') // unhide entry
+#define CHUNK_DSTR MKID_BE('DSTR') // destroy entry
+// Conversation chunks - entry related (conditional)
+#define CHUNK_CRPL MKID_BE('CRPL') // reply
+#define CHUNK_CHDE MKID_BE('CHDE') // hide entry
+#define CHUNK_CUHD MKID_BE('CUHD') // unhide entry
+#define CHUNK_CDST MKID_BE('DDTS') // destroy entry
+// Conversation chunks - branching and logic (unconditional)
+#define CHUNK_ASGN MKID_BE('ASGN') // assign
+#define CHUNK_GOTO MKID_BE('GOTO') // goto chunk
+#define CHUNK_EXIT MKID_BE('EXIT') // exit/return from goto
+// Conversation chunks - branching and logic (conditional)
+#define CHUNK_CASN MKID_BE('CASN') // assign
+#define CHUNK_CCGO MKID_BE('CCGO') // goto chunk
+#define CHUNK_CEGO MKID_BE('CEGO') // exit/return from goto
+// Others
+#define CHUNK_FALL MKID_BE('FALL') // fallthrough
+#define CHUNK_WRPL MKID_BE('WRPL') // weighted reply chunk
+#define CHUNK_WPRL MKID_BE('WPRL') // weighted preply chunk
+
+
+ConversationView::ConversationView(M4Engine *vm): View(vm, Common::Rect(0,
+ vm->_screen->height() - INTERFACE_HEIGHT, vm->_screen->width(), vm->_screen->height())) {
+
+ _screenType = VIEWID_CONVERSATION;
+ _screenFlags.layer = LAYER_INTERFACE;
+ _screenFlags.visible = false;
+ _screenFlags.get = SCREVENT_MOUSE;
+ _conversationState = kNoConversation;
+ _currentHandle = NULL;
+}
+
+ConversationView::~ConversationView() {
+ _activeItems.clear();
+}
+
+void ConversationView::setNode(int32 nodeIndex) {
+ _highlightedIndex = -1;
+ _xEnd = CONV_ENTRIES_X_OFFSET;
+ _vm->_font->setFont(FONT_CONVERSATION);
+
+ // TODO: Conversation styles and colors
+ _vm->_font->setColors(2, 1, 3);
+
+ _currentNodeIndex = nodeIndex;
+
+ _activeItems.clear();
+
+ if (nodeIndex != -1) {
+ ConvEntry *node = _vm->_converse->getNode(nodeIndex);
+
+ for (uint i = 0; i < node->entries.size(); ++i) {
+ if (!node->entries[i]->visible)
+ continue;
+
+ if ((int)_activeItems.size() > CONV_MAX_SHOWN_ENTRIES) {
+ warning("TODO: scrolling. Max shown entries are %i, skipping entry %i",
+ CONV_MAX_SHOWN_ENTRIES, i);
+ }
+
+ // Add node to active items list
+ _activeItems.push_back(node->entries[i]);
+
+ if (node->entries[i]->autoSelect || strlen(node->entries[i]->text) == 0) {
+ //printf("Auto selecting entry %i of node %i\n", i, nodeIndex);
+ selectEntry(i);
+ return;
+ }
+
+ // Figure out the longest string to determine where option highlighting ends
+ int tempX = _vm->_font->getWidth(node->entries[i]->text, 0) +
+ CONV_ENTRIES_X_OFFSET + 10;
+ _xEnd = MAX(_xEnd, tempX);
+ }
+
+ // Make sure that there aren't too many entries
+ //assert((int)_activeItems.size() < (height() - CONV_ENTRIES_Y_OFFSET) / CONV_ENTRIES_HEIGHT);
+
+ // Fallthrough
+ if (node->fallthroughMinEntries >= 0 && node->fallthroughOffset >= 0) {
+ //printf("Current node falls through node at offset %i when entries are less or equal than %i\n",
+ // node->fallthroughOffset, node->fallthroughMinEntries);
+ if (_activeItems.size() <= (uint32)node->fallthroughMinEntries) {
+ const EntryInfo *entryInfo = _vm->_converse->getEntryInfo(node->fallthroughOffset);
+ //printf("Entries are less than or equal to %i, falling through to node at offset %i, index %i\n",
+ // node->fallthroughMinEntries, node->fallthroughOffset, entryInfo->nodeIndex);
+ setNode(entryInfo->nodeIndex);
+ return;
+ }
+ }
+
+ _entriesShown = true;
+ _conversationState = kConversationOptionsShown;
+ }
+}
+
+void ConversationView::onRefresh(RectList *rects, M4Surface *destSurface) {
+ //if (!this->isVisible())
+ // return;
+ empty();
+
+ if (_entriesShown) {
+ // Write out the conversation options
+ _vm->_font->setFont(FONT_CONVERSATION);
+ for (int i = 0; i < (int)_activeItems.size(); ++i) {
+ // TODO: scrolling
+ if (i > CONV_MAX_SHOWN_ENTRIES - 1)
+ break;
+
+ _vm->_font->setColor((_highlightedIndex == i) ? CONVERSATION_ENTRY_HIGHLIGHTED :
+ CONVERSATION_ENTRY_NORMAL);
+
+ _vm->_font->writeString(this, _activeItems[i]->text, CONV_ENTRIES_X_OFFSET,
+ CONV_ENTRIES_Y_OFFSET + CONV_ENTRIES_HEIGHT * i, 0, 0);
+ }
+ }
+ View::onRefresh(rects, destSurface);
+}
+
+bool ConversationView::onEvent(M4EventType eventType, int param, int x, int y, bool &captureEvents) {
+ //if (!this->isVisible())
+ // return false;
+ if (!_entriesShown)
+ return false;
+ if (eventType == KEVENT_KEY)
+ return false;
+
+ int localY = y - _coords.top;
+ int selectedIndex = _highlightedIndex;
+
+ switch (eventType) {
+ case MEVENT_MOVE:
+ if ((x < CONV_ENTRIES_X_OFFSET) || (x >= _xEnd) || (localY < CONV_ENTRIES_Y_OFFSET))
+ _highlightedIndex = -1;
+ else {
+ int index = (localY - CONV_ENTRIES_Y_OFFSET) / CONV_ENTRIES_HEIGHT;
+ _highlightedIndex = (index >= (int)_activeItems.size()) ? -1 : index;
+ }
+ break;
+
+ case MEVENT_LEFT_RELEASE:
+ if (_highlightedIndex != -1) {
+ selectEntry(selectedIndex);
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ return true;
+}
+
+void ConversationView::selectEntry(int entryIndex) {
+ char buffer[20];
+ sprintf(buffer, "%s.raw", _activeItems[entryIndex]->voiceFile);
+
+ _entriesShown = false;
+ _conversationState = kEntryIsActive;
+ _vm->_player->setCommandsAllowed(false);
+ // Necessary, as entries can be selected programmatically
+ _highlightedIndex = entryIndex;
+
+ // Play the selected entry's voice
+ if (strlen(_activeItems[entryIndex]->voiceFile) > 0) {
+ _currentHandle = _vm->_sound->getHandle();
+ _vm->_sound->playVoice(buffer, 255);
+ } else {
+ _currentHandle = NULL;
+ }
+
+ // Hide selected entry, unless it has a persistent flag set
+ if (!(_activeItems[entryIndex]->flags & kEntryPersists)) {
+ //printf("Hiding selected entry\n");
+ _vm->_converse->getNode(_currentNodeIndex)->entries[entryIndex]->visible = false;
+ } else {
+ //printf("Selected entry is persistent, not hiding it\n");
+ }
+}
+
+void ConversationView::updateState() {
+ switch(_conversationState) {
+ case kConversationOptionsShown:
+ return;
+ case kEntryIsActive:
+ case kReplyIsActive:
+ // FIXME: for now, we determine whether a conversation entry is
+ // finished by waiting for its associated speech file to finish playing
+ if (_currentHandle != NULL && _vm->_sound->isHandleActive(_currentHandle)) {
+ return;
+ } else {
+ playNextReply();
+ } // end else
+ break;
+ case kNoConversation:
+ return;
+ default:
+ error("Unknown converstation state");
+ break;
+ }
+}
+
+void ConversationView::playNextReply() {
+ char buffer[20];
+
+ assert(_highlightedIndex >= 0);
+
+ // Start playing the first reply
+ for (uint32 i = 0; i < _activeItems[_highlightedIndex]->entries.size(); i++) {
+ ConvEntry *currentEntry = _activeItems[_highlightedIndex]->entries[i];
+
+ if (currentEntry->isConditional) {
+ if (!_vm->_converse->evaluateCondition(
+ _vm->_converse->getValue(currentEntry->condition.offset),
+ currentEntry->condition.op, currentEntry->condition.val))
+ continue; // don't play this reply
+ }
+
+ if (currentEntry->entryType != kWeightedReply) {
+ sprintf(buffer, "%s.raw", currentEntry->voiceFile);
+ if (strlen(currentEntry->voiceFile) > 0) {
+ _currentHandle = _vm->_sound->getHandle();
+ _vm->_sound->playVoice(buffer, 255);
+ // Remove reply from the list of replies
+ _activeItems[_highlightedIndex]->entries.remove_at(i);
+ _conversationState = kReplyIsActive;
+ return;
+ } else {
+ _currentHandle = NULL;
+ }
+ } else {
+ int selectedWeight = _vm->_random->getRandomNumber(currentEntry->totalWeight - 1) + 1;
+ //printf("Selected weight: %i\n", selectedWeight);
+ int previousWeight = 1;
+ int currentWeight = 0;
+
+ for(uint32 j = 0; j < currentEntry->entries.size(); j++) {
+ currentWeight += currentEntry->entries[j]->weight;
+ if (selectedWeight >= previousWeight && selectedWeight <= currentWeight) {
+ sprintf(buffer, "%s.raw", currentEntry->entries[j]->voiceFile);
+ if (strlen(currentEntry->entries[j]->voiceFile) > 0) {
+ _currentHandle = _vm->_sound->getHandle();
+ _vm->_sound->playVoice(buffer, 255);
+ // Remove reply from the list of replies
+ _activeItems[_highlightedIndex]->entries.remove_at(i);
+ _conversationState = kReplyIsActive;
+ return;
+ } else {
+ _currentHandle = NULL;
+ }
+ break;
+ }
+ previousWeight += currentWeight;
+ } // end for j
+ } // end if
+ } // end for i
+
+ // If we reached here, there are no more replies, so perform the active entry's actions
+
+ //printf("Current selection does %i actions\n", _activeItems[entryIndex]->actions.size());
+ for (uint32 i = 0; i < _activeItems[_highlightedIndex]->actions.size(); i++) {
+ if (!_vm->_converse->performAction(_activeItems[_highlightedIndex]->actions[i]))
+ break;
+ } // end for
+
+ // Refresh the conversation node, in case it hasn't changed
+ setNode(_currentNodeIndex);
+
+ _entriesShown = true;
+ _vm->_player->setCommandsAllowed(true);
+
+ // Check if the conversation has been ended
+ if (_currentNodeIndex == -1) {
+ _conversationState = kNoConversation;
+ }
+}
+
+//--------------------------------------------------------------------------
+
+void Converse::startConversation(const char *convName, bool showConverseBox, ConverseStyle style) {
+ if (_vm->isM4())
+ loadConversation(convName);
+ else
+ loadConversationMads(convName);
+
+ if (!_vm->isM4()) showConverseBox = false; // TODO: remove
+
+ _playerCommandsAllowed = _vm->_player->commandsAllowed;
+ if (_vm->isM4()) // TODO: remove (interface not implemented yet in MADS games)
+ _interfaceWasVisible = _vm->_interfaceView->isVisible();
+ _vm->_player->setCommandsAllowed(false);
+ _style = style;
+
+ if (showConverseBox) {
+ _vm->_conversationView->show();
+ _vm->_mouse->lockCursor(CURSOR_ARROW);
+
+ if (_interfaceWasVisible)
+ _vm->_interfaceView->hide();
+
+ _vm->_conversationView->setNode(0);
+ _vm->_conversationView->show();
+ }
+}
+
+void Converse::endConversation() {
+ _vm->_conversationView->setNode(-1);
+ _vm->_conversationView->hide();
+ // TODO: do a more proper cleanup here
+ _convNodes.clear();
+ _variables.clear();
+ _offsetMap.clear();
+ _vm->_player->setCommandsAllowed(_playerCommandsAllowed);
+ if (_interfaceWasVisible)
+ _vm->_interfaceView->show();
+}
+
+void Converse::loadConversation(const char *convName) {
+ char name[40];
+ char buffer[256];
+ sprintf(name, "%s.chk", convName);
+ Common::SeekableReadStream *convS = _vm->res()->get(name);
+ uint32 header = convS->readUint32LE();
+ uint32 size;
+ uint32 chunk;
+ uint32 data;
+ uint32 i;
+ ConvEntry* curEntry = NULL;
+ ConvEntry* replyEntry = NULL;
+ int32 currentWeightedEntry = -1;
+ EntryAction* curAction = NULL;
+ uint32 curNode = 0;
+ uint32 chunkPos = 0;
+ uint32 val;
+ int32 autoSelectIndex = -1;
+ int returnAddress = -1;
+
+ bool debugFlag = false; // set to true for debug messages
+
+ // Conversation *.chk files contain a 'CONV' header in LE format
+ if (header != HEAD_CONV) {
+ warning("Unexpected conversation file external header");
+ return;
+ }
+ size = convS->readUint32LE(); // is this used at all?
+ if (debugFlag) printf("Conv chunk size (external header): %i\n", size);
+
+ // Conversation name, which is the conversation file's name
+ // without the extension
+ convS->read(buffer, 8);
+ if (debugFlag) printf("Conversation name: %s\n", buffer);
+
+ while(!convS->eos()) {
+ chunkPos = convS->pos();
+ if (debugFlag) printf("***** Pos: %i -> ", chunkPos);
+ chunk = convS->readUint32LE(); // read chunk
+ switch(chunk) {
+ case CHUNK_DECL: // Declare
+ if (debugFlag) printf("DECL chunk\n");
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Tag: %i\n", data);
+ if (data > 0)
+ warning("Tag > 0 in DECL chunk, value is: %i", data); // TODO
+ val = convS->readUint32LE();
+ if (debugFlag) printf("Value: %i\n", val);
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Flags: %i\n", data);
+ if (data > 0)
+ warning("Flags != 0 in DECL chunk, value is %i", data); // TODO
+ setValue(chunkPos, val);
+ break;
+ // ----------------------------------------------------------------------------
+ case CHUNK_NODE: // Node
+ case CHUNK_LNOD: // Linear node
+ // Create new node
+ curEntry = new ConvEntry();
+ curEntry->offset = chunkPos;
+ curEntry->entryType = (chunk == CHUNK_NODE) ? kNode : kLinearNode;
+ curEntry->fallthroughMinEntries = -1;
+ curEntry->fallthroughOffset = -1;
+ if (chunk == CHUNK_NODE) {
+ if (debugFlag) printf("NODE chunk\n");
+ } else {
+ if (debugFlag) printf("LNOD chunk\n");
+ }
+ curNode = convS->readUint32LE();
+ if (debugFlag) printf("Node number: %i\n", curNode);
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Tag: %i\n", data);
+ if (chunk == CHUNK_LNOD) {
+ autoSelectIndex = convS->readUint32LE();
+ if (debugFlag) printf("Autoselect entry number: %i\n", autoSelectIndex);
+ }
+ size = convS->readUint32LE();
+ if (debugFlag) printf("Number of entries: %i\n", size);
+ for (i = 0; i < size; i++) {
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Entry %i: %i\n", i + 1, data);
+ }
+ _convNodes.push_back(curEntry);
+ setEntryInfo(curEntry->offset, curEntry->entryType, curNode, -1);
+ break;
+ case CHUNK_ETRY: // Entry
+ // Create new entry
+ curEntry = new ConvEntry();
+ curEntry->offset = chunkPos;
+ curEntry->entryType = kEntry;
+ strcpy(curEntry->voiceFile, "");
+ strcpy(curEntry->text, "");
+ if (debugFlag) printf("ETRY chunk\n");
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Unknown (attributes perhaps?): %i\n", data);
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Entry flags: ");
+ if (debugFlag) if (data & kEntryInitial) printf ("Initial ");
+ if (debugFlag) if (data & kEntryPersists) printf ("Persists ");
+ if (debugFlag) printf("\n");
+ curEntry->flags = data;
+ curEntry->visible = (curEntry->flags & kEntryInitial) ? true : false;
+ if (autoSelectIndex >= 0) {
+ if (_convNodes[curNode]->entries.size() == (uint32)autoSelectIndex) {
+ curEntry->autoSelect = true;
+ autoSelectIndex = -1;
+ } else {
+ curEntry->autoSelect = false;
+ }
+ } else {
+ curEntry->autoSelect = false;
+ }
+ _convNodes[curNode]->entries.push_back(curEntry);
+ setEntryInfo(curEntry->offset, curEntry->entryType,
+ curNode, _convNodes[curNode]->entries.size() - 1);
+ replyEntry = NULL;
+ break;
+ case CHUNK_WPRL: // Weighted preply
+ // WPRL chunks are random entries that the character would say, not an NPC
+ // They don't seem to be used in Orion Burger
+ warning("WPRL chunk - treating as WRPL chunk");
+ case CHUNK_WRPL: // Weighted reply
+ case CHUNK_CRPL: // Conditional reply
+ case CHUNK_RPLY: // Reply
+ {
+ ConvEntry* weightedEntry = NULL;
+ // Create new reply
+ replyEntry = new ConvEntry();
+ replyEntry->offset = chunkPos;
+ strcpy(replyEntry->voiceFile, "");
+
+ // Conditional part
+ if (chunk == CHUNK_CRPL) {
+ replyEntry->isConditional = true;
+ replyEntry->condition.offset = convS->readUint32LE();
+ replyEntry->condition.op = convS->readUint32LE();
+ replyEntry->condition.val = convS->readUint32LE();
+ } else {
+ replyEntry->isConditional = false;
+ }
+
+ if (chunk == CHUNK_WPRL || chunk == CHUNK_WRPL) {
+ replyEntry->entryType = kWeightedReply;
+ replyEntry->totalWeight = 0;
+ if (debugFlag) printf("WRPL chunk\n");
+ size = convS->readUint32LE();
+ if (debugFlag) printf("Weighted reply %i - %i entries:\n", i, size);
+ for (i = 0; i < size; i++) {
+ weightedEntry = new ConvEntry();
+ weightedEntry->offset = chunkPos;
+ strcpy(weightedEntry->voiceFile, "");
+ weightedEntry->entryType = kWeightedReply;
+ data = convS->readUint32LE();
+ if (debugFlag) printf("- Weight: %i ", data);
+ weightedEntry->weight = data;
+ replyEntry->totalWeight += weightedEntry->weight;
+ data = convS->readUint32LE();
+ if (debugFlag) printf("offset: %i\n", data);
+ replyEntry->entries.push_back(weightedEntry);
+ }
+ currentWeightedEntry = 0;
+ } else {
+ replyEntry->entryType = kReply;
+ if (debugFlag) printf("RPLY chunk\n");
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Reply data offset: %i\n", data);
+ }
+
+ curEntry->entries.push_back(replyEntry);
+ setEntryInfo(replyEntry->offset, replyEntry->entryType,
+ curNode, _convNodes[curNode]->entries.size() - 1);
+ // Seek to chunk data (i.e. TEXT/MESG tag, which is usually right
+ // after this chunk but it can be further on in conditional reply chunks
+ assert(data >= convS->pos());
+ // If the entry's data is not right after the entry, remember the position
+ // to return to after the data is read
+ if (chunk == CHUNK_CRPL && data != convS->pos())
+ returnAddress = convS->pos();
+ convS->seek(data, SEEK_SET);
+ }
+ break;
+ // ----------------------------------------------------------------------------
+ case CHUNK_TEXT: // Text (contains text and voice)
+ case CHUNK_MESG: // Message (contains voice only)
+ {
+ ConvEntry* parentEntry = NULL;
+ if (chunk == CHUNK_TEXT) {
+ if (debugFlag) printf("TEXT chunk\n");
+ } else {
+ if (debugFlag) printf("MESG chunk\n");
+ }
+
+ if (replyEntry == NULL) {
+ parentEntry = curEntry;
+ } else if (replyEntry != NULL && replyEntry->entryType != kWeightedReply) {
+ parentEntry = replyEntry;
+ } else if (replyEntry != NULL && replyEntry->entryType == kWeightedReply) {
+ parentEntry = replyEntry->entries[currentWeightedEntry];
+ currentWeightedEntry++;
+ }
+
+ size = convS->readUint32LE();
+ if (debugFlag) printf("Entry data size: %i\n", size);
+ convS->read(buffer, 8);
+ size -= 8; // subtract maximum length of voice file name
+ // If the file name is 8 characters, it will not be 0-terminated, so use strncpy
+ strncpy(parentEntry->voiceFile, buffer, 8);
+ parentEntry->voiceFile[8] = '\0';
+ if (debugFlag) printf("Voice file: %s\n", parentEntry->voiceFile);
+
+ if (chunk == CHUNK_TEXT) {
+ convS->read(buffer, size);
+ if (debugFlag) printf("Text: %s\n", buffer);
+ sprintf(parentEntry->text, "%s", buffer);
+ } else {
+ while (size > 0) {
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Unknown: %i\n", data); // TODO
+ size -= 4;
+ }
+ }
+ // Now that the data chunk has been read, if we skipped a reply node,
+ // jump back to it
+ if (returnAddress != -1) {
+ convS->seek(returnAddress, SEEK_SET);
+ returnAddress = -1;
+ }
+ }
+ break;
+ // ----------------------------------------------------------------------------
+ // Entry action chunks
+ case CHUNK_CASN: // Conditional assign
+ case CHUNK_ASGN: // Assign
+ curAction = new EntryAction();
+ if (debugFlag) printf("ASGN chunk\n");
+ curAction->actionType = kAssignValue;
+
+ // Conditional part
+ if (chunk == CHUNK_CASN) {
+ curAction->isConditional = true;
+ curAction->condition.offset = convS->readUint32LE();
+ curAction->condition.op = convS->readUint32LE();
+ curAction->condition.val = convS->readUint32LE();
+ } else {
+ curAction->isConditional = false;
+ }
+
+ curAction->targetOffset = convS->readUint32LE();
+ assert(convS->readUint32LE() == kOpAssign);
+ curAction->value = convS->readUint32LE();
+ break;
+ case CHUNK_CCGO: // Conditional go to entry
+ case CHUNK_CHDE: // Conditional hide entry
+ case CHUNK_CUHD: // Conditional unhide entry
+ case CHUNK_CDST: // Conditional destroy entry
+ case CHUNK_CEGO: // Conditional exit conversation / go to
+
+ case CHUNK_GOTO: // Go to entry
+ case CHUNK_HIDE: // Hide entry
+ case CHUNK_UHID: // Unhide entry
+ case CHUNK_DSTR: // Destroy entry
+ case CHUNK_EXIT: // Exit conversation
+ curAction = new EntryAction();
+
+ // Conditional part
+ if (chunk == CHUNK_CCGO || chunk == CHUNK_CHDE || chunk == CHUNK_CUHD ||
+ chunk == CHUNK_CDST || chunk == CHUNK_CEGO) {
+ curAction->isConditional = true;
+ curAction->condition.offset = convS->readUint32LE();
+ curAction->condition.op = convS->readUint32LE();
+ curAction->condition.val = convS->readUint32LE();
+ } else {
+ curAction->isConditional = false;
+ }
+
+ if (chunk == CHUNK_GOTO || chunk == CHUNK_CCGO) {
+ curAction->actionType = kGotoEntry;
+ if (debugFlag) printf("GOTO chunk\n");
+ } else if (chunk == CHUNK_HIDE || chunk == CHUNK_CHDE) {
+ curAction->actionType = kHideEntry;
+ if (debugFlag) printf("HIDE chunk\n");
+ } else if (chunk == CHUNK_UHID || chunk == CHUNK_CUHD) {
+ curAction->actionType = kUnhideEntry;
+ if (debugFlag) printf("UHID chunk\n");
+ } else if (chunk == CHUNK_DSTR || chunk == CHUNK_CDST) {
+ curAction->actionType = kDestroyEntry;
+ if (debugFlag) printf("DSTR chunk\n");
+ } else if (chunk == CHUNK_EXIT || chunk == CHUNK_CEGO) {
+ curAction->actionType = kExitConv;
+ if (debugFlag) printf("EXIT chunk\n");
+ }
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Offset: %i\n", data);
+ curAction->targetOffset = data;
+ curEntry->actions.push_back(curAction);
+ break;
+ case CHUNK_FALL: // Fallthrough
+ if (debugFlag) printf("FALL chunk\n");
+ size = convS->readUint32LE();
+ if (debugFlag) printf("Minimum nodes: %i\n", size);
+ _convNodes[curNode]->fallthroughMinEntries = size;
+ data = convS->readUint32LE();
+ if (debugFlag) printf("Offset: %i\n", data);
+ _convNodes[curNode]->fallthroughOffset = data;
+ break;
+ // ----------------------------------------------------------------------------
+ default:
+ // Should never happen
+ error("Unknown conversation chunk");
+ break;
+ }
+ }
+
+ _vm->res()->toss(name);
+}
+
+void Converse::loadConversationMads(const char *convName) {
+ char name[40];
+ char buffer[256];
+ char *buf;
+ Common::SeekableReadStream *convS;
+ int curPos = 0;
+ int unk = 0;
+ uint32 stringIndex = 0;
+ uint32 stringCount = 0;
+ int offset = 0;
+ int flags = 0;
+ int count = 0;
+ uint32 i, j;
+ ConvEntry* curEntry = NULL;
+ MessageEntry *curMessage;
+ Common::Array<char *> messageList;
+ // TODO
+
+ // CND file
+ sprintf(name, "%s.cnd", convName);
+ MadsPack convDataD(name, _vm);
+
+ // ------------------------------------------------------------
+ // Chunk 0
+ convS = convDataD.getItemStream(0);
+ printf("Chunk 0\n");
+ printf("Conv stream size: %i\n", convS->size());
+
+ while(!convS->eos()) {
+ printf("%i ", convS->readByte());
+ }
+ printf("\n");
+
+ // ------------------------------------------------------------
+ // Chunk 1
+ convS = convDataD.getItemStream(1);
+ printf("Chunk 1\n");
+ printf("Conv stream size: %i\n", convS->size());
+
+ while(!convS->eos()) {
+ printf("%i ", convS->readByte());
+ }
+ printf("\n");
+
+ // ------------------------------------------------------------
+ // Chunk 2
+ convS = convDataD.getItemStream(2);
+ printf("Chunk 2\n");
+ printf("Conv stream size: %i\n", convS->size());
+
+ while(!convS->eos()) {
+ printf("%i ", convS->readByte());
+ }
+ printf("\n");
+
+ // ------------------------------------------------------------
+ // CNV file
+ sprintf(name, "%s.cnv", convName);
+ MadsPack convData(name, _vm);
+ // *.cnv files have 7 chunks
+ // Here is the chunk output of conv001.cnv (from the dump_file command)
+ /*
+ Dumping conv001.cnv, size: 3431
+ Dumping compressed chunk 1 of 7, size is 150
+ Dumping compressed chunk 2 of 7, size is 130
+ Dumping compressed chunk 3 of 7, size is 224
+ Dumping compressed chunk 4 of 7, size is 92
+ Dumping compressed chunk 5 of 7, size is 168
+ Dumping compressed chunk 6 of 7, size is 4064
+ Dumping compressed chunk 7 of 7, size is 2334
+ */
+
+ // ------------------------------------------------------------
+ // TODO: finish this
+ // Chunk 0
+ convS = convData.getItemStream(0);
+ printf("Chunk 0\n");
+ printf("Conv stream size: %i\n", convS->size());
+ printf("%i ", convS->readUint16LE());
+ printf("%i ", convS->readUint16LE());
+ printf("%i ", convS->readUint16LE());
+ printf("%i ", convS->readUint16LE());
+ printf("%i ", convS->readUint16LE());
+ printf("%i ", convS->readUint16LE());
+ printf("\n");
+ count = convS->readUint16LE(); // conversation face count (usually 2)
+ printf("Conversation faces: %i\n", count);
+ for (i = 0; i < 5; i++) {
+ convS->read(buffer, 16);
+ printf("Face %i: %s ", i + 1, buffer);
+ }
+ printf("\n");
+
+ // 5 face slots
+ // 1 = face slot has a face (with the filename specified above)
+ // 0 = face slot doesn't contain face data
+ for (i = 0; i < 5; i++) {
+ printf("%i ", convS->readUint16LE());
+ }
+ printf("\n");
+
+ convS->read(buffer, 14); // speech file
+ printf("Speech file: %s\n", buffer);
+
+ while(!convS->eos()) {
+ printf("%i ", convS->readByte());
+ }
+ printf("\n");
+
+ delete convS;
+
+ // ------------------------------------------------------------
+ // Chunk 1: Conversation nodes
+ convS = convData.getItemStream(1);
+ printf("Chunk 1: conversation nodes\n");
+ printf("Conv stream size: %i\n", convS->size());
+
+ while(!convS->eos()) {
+ curEntry = new ConvEntry();
+ curEntry->id = convS->readUint16LE();
+ curEntry->entryCount = convS->readUint16LE();
+ curEntry->flags = convS->readUint16LE();
+ if (curEntry->entryCount == 1 && curEntry->flags != 65535) {
+ warning("Entry count is 1 and flags is not 65535 (it's %i)", flags);
+ } else if (curEntry->entryCount != 1 && flags != 0) {
+ warning("Entry count > 1 and flags is not 0 (it's %i)", flags);
+ }
+ unk = convS->readUint16LE();
+ assert (unk == 65535);
+ unk = convS->readUint16LE();
+ assert (unk == 65535);
+ _convNodes.push_back(curEntry);
+ printf("Node %i, ID %i, entries %i\n", _convNodes.size(), curEntry->id, curEntry->entryCount);
+ // flags = 0: node has more than 1 entry
+ // flags = 65535: node has 1 entry
+ }
+ printf("Conversation has %i nodes\n", _convNodes.size());
+ printf("\n");
+
+ delete convS;
+
+ // ------------------------------------------------------------
+ // Chunk 4 contains the conversation string offsets of chunk 5
+ // (unused, as it's unneeded - we find the offsets ourselves)
+
+ // ------------------------------------------------------------
+ // Chunk 5 contains the conversation strings
+ convS = convData.getItemStream(5);
+ //printf("Chunk 5: conversation strings\n");
+ //printf("Conv stream size: %i\n", convS->size());
+
+ *buffer = 0;
+
+ while(!convS->eos()) {
+ //if (curPos == 0)
+ // printf("%i: Offset %i: ", _convStrings.size(), convS->pos());
+ buffer[curPos++] = convS->readByte();
+ if (buffer[curPos - 1] == '~') { // filter out special characters
+ curPos--;
+ continue;
+ }
+ if (buffer[curPos - 1] == '\0') {
+ // end of string
+ //printf("%s\n", buffer);
+ buf = new char[strlen(buffer)];
+ sprintf(buf, "%s", buffer);
+ _convStrings.push_back(buf);
+ curPos = 0;
+ *buffer = 0;
+ }
+ }
+
+ delete convS;
+
+ // ------------------------------------------------------------
+ // Chunk 2: entry data
+ convS = convData.getItemStream(2);
+ //printf("Chunk 2 - entry data\n");
+ //printf("Conv stream size: %i\n", convS->size());
+
+ for (i = 0; i < _convNodes.size(); i++) {
+ for (j = 0; j < _convNodes[i]->entryCount; j++) {
+ curEntry = new ConvEntry();
+ stringIndex = convS->readUint16LE();
+ if (stringIndex != 65535)
+ sprintf(curEntry->text, "%s", _convStrings[stringIndex]);
+ else
+ *curEntry->text = 0;
+ curEntry->id = convS->readUint16LE();
+ curEntry->offset = convS->readUint16LE();
+ curEntry->size = convS->readUint16LE();
+
+ _convNodes[i]->entries.push_back(curEntry);
+ //printf("Node %i, entry %i, id %i, offset %i, size %i, text: %s\n",
+ // i, j, curEntry->id, curEntry->offset, curEntry->size, curEntry->text);
+ }
+ }
+
+ delete convS;
+
+ // ------------------------------------------------------------
+ // Chunk 3: message (MESG) chunks, created from the strings of chunk 5
+ convS = convData.getItemStream(3);
+ //printf("Chunk 3 - MESG chunk data\n");
+ //printf("Conv stream size: %i\n", convS->size());
+
+ while(!convS->eos()) {
+ curMessage = new MessageEntry();
+ stringIndex = convS->readUint16LE();
+ stringCount = convS->readUint16LE();
+ *buffer = 0;
+ //printf("Message: %i\n", _madsMessageList.size());
+ for (i = stringIndex; i < stringIndex + stringCount; i++) {
+ //printf("%i: %s\n", i, _convStrings[i]);
+ curMessage->messageStrings.push_back(_convStrings[i]);
+ }
+ _madsMessageList.push_back(curMessage);
+ //printf("----------\n");
+ }
+ //printf("\n");
+
+ delete convS;
+
+ // ------------------------------------------------------------
+ // TODO: finish this
+ // Chunk 6: conversation script
+ convS = convData.getItemStream(6);
+ printf("Chunk 6\n");
+ printf("Conv stream size: %i\n", convS->size());
+ /*while(!convS->eos()) {
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("%i ", convS->readByte());
+ printf("\n");
+ }
+ return;*/
+
+ for (i = 0; i < _convNodes.size(); i++) {
+ for (j = 0; j < _convNodes[i]->entryCount; j++) {
+ printf("*** Node %i entry %i data size %i\n", i, j, _convNodes[i]->entries[j]->size);
+ printf("Entry ID %i, text %s\n", _convNodes[i]->entries[j]->id, _convNodes[i]->entries[j]->text);
+ Common::SubReadStream *entryStream = new Common::SubReadStream(convS, _convNodes[i]->entries[j]->size);
+ readConvEntryActions(entryStream, _convNodes[i]->entries[j]);
+ delete entryStream;
+ printf("--------------------\n");
+ }
+ }
+
+ delete convS;
+}
+
+void Converse::readConvEntryActions(Common::SubReadStream *convS, ConvEntry *curEntry) {
+ uint8 chunk;
+ uint8 type; // 255: normal, 11: conditional
+ uint8 hasText1, hasText2;
+ int target;
+ int count = 0;
+ int var, val;
+ int messageIndex = 0;
+ int unk = 0;
+
+ while(!convS->eos()) {
+ chunk = convS->readByte();
+ type = convS->readByte();
+
+ switch (chunk) {
+ case 1:
+ printf("TODO: chunk type %i\n", chunk);
+ break;
+ case 2:
+ printf("HIDE\n");
+ convS->readByte();
+ count = convS->readByte();
+ printf("%i entries: ", count);
+ for (int i = 0; i < count; i++)
+ printf("%i %d", i, convS->readUint16LE());
+ printf("\n");
+ break;
+ case 3:
+ printf("UNHIDE\n");
+ convS->readByte();
+ count = convS->readByte();
+ printf("%i entries: ", count);
+ for (int i = 0; i < count; i++)
+ printf("%i %d", i, convS->readUint16LE());
+ printf("\n");
+ break;
+ case 4: // MESSAGE
+ printf("MESSAGE\n");
+
+ if (type == 255) {
+ //printf("unconditional\n");
+ } else if (type == 11) {
+ //printf("conditional\n");
+ } else {
+ printf("unknown type: %i\n", type);
+ }
+
+ // Conditional part
+ if (type == 11) {
+ unk = convS->readUint16LE(); // 1
+ if (unk != 1)
+ printf("Message: unk != 1 (it's %i)\n", unk);
+
+ var = convS->readUint16LE();
+ val = convS->readUint16LE();
+ printf("Var %i == %i\n", var, val);
+ }
+ unk = convS->readUint16LE(); // 256
+ if (unk != 256)
+ printf("Message: unk != 256 (it's %i)\n", unk);
+
+ // it seems that the first text entry is set when the message
+ // chunk is supposed to be shown unconditionally, whereas the second text
+ // entry is set when the message is supposed to be shown conditionally
+ hasText1 = convS->readByte();
+ hasText2 = convS->readByte();
+
+ if (hasText1 == 1) {
+ messageIndex = convS->readUint16LE();
+ printf("Message 1 index: %i, text:\n", messageIndex);
+ for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) {
+ printf("%s\n", _madsMessageList[messageIndex]->messageStrings[i]);
+ }
+ }
+
+ if (hasText2 == 1) {
+ messageIndex = convS->readUint16LE();
+ if (hasText1 == 0) {
+ printf("Message 2 index: %i, text:\n", messageIndex);
+ for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) {
+ printf("%s\n", _madsMessageList[messageIndex]->messageStrings[i]);
+ }
+ }
+ }
+
+ break;
+ case 5: // AUTO
+ printf("AUTO\n");
+ for (int k = 0; k < 4; k++)
+ convS->readByte();
+ messageIndex = convS->readUint16LE();
+ printf("Message index: %i, text:\n", messageIndex);
+ for (uint32 i = 0; i < _madsMessageList[messageIndex]->messageStrings.size(); i++) {
+ printf("%s\n", _madsMessageList[messageIndex]->messageStrings[i]);
+ }
+
+ convS->readUint16LE();
+ break;
+ case 6:
+ printf("TODO: chunk type %i\n", chunk);
+ break;
+ case 7: // GOTO
+ unk = convS->readUint32LE(); // 0
+ if (unk != 0 && unk != 1)
+ printf("Goto: unk != 0 or 1 (it's %i)\n", unk);
+
+ target = convS->readUint16LE();
+ convS->readUint16LE(); // 255
+
+ if (unk != 0)
+ printf("Goto: unk != 0 (it's %i)\n", unk);
+
+ if (target != 65535)
+ printf("GOTO node %i\n", target);
+ else
+ printf("GOTO exit\n");
+ break;
+ case 8:
+ printf("TODO: chunk type %i\n", chunk);
+ break;
+ case 9: // ASSIGN
+ //printf("ASSIGN\n");
+ unk = convS->readUint32LE(); // 0
+
+ if (unk != 0)
+ printf("Assign: unk != 0 (it's %i)\n", unk);
+
+ val = convS->readUint16LE();
+ var = convS->readUint16LE();
+ //printf("Var %i = %i\n", var, val);
+ break;
+ default:
+ printf ("Unknown chunk type! (%i)\n", chunk);
+ break;
+ }
+ }
+ printf("\n");
+}
+
+void Converse::setEntryInfo(int32 offset, EntryType type, int32 nodeIndex, int32 entryIndex) {
+ char hashOffset[10];
+ sprintf(hashOffset, "%i", offset);
+ EntryInfo info;
+ info.targetType = type;
+ info.nodeIndex = nodeIndex;
+ info.entryIndex = entryIndex;
+ _offsetMap[hashOffset] = info;
+ //printf("Set entry info: offset %i, type %i, node %i, entry %i\n", offset, type, nodeIndex, entryIndex);
+}
+
+const EntryInfo* Converse::getEntryInfo(int32 offset) {
+ char hashOffset[10];
+ sprintf(hashOffset, "%i", offset);
+ OffsetHashMap::const_iterator entry = _offsetMap.find(hashOffset);
+ if (entry != _offsetMap.end())
+ return &(entry->_value);
+ else
+ error("Undeclared entry offset: %i", offset);
+}
+
+void Converse::setValue(int32 offset, int32 value) {
+ char hashOffset[10];
+ sprintf(hashOffset, "%i", offset);
+ _variables[hashOffset] = value;
+}
+
+const int32 Converse::getValue(int32 offset) {
+ char hashOffset[10];
+ sprintf(hashOffset, "%i", offset);
+ ConvVarHashMap::const_iterator entry = _variables.find(hashOffset);
+ if (entry != _variables.end())
+ return entry->_value;
+ else
+ error("Undeclared variable offset: %i", offset);
+}
+
+bool Converse::evaluateCondition(int32 leftVal, int32 op, int32 rightVal) {
+ switch (op) {
+ case kOpPercent:
+ return (leftVal % rightVal == 0);
+ case kOpGreaterOrEqual:
@@ Diff output truncated at 100000 characters. @@
This was sent by the SourceForge.net collaborative development platform, the world's largest Open Source development site.
More information about the Scummvm-git-logs
mailing list