[Scummvm-cvs-logs] SF.net SVN: scummvm:[55215] scummvm/trunk/engines/mohawk

fuzzie at users.sourceforge.net fuzzie at users.sourceforge.net
Wed Jan 12 20:11:27 CET 2011


Revision: 55215
          http://scummvm.svn.sourceforge.net/scummvm/?rev=55215&view=rev
Author:   fuzzie
Date:     2011-01-12 19:11:27 +0000 (Wed, 12 Jan 2011)

Log Message:
-----------
MOHAWK: Add a basic LBCode implementation.

This is enough for the Rugrats Adventure Game to play the introduction
videos, but is still in a very preliminary state.

Modified Paths:
--------------
    scummvm/trunk/engines/mohawk/livingbooks.cpp
    scummvm/trunk/engines/mohawk/livingbooks.h
    scummvm/trunk/engines/mohawk/module.mk

Added Paths:
-----------
    scummvm/trunk/engines/mohawk/livingbooks_code.cpp
    scummvm/trunk/engines/mohawk/livingbooks_code.h

Modified: scummvm/trunk/engines/mohawk/livingbooks.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/livingbooks.cpp	2011-01-12 12:31:18 UTC (rev 55214)
+++ scummvm/trunk/engines/mohawk/livingbooks.cpp	2011-01-12 19:11:27 UTC (rev 55215)
@@ -80,6 +80,8 @@
 
 	_alreadyShowedIntro = false;
 
+	_code = NULL;
+
 	_rnd = new Common::RandomSource();
 	g_eventRec.registerRandomSource(*_rnd, "livingbooks");
 
@@ -260,6 +262,9 @@
 
 	_eventQueue.clear();
 
+	delete _code;
+	_code = NULL;
+
 	for (uint32 i = 0; i < _items.size(); i++)
 		delete _items[i];
 	_items.clear();
@@ -330,8 +335,11 @@
 	_cursor->showCursor();
 
 	_gfx->setPalette(1000);
+
+	if (hasResource(ID_BCOD, 1000))
+		_code = new LBCode(this);
+
 	loadBITL(1000);
-
 	for (uint32 i = 0; i < _items.size(); i++)
 		_items[i]->init();
 
@@ -1875,6 +1883,8 @@
 		_delayMin = stream->readUint16();
 		_delayMax = stream->readUint16();
 		_timingMode = stream->readUint16();
+		if (_timingMode > 7)
+			error("encountered timing mode %04x", _timingMode);
 		_periodMin = stream->readUint16();
 		_periodMax = stream->readUint16();
 		_relocPoint.x = stream->readSint16();
@@ -1903,16 +1913,16 @@
 			error("0x6f had wrong size (%d)", size);
 		uint u1 = stream->readUint16();
 		uint u2 = stream->readUint16();
-		uint u3 = stream->readUint16();
-		uint u4 = stream->readUint16();
-		uint u5 = stream->readUint16();
+		uint event = stream->readUint16();
+		uint opcode = stream->readUint16();
+		uint param = stream->readUint16();
 		uint u6 = stream->readUint16();
 		uint u7 = stream->readUint16();
 		uint u8 = stream->readUint16();
 		uint u9 = stream->readUint16();
 		// FIXME: this is scripting stuff
-		debug(2, "0x6f: item %s, unknowns: %04x, %04x, %04x, %04x, %04x, %04x, %04x, %04x, %04x\n",
-			_desc.c_str(), u1, u2, u3, u4, u5, u6, u7, u8, u9);
+		warning("0x6f: unknown: item %s, unknowns: %04x, %04x, event %04x, opcode %04x, param %04x, unknowns %04x, %04x, %04x, %04x",
+			_desc.c_str(), u1, u2, event, opcode, param, u6, u7, u8, u9);
 		}
 		break;
 
@@ -1951,16 +1961,36 @@
 		if (size != 10)
 			error("0x7d had wrong size (%d)", size);
 		uint u1 = stream->readUint16();
-		uint u2 = stream->readUint16();
+		uint key = stream->readUint16();
 		uint u3 = stream->readUint16();
-		uint u4 = stream->readUint16();
-		uint u5 = stream->readUint16();
-		// FIXME: this is scripting stuff
-		debug(2, "0x7d: item %s, unknowns: %04x, %04x, %04x, %04x, %04x\n",
-			_desc.c_str(), u1, u2, u3, u4, u5);
+		uint target = stream->readUint16();
+		byte event = stream->readByte();
+		byte u4 = stream->readByte();
+		// FIXME: this is scripting stuff: what to run when key is pressed
+		warning("0x7d: unknown: item %s, unknown %04x, key %04x, unknown %04x, target %d, event %02x, unknown %02x",
+			_desc.c_str(), u1, key, u3, target, event, u4);
 		}
 		break;
 
+	case kLBUnknown80:
+		{
+		assert(size == 2);
+		uint id = stream->readUint16();
+		warning("0x80: unknown: item %s, id %04x", _desc.c_str(), id);
+		// FIXME
+		}
+		break;
+
+	case kLBUnknown194:
+		{
+		assert(size == 4);
+		uint offset = stream->readUint32();
+		if (!_vm->_code)
+			error("no BCOD?");
+		_vm->_code->runCode(this, offset);
+		}
+		break;
+
 	default:
 		error("Unknown message %04x (size 0x%04x)", type, size);
 		//for (uint i = 0; i < size; i++)
@@ -2009,7 +2039,7 @@
 }
 
 void LBItem::update() {
-	if (_neverEnabled || !_enabled || !_globalEnabled)
+	if (_phase != 0x7FFF && (_neverEnabled || !_enabled || !_globalEnabled))
 		return;
 
 	if (_nextTime == 0 || _nextTime > (uint32)(_vm->_system->getMillis() / 16))
@@ -2047,7 +2077,7 @@
 		_vm->queueDelayedEvent(DelayedEvent(this, kLBDelayedEventDone));
 		return true;
 	}
-	if (!_neverEnabled && _enabled && _globalEnabled && !_playing) {
+	if (((!_neverEnabled && _enabled && _globalEnabled) || _phase == 0x7FFF) && !_playing) {
 		_playing = togglePlaying(true, restart);
 		if (_playing) {
 			_nextTime = 0;
@@ -2387,9 +2417,9 @@
 			break;
 
 		case kLBOpSendExpression:
-			// FIXME
-			warning("ignoring kLBOpSendExpression (event 0x%04x, param 0x%04x, target '%s')",
-				entry->event, entry->param, target->_desc.c_str());
+			if (!_vm->_code)
+				error("no BCOD?");
+			_vm->_code->runCode(this, entry->offset);
 			break;
 
 		case kLBOpRunSubentries:

Modified: scummvm/trunk/engines/mohawk/livingbooks.h
===================================================================
--- scummvm/trunk/engines/mohawk/livingbooks.h	2011-01-12 12:31:18 UTC (rev 55214)
+++ scummvm/trunk/engines/mohawk/livingbooks.h	2011-01-12 19:11:27 UTC (rev 55215)
@@ -38,6 +38,8 @@
 
 #include "sound/mixer.h"
 
+#include "livingbooks_code.h"
+
 namespace Mohawk {
 
 enum NodeState {
@@ -86,7 +88,8 @@
 	kLBPaletteAItem = 0x44, // unused?
 	kLBPaletteItem = 0x45,
 	kLBProxyItem = 0x46,
-	kLBXDataFileItem = 0x3e9
+	kLBXDataFileItem = 0x3e9,
+	kLBDiscDectectorItem = 0xfa1
 };
 
 enum {
@@ -163,9 +166,11 @@
 	kLBSetAmbient = 0x7b,
 	kLBUnknown7C = 0x7c,     // unused?
 	kLBUnknown7D = 0x7d,
-	kLBUnknown7E = 0x7e,     // unused?
+	kLBUnknown7E = 0x7e,     // unused? (rect flag)
 	kLBSetParent = 0x7f,     // unused?
-	kLBUnknown80 = 0x80      // unused?
+	kLBUnknown80 = 0x80,      // unused? TODO: sets +36
+	// from here, rugrats
+	kLBUnknown194 = 0x194
 };
 
 enum {
@@ -321,23 +326,9 @@
 	Common::Array<Common::Point> _shapeOffsets;
 };
 
-enum LBValueType {
-	kLBValueString,
-	kLBValueInteger
-};
-
-struct LBValue {
-	LBValue() { type = kLBValueInteger; integer = 0; }
-
-	LBValueType type;
-	Common::String string;
-	int integer;
-
-	bool operator==(const LBValue &x) const;
-	bool operator!=(const LBValue &x) const;
-};
-
 class LBItem {
+	friend class LBCode;
+
 public:
 	LBItem(MohawkEngine_LivingBooks *vm, Common::Rect rect);
 	virtual ~LBItem();
@@ -599,6 +590,8 @@
 	void prevPage();
 	void nextPage();
 
+	LBCode *_code;
+
 	// TODO: make private
 	Common::HashMap<Common::String, LBValue> _variables;
 

Added: scummvm/trunk/engines/mohawk/livingbooks_code.cpp
===================================================================
--- scummvm/trunk/engines/mohawk/livingbooks_code.cpp	                        (rev 0)
+++ scummvm/trunk/engines/mohawk/livingbooks_code.cpp	2011-01-12 19:11:27 UTC (rev 55215)
@@ -0,0 +1,386 @@
+/* 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 "mohawk/livingbooks.h"
+#include "mohawk/resource.h"
+
+namespace Mohawk {
+
+LBCode::LBCode(MohawkEngine_LivingBooks *vm) : _vm(vm) {
+	Common::SeekableSubReadStreamEndian *bcodStream = _vm->wrapStreamEndian(ID_BCOD, 1000);
+	uint32 totalSize = bcodStream->readUint32();
+	if (totalSize != (uint32)bcodStream->size())
+		error("BCOD had size %d, but claimed to be of size %d", bcodStream->size(), totalSize);
+	size = bcodStream->readUint32();
+	if (size + 8 > totalSize)
+		error("BCOD code was of size %d, beyond size %d", size, totalSize);
+	data = new byte[size];
+	bcodStream->read(data, size);
+	uint16 pos = 0;
+	while (bcodStream->pos() < bcodStream->size()) {
+		uint16 unknown = bcodStream->readUint16();
+		if (unknown != 0) {
+			warning("unknown was %04x, not zero, while reading strings", unknown);
+			if (bcodStream->pos() != bcodStream->size())
+				error(".. and there was more data afterwards");
+			break;
+		}
+		Common::String string = _vm->readString(bcodStream);
+		strings[pos] = string;
+		debug(2, "read '%s' from BCOD at 0x%04x", string.c_str(), pos);
+		pos += 2 + string.size() + 1;
+	}
+}
+
+LBCode::~LBCode() {
+	delete[] data;
+}
+
+Common::Array<LBValue> LBCode::readParams(LBItem *src, uint32 &offset) {
+	Common::Array<LBValue> params;
+
+	if (offset + 1 >= size)
+		error("went off the end of code");
+
+	byte numParams = data[offset];
+	offset++;
+
+	if (!numParams) {
+		debugN("()\n");
+		return params;
+	}
+
+	byte nextToken = data[offset];
+	offset++;
+	if (nextToken != kLBCodeTokenOpenBracket)
+		error("missing ( before code parameter list (got %02x)", nextToken);
+	debugN("(");
+
+	for (uint i = 0; i < numParams; i++) {
+		if (i != 0) {
+			nextToken = data[offset];
+			offset++;
+			if (nextToken != ',')
+				error("missing , between code parameters (got %02x)", nextToken);
+			debugN(", ");
+		}
+
+		nextToken = data[offset];
+		offset++;
+
+		LBValue nextValue;
+
+		switch (nextToken) {
+		case kLBCodeTokenLiteral:
+			{
+			byte literalType = data[offset];
+			offset++;
+			if (literalType == kLBCodeLiteralInteger) {
+				uint16 intValue = READ_BE_UINT16(data + offset);
+				offset += 2;
+				nextValue.type = kLBValueInteger;
+				nextValue.integer = intValue;
+				debugN("%d", nextValue.integer);
+			} else
+				error("unknown literal type %02x in code", literalType);
+			}
+			break;
+
+		case kLBCodeTokenString:
+			{
+			uint16 stringOffset = READ_BE_UINT16(data + offset);
+			offset += 2;
+			// TODO: check string exists
+			nextValue.type = kLBValueString;
+			nextValue.string = strings[stringOffset];
+			debugN("\"%s\"", nextValue.string.c_str());
+			}
+			break;
+
+		case kLBCodeTokenChar:
+			{
+			uint16 stringOffset = READ_BE_UINT16(data + offset);
+			offset += 2;
+			// TODO: check string exists
+			nextValue.type = kLBValueString;
+			nextValue.string = strings[stringOffset];
+			debugN("'%s'", nextValue.string.c_str());
+			}
+			break;
+
+		case kLBCodeTokenLong: // FIXME: wrong?
+			{
+			uint32 intValue = READ_BE_UINT32(data + offset);
+			offset += 4;
+			nextValue.type = kLBValueInteger;
+			nextValue.integer = intValue;
+			debugN("%d", nextValue.integer);
+			}
+			break;
+
+		case 0x31:
+			{
+			// TODO
+			uint16 intValue = READ_BE_UINT16(data + offset);
+			offset += 2;
+			nextValue.type = kLBValueInteger;
+			nextValue.integer = intValue;
+			debugN("%d", nextValue.integer);
+			}
+			break;
+
+		case 0x4d:
+			// TODO
+			runCodeCommand(src, offset);
+			break;
+
+		case 0x5f:
+			// keycode
+			nextValue.type = kLBValueInteger;
+			nextValue.integer = data[offset];
+			debugN("%d", nextValue.integer);
+			offset++;
+			offset++; // TODO
+			break;
+
+		default:
+			error("unknown token %02x in code parameter", nextToken);
+		}
+
+		params.push_back(nextValue);
+	}
+
+	nextToken = data[offset];
+	offset++;
+	if (nextToken != kLBCodeTokenCloseBracket)
+		error("missing ) after code parameter list (got %02x)", nextToken);
+	debugN(")");
+
+	return params;
+}
+
+void LBCode::runCodeCommand(LBItem *src, uint32 &offset) {
+	if (offset + 1 >= size)
+		error("went off the end of code");
+
+	byte commandType = data[offset];
+	offset++;
+
+	switch (commandType) {
+	case 0x23:
+		{
+		debugN("setViewOrigin");
+		Common::Array<LBValue> params = readParams(src, offset);
+		// TODO
+		}
+		break;
+
+	case 0x36:
+		{
+		debugN("setWorld");
+		Common::Array<LBValue> params = readParams(src, offset);
+		// TODO
+		}
+		break;
+
+	case 0x42:
+		{
+		debugN("setPlayParams");
+		Common::Array<LBValue> params = readParams(src, offset);
+		if (params.size() > 8)
+			error("too many parameters (%d) to setPlayParams", params.size());
+		if (!params.size())
+			error("no target for setPlayParams");
+		LBItem *target;
+		if (params[0].string.equalsIgnoreCase("self")) {
+			target = src;
+		} else {
+			error("didn't understand target '%s'", params[0].string.c_str());
+		}
+		// TODO: type-checking
+		switch (params.size()) {
+		case 8:
+			target->_soundMode = params[7].integer;
+		case 7:
+			target->_controlMode = params[6].integer;
+		case 6:
+			// TODO: _relocPoint?
+		case 5:
+			// TODO: _periodMin/Max
+		case 4:
+			target->_timingMode = params[3].integer;
+		case 3:
+			// TODO: _delayMin/Max
+		case 2:
+			target->_loopMode = params[1].integer;
+		}
+		}
+		break;
+
+	case 0x50:
+		{
+		debugN("setKeyEvent");
+		Common::Array<LBValue> params = readParams(src, offset);
+		if (params.size() != 2)
+			error("incorrect number of parameters (%d) to setKeyEvent", params.size());
+		// FIXME: params[0] is key, params[1] is opcode id
+		}
+		break;
+
+	case 0x51:
+		{
+		debugN("setHitTest");
+		Common::Array<LBValue> params = readParams(src, offset);
+		if (params.size() > 2)
+			error("incorrect number of parameters (%d) to setHitTest", params.size());
+		// TODO
+		}
+		break;
+
+	case 0x52:
+		{
+		debugN("key");
+		Common::Array<LBValue> params = readParams(src, offset);
+		// TODO
+		}
+		break;
+
+	case 0x5E:
+		{
+		debugN("setPageFade");
+		Common::Array<LBValue> params = readParams(src, offset);
+		// TODO
+		}
+		break;
+
+	default:
+		error("unknown command %02x in code", commandType);
+	}
+}
+
+void LBCode::runCodeItemCommand(LBItem *src, uint32 &offset) {
+	if (offset + 1 >= size)
+		error("went off the end of code");
+
+	byte commandType = data[offset];
+	offset++;
+
+	switch (commandType) {
+	case 0x1d:
+		{
+		debugN("setParent");
+		Common::Array<LBValue> params = readParams(src, offset);
+		if (params.size() > 2)
+			error("incorrect number of parameters (%d) to setParent", params.size());
+		// TODO
+		}
+		break;
+
+	default:
+		error("unknown item command %02x in code", commandType);
+	}
+}
+
+void LBCode::runCodeNotifyCommand(LBItem *src, uint32 &offset) {
+	if (offset + 1 >= size)
+		error("went off the end of code");
+
+	byte commandType = data[offset];
+	offset++;
+
+	switch (commandType) {
+	case 0x3:
+		{
+		debugN("goto");
+		Common::Array<LBValue> params = readParams(src, offset);
+		// TODO: type-checking
+		switch (params.size()) {
+		case 1:
+			_vm->addNotifyEvent(NotifyEvent(kLBNotifyChangePage, params[0].integer));
+			break;
+
+		case 2:
+			// FIXME
+		case 4:
+			// FIXME
+
+		default:
+			error("incorrect number of parameters (%d) to goto", params.size());
+		}
+		}
+		break;
+
+	default:
+		error("unknown notify command %02x in code", commandType);
+	}
+}
+
+void LBCode::runCode(LBItem *src, uint32 offset) {
+	while (true) {
+		if (offset + 1 >= size) {
+			warning("went off the end of code");
+			return;
+		}
+
+		byte tokenType = data[offset];
+		offset++;
+
+		switch (tokenType) {
+		case 0x01: // FIXME
+		case kLBCodeTokenEndOfFile:
+			return;
+
+		case 0x4D:
+			runCodeCommand(src, offset);
+			break;
+
+		case 0x4E:
+			runCodeItemCommand(src, offset);
+			break;
+
+		case 0x4F:
+			runCodeNotifyCommand(src, offset);
+			break;
+
+		default:
+			debugN("at %04x: %02x ", offset - 1, tokenType);
+			for (uint i = 0; i < size; i++)
+				debugN("%02x ", data[offset++]);
+			debugN("\n");
+			error("unknown token %02x in code", tokenType);
+		}
+
+		byte nextToken = data[offset];
+		offset++;
+		if (nextToken != kLBCodeTokenEndOfStatement)
+			warning("missing EndOfStatement after code statement (got %04x)", nextToken);
+		if (nextToken == kLBCodeTokenEndOfFile)
+			return;
+
+		debugN("\n");
+	}
+}
+
+} // End of namespace Mohawk


Property changes on: scummvm/trunk/engines/mohawk/livingbooks_code.cpp
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Added: scummvm/trunk/engines/mohawk/livingbooks_code.h
===================================================================
--- scummvm/trunk/engines/mohawk/livingbooks_code.h	                        (rev 0)
+++ scummvm/trunk/engines/mohawk/livingbooks_code.h	2011-01-12 19:11:27 UTC (rev 55215)
@@ -0,0 +1,94 @@
+/* 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 MOHAWK_LIVINGBOOKS_CODE_H
+#define MOHAWK_LIVINGBOOKS_CODE_H
+
+#include "common/substream.h"
+
+namespace Mohawk {
+
+class MohawkEngine_LivingBooks;
+class LBItem;
+
+enum LBValueType {
+	kLBValueString,
+	kLBValueInteger
+};
+
+struct LBValue {
+	LBValue() { type = kLBValueInteger; integer = 0; }
+
+	LBValueType type;
+	Common::String string;
+	int integer;
+
+	bool operator==(const LBValue &x) const;
+	bool operator!=(const LBValue &x) const;
+};
+
+enum {
+	kLBCodeLiteralInteger = 0x1
+};
+
+enum {
+	kLBCodeTokenString = 0x1,
+	kLBCodeTokenLiteral = 0x5,
+	kLBCodeTokenChar = 0x6,
+	kLBCodeTokenEndOfStatement = 0x7,
+	kLBCodeTokenEndOfFile = 0x8,
+	kLBCodeTokenOpenBracket = 0xf,
+	kLBCodeTokenCloseBracket = 0x10,
+	kLBCodeTokenLong = 0x11,
+
+	kLBCodeTokenEquals = 0x22, // TODO: maybe..
+	kLBCodeTokenQuote = 0x27, // "'"
+	kLBCodeTokenComma = 0x2c // ","
+};
+
+class LBCode {
+public:
+	LBCode(MohawkEngine_LivingBooks *vm);
+	~LBCode();
+
+	void runCode(LBItem *src, uint32 offset);
+
+protected:
+	MohawkEngine_LivingBooks *_vm;
+
+	uint32 size;
+	byte *data;
+
+	Common::HashMap<uint16, Common::String> strings;
+
+	Common::Array<LBValue> readParams(LBItem *src, uint32 &offset);
+	void runCodeCommand(LBItem *src, uint32 &offset);
+	void runCodeItemCommand(LBItem *src, uint32 &offset);
+	void runCodeNotifyCommand(LBItem *src, uint32 &offset);
+};
+
+} // End of namespace Mohawk
+
+#endif


Property changes on: scummvm/trunk/engines/mohawk/livingbooks_code.h
___________________________________________________________________
Added: svn:mime-type
   + text/plain
Added: svn:keywords
   + Date Rev Author URL Id
Added: svn:eol-style
   + native

Modified: scummvm/trunk/engines/mohawk/module.mk
===================================================================
--- scummvm/trunk/engines/mohawk/module.mk	2011-01-12 12:31:18 UTC (rev 55214)
+++ scummvm/trunk/engines/mohawk/module.mk	2011-01-12 19:11:27 UTC (rev 55215)
@@ -8,6 +8,7 @@
 	dialogs.o \
 	graphics.o \
 	livingbooks.o \
+	livingbooks_code.o \
 	mohawk.o \
 	myst.o \
 	myst_areas.o \


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