aboutsummaryrefslogtreecommitdiff
path: root/engines/wintermute/base
diff options
context:
space:
mode:
Diffstat (limited to 'engines/wintermute/base')
-rw-r--r--engines/wintermute/base/base.cpp185
-rw-r--r--engines/wintermute/base/base.h62
-rw-r--r--engines/wintermute/base/base_active_rect.cpp110
-rw-r--r--engines/wintermute/base/base_active_rect.h60
-rw-r--r--engines/wintermute/base/base_dynamic_buffer.cpp204
-rw-r--r--engines/wintermute/base/base_dynamic_buffer.h66
-rw-r--r--engines/wintermute/base/base_engine.cpp93
-rw-r--r--engines/wintermute/base/base_engine.h69
-rw-r--r--engines/wintermute/base/base_fader.cpp194
-rw-r--r--engines/wintermute/base/base_fader.h63
-rw-r--r--engines/wintermute/base/base_file_manager.cpp340
-rw-r--r--engines/wintermute/base/base_file_manager.h76
-rw-r--r--engines/wintermute/base/base_frame.cpp760
-rw-r--r--engines/wintermute/base/base_frame.h73
-rw-r--r--engines/wintermute/base/base_game.cpp4483
-rw-r--r--engines/wintermute/base/base_game.h362
-rw-r--r--engines/wintermute/base/base_keyboard_state.cpp309
-rw-r--r--engines/wintermute/base/base_keyboard_state.h75
-rw-r--r--engines/wintermute/base/base_named_object.cpp71
-rw-r--r--engines/wintermute/base/base_named_object.h51
-rw-r--r--engines/wintermute/base/base_object.cpp1246
-rw-r--r--engines/wintermute/base/base_object.h147
-rw-r--r--engines/wintermute/base/base_parser.cpp467
-rw-r--r--engines/wintermute/base/base_parser.h88
-rw-r--r--engines/wintermute/base/base_persistence_manager.cpp828
-rw-r--r--engines/wintermute/base/base_persistence_manager.h118
-rw-r--r--engines/wintermute/base/base_point.cpp63
-rw-r--r--engines/wintermute/base/base_point.h50
-rw-r--r--engines/wintermute/base/base_quick_msg.cpp57
-rw-r--r--engines/wintermute/base/base_quick_msg.h48
-rw-r--r--engines/wintermute/base/base_region.cpp535
-rw-r--r--engines/wintermute/base/base_region.h69
-rw-r--r--engines/wintermute/base/base_save_thumb_helper.cpp80
-rw-r--r--engines/wintermute/base/base_save_thumb_helper.h51
-rw-r--r--engines/wintermute/base/base_script_holder.cpp502
-rw-r--r--engines/wintermute/base/base_script_holder.h76
-rw-r--r--engines/wintermute/base/base_scriptable.cpp191
-rw-r--r--engines/wintermute/base/base_scriptable.h83
-rw-r--r--engines/wintermute/base/base_sprite.cpp814
-rw-r--r--engines/wintermute/base/base_sprite.h90
-rw-r--r--engines/wintermute/base/base_string_table.cpp255
-rw-r--r--engines/wintermute/base/base_string_table.h55
-rw-r--r--engines/wintermute/base/base_sub_frame.cpp655
-rw-r--r--engines/wintermute/base/base_sub_frame.h92
-rw-r--r--engines/wintermute/base/base_surface_storage.cpp207
-rw-r--r--engines/wintermute/base/base_surface_storage.h57
-rw-r--r--engines/wintermute/base/base_transition_manager.cpp136
-rw-r--r--engines/wintermute/base/base_transition_manager.h54
-rw-r--r--engines/wintermute/base/base_viewport.cpp98
-rw-r--r--engines/wintermute/base/base_viewport.h55
-rw-r--r--engines/wintermute/base/file/base_disk_file.cpp196
-rw-r--r--engines/wintermute/base/file/base_disk_file.h41
-rw-r--r--engines/wintermute/base/file/base_file.cpp68
-rw-r--r--engines/wintermute/base/file/base_file.h67
-rw-r--r--engines/wintermute/base/file/base_file_entry.cpp73
-rw-r--r--engines/wintermute/base/file/base_file_entry.h60
-rw-r--r--engines/wintermute/base/file/base_package.cpp276
-rw-r--r--engines/wintermute/base/file/base_package.h90
-rw-r--r--engines/wintermute/base/file/base_resources.cpp2830
-rw-r--r--engines/wintermute/base/file/base_resources.h45
-rw-r--r--engines/wintermute/base/file/base_save_thumb_file.cpp154
-rw-r--r--engines/wintermute/base/file/base_save_thumb_file.h52
-rw-r--r--engines/wintermute/base/file/dcpackage.h80
-rw-r--r--engines/wintermute/base/font/base_font.cpp140
-rw-r--r--engines/wintermute/base/font/base_font.h61
-rw-r--r--engines/wintermute/base/font/base_font_bitmap.cpp589
-rw-r--r--engines/wintermute/base/font/base_font_bitmap.h71
-rw-r--r--engines/wintermute/base/font/base_font_storage.cpp142
-rw-r--r--engines/wintermute/base/font/base_font_storage.h55
-rw-r--r--engines/wintermute/base/font/base_font_truetype.cpp605
-rw-r--r--engines/wintermute/base/font/base_font_truetype.h152
-rw-r--r--engines/wintermute/base/gfx/base_image.cpp231
-rw-r--r--engines/wintermute/base/gfx/base_image.h72
-rw-r--r--engines/wintermute/base/gfx/base_renderer.cpp381
-rw-r--r--engines/wintermute/base/gfx/base_renderer.h221
-rw-r--r--engines/wintermute/base/gfx/base_surface.cpp149
-rw-r--r--engines/wintermute/base/gfx/base_surface.h99
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.cpp604
-rw-r--r--engines/wintermute/base/gfx/osystem/base_render_osystem.h131
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp429
-rw-r--r--engines/wintermute/base/gfx/osystem/base_surface_osystem.h99
-rw-r--r--engines/wintermute/base/particles/part_emitter.cpp1256
-rw-r--r--engines/wintermute/base/particles/part_emitter.h140
-rw-r--r--engines/wintermute/base/particles/part_force.cpp65
-rw-r--r--engines/wintermute/base/particles/part_force.h57
-rw-r--r--engines/wintermute/base/particles/part_particle.cpp269
-rw-r--r--engines/wintermute/base/particles/part_particle.h90
-rw-r--r--engines/wintermute/base/saveload.cpp203
-rw-r--r--engines/wintermute/base/saveload.h57
-rw-r--r--engines/wintermute/base/scriptables/dcscript.h141
-rw-r--r--engines/wintermute/base/scriptables/script.cpp1467
-rw-r--r--engines/wintermute/base/scriptables/script.h174
-rw-r--r--engines/wintermute/base/scriptables/script_engine.cpp610
-rw-r--r--engines/wintermute/base/scriptables/script_engine.h135
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.cpp252
-rw-r--r--engines/wintermute/base/scriptables/script_ext_array.h56
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.cpp293
-rw-r--r--engines/wintermute/base/scriptables/script_ext_date.h54
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.cpp829
-rw-r--r--engines/wintermute/base/scriptables/script_ext_file.h66
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.cpp295
-rw-r--r--engines/wintermute/base/scriptables/script_ext_math.h53
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp529
-rw-r--r--engines/wintermute/base/scriptables/script_ext_mem_buffer.h60
-rw-r--r--engines/wintermute/base/scriptables/script_ext_object.cpp67
-rw-r--r--engines/wintermute/base/scriptables/script_ext_object.h46
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.cpp436
-rw-r--r--engines/wintermute/base/scriptables/script_ext_string.h58
-rw-r--r--engines/wintermute/base/scriptables/script_stack.cpp232
-rw-r--r--engines/wintermute/base/scriptables/script_stack.h66
-rw-r--r--engines/wintermute/base/scriptables/script_value.cpp995
-rw-r--r--engines/wintermute/base/scriptables/script_value.h113
-rw-r--r--engines/wintermute/base/sound/base_sound.cpp292
-rw-r--r--engines/wintermute/base/sound/base_sound.h87
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.cpp297
-rw-r--r--engines/wintermute/base/sound/base_sound_buffer.h100
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.cpp282
-rw-r--r--engines/wintermute/base/sound/base_sound_manager.h68
118 files changed, 33526 insertions, 0 deletions
diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp
new file mode 100644
index 0000000000..e351792e61
--- /dev/null
+++ b/engines/wintermute/base/base.cpp
@@ -0,0 +1,185 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+BaseClass::BaseClass(BaseGame *gameOwner) {
+ _gameRef = gameOwner;
+ _persistable = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseClass::BaseClass() {
+ _gameRef = NULL;
+ _persistable = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseClass::~BaseClass() {
+ _editorProps.clear();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+Common::String BaseClass::getEditorProp(const Common::String &propName, const Common::String &initVal) {
+ _editorPropsIter = _editorProps.find(propName);
+ if (_editorPropsIter != _editorProps.end()) {
+ return _editorPropsIter->_value.c_str();
+ } else {
+ return initVal;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseClass::setEditorProp(const Common::String &propName, const Common::String &propValue) {
+ if (propName.size() == 0) {
+ return STATUS_FAILED;
+ }
+
+ if (propValue.size() == 0) {
+ _editorProps.erase(propName);
+ } else {
+ _editorProps[propName] = propValue;
+ }
+ return STATUS_OK;
+}
+
+
+
+TOKEN_DEF_START
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(NAME)
+TOKEN_DEF(VALUE)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+bool BaseClass::parseEditorProperty(byte *buffer, bool complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(VALUE)
+ TOKEN_TABLE_END
+
+
+ if (!_gameRef->_editorMode) {
+ return STATUS_OK;
+ }
+
+
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ if (complete) {
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_EDITOR_PROPERTY) {
+ _gameRef->LOG(0, "'EDITOR_PROPERTY' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ }
+
+ char *propName = NULL;
+ char *propValue = NULL;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_NAME:
+ delete[] propName;
+ propName = new char[strlen((char *)params) + 1];
+ if (propName) {
+ strcpy(propName, (char *)params);
+ } else {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_VALUE:
+ delete[] propValue;
+ propValue = new char[strlen((char *)params) + 1];
+ if (propValue) {
+ strcpy(propValue, (char *)params);
+ } else {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+ }
+
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+ _gameRef->LOG(0, "Syntax error in EDITOR_PROPERTY definition");
+ return STATUS_FAILED;
+ }
+ if (cmd == PARSERR_GENERIC || propName == NULL || propValue == NULL) {
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+ _gameRef->LOG(0, "Error loading EDITOR_PROPERTY definition");
+ return STATUS_FAILED;
+ }
+
+
+ setEditorProp(propName, propValue);
+
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseClass::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ _editorPropsIter = _editorProps.begin();
+ while (_editorPropsIter != _editorProps.end()) {
+ buffer->putTextIndent(indent, "EDITOR_PROPERTY\n");
+ buffer->putTextIndent(indent, "{\n");
+ buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _editorPropsIter->_key.c_str());
+ buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _editorPropsIter->_value.c_str());
+ buffer->putTextIndent(indent, "}\n\n");
+
+ _editorPropsIter++;
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base.h b/engines/wintermute/base/base.h
new file mode 100644
index 0000000000..24820c748a
--- /dev/null
+++ b/engines/wintermute/base/base.h
@@ -0,0 +1,62 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_BASE_H
+#define WINTERMUTE_BASE_BASE_H
+
+#include "engines/wintermute/wintypes.h"
+#include "engines/wintermute/dctypes.h"
+#include "common/str.h"
+#include "common/hashmap.h"
+#include "common/hash-str.h"
+
+namespace Wintermute {
+
+class BaseGame;
+class BaseDynamicBuffer;
+
+class BaseClass {
+public:
+ bool _persistable;
+ bool setEditorProp(const Common::String &propName, const Common::String &propValue);
+ Common::String getEditorProp(const Common::String &propName, const Common::String &initVal = NULL);
+ BaseClass(TDynamicConstructor, TDynamicConstructor) {}
+ bool parseEditorProperty(byte *buffer, bool complete = true);
+ virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0);
+ BaseClass();
+ BaseClass(BaseGame *GameOwner);
+ virtual ~BaseClass();
+ BaseGame *_gameRef;
+protected:
+ Common::HashMap<Common::String, Common::String> _editorProps;
+ Common::HashMap<Common::String, Common::String>::iterator _editorPropsIter;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_active_rect.cpp b/engines/wintermute/base/base_active_rect.cpp
new file mode 100644
index 0000000000..d754cf0114
--- /dev/null
+++ b/engines/wintermute/base/base_active_rect.cpp
@@ -0,0 +1,110 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_active_rect.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/platform_osystem.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+BaseActiveRect::BaseActiveRect(BaseGame *inGame) : BaseClass(inGame) {
+ BasePlatform::setRectEmpty(&_rect);
+ _owner = NULL;
+ _frame = NULL;
+ _region = NULL;
+ _zoomX = 100;
+ _zoomY = 100;
+ _offsetX = _offsetY = 0;
+ clipRect();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseSubFrame *frame, int x, int y, int width, int height, float zoomX, float zoomY, bool precise) : BaseClass(inGame) {
+ _owner = owner;
+ _frame = frame;
+ BasePlatform::setRect(&_rect, x, y, x + width, y + height);
+ _zoomX = zoomX;
+ _zoomY = zoomY;
+ _precise = precise;
+ _region = NULL;
+ _offsetX = _offsetY = 0;
+ clipRect();
+}
+
+//////////////////////////////////////////////////////////////////////
+BaseActiveRect::BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseRegion *region, int offsetX, int offsetY) : BaseClass(inGame) {
+ _owner = owner;
+ _region = region;
+ BasePlatform::copyRect(&_rect, &region->_rect);
+ _rect.offsetRect(-offsetX, -offsetY);
+ _zoomX = 100;
+ _zoomY = 100;
+ _precise = true;
+ _frame = NULL;
+ clipRect();
+ _offsetX = offsetX;
+ _offsetY = offsetY;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseActiveRect::~BaseActiveRect() {
+ _owner = NULL;
+ _frame = NULL;
+ _region = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseActiveRect::clipRect() {
+ Rect32 rc;
+ bool customViewport;
+ _gameRef->getCurrentViewportRect(&rc, &customViewport);
+ BaseRenderer *Rend = _gameRef->_renderer;
+
+ if (!customViewport) {
+ rc.left -= Rend->_drawOffsetX;
+ rc.right -= Rend->_drawOffsetX;
+ rc.top -= Rend->_drawOffsetY;
+ rc.bottom -= Rend->_drawOffsetY;
+ }
+
+ if (rc.left > _rect.left) {
+ _offsetX = rc.left - _rect.left;
+ }
+ if (rc.top > _rect.top) {
+ _offsetY = rc.top - _rect.top;
+ }
+
+ BasePlatform::intersectRect(&_rect, &_rect, &rc);
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_active_rect.h b/engines/wintermute/base/base_active_rect.h
new file mode 100644
index 0000000000..fcd2619b03
--- /dev/null
+++ b/engines/wintermute/base/base_active_rect.h
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_ACTIVE_RECT_H
+#define WINTERMUTE_BASE_ACTIVE_RECT_H
+
+#include "engines/wintermute/math/rect32.h"
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+class BaseRegion;
+class BaseSubFrame;
+class BaseObject;
+class BaseActiveRect: BaseClass {
+public:
+ void clipRect();
+ bool _precise;
+ float _zoomX;
+ float _zoomY;
+ BaseSubFrame *_frame;
+ BaseObject *_owner;
+ BaseRegion *_region;
+ int _offsetX;
+ int _offsetY;
+ Rect32 _rect;
+ BaseActiveRect(BaseGame *inGameOwner = NULL);
+ BaseActiveRect(BaseGame *inGameOwner, BaseObject *owner, BaseSubFrame *frame, int x, int y, int width, int height, float zoomX = 100, float zoomY = 100, bool precise = true);
+ BaseActiveRect(BaseGame *inGame, BaseObject *owner, BaseRegion *region, int offsetX, int offsetY);
+ virtual ~BaseActiveRect();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_dynamic_buffer.cpp b/engines/wintermute/base/base_dynamic_buffer.cpp
new file mode 100644
index 0000000000..fc48e93c2b
--- /dev/null
+++ b/engines/wintermute/base/base_dynamic_buffer.cpp
@@ -0,0 +1,204 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseDynamicBuffer::BaseDynamicBuffer(BaseGame *inGame, uint32 initSize, uint32 growBy) {
+ _buffer = NULL;
+ _size = 0;
+ _realSize = 0;
+
+ _offset = 0;
+ _initSize = initSize;
+ _growBy = growBy;
+
+ _initialized = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseDynamicBuffer::~BaseDynamicBuffer() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::cleanup() {
+ if (_buffer) {
+ free(_buffer);
+ }
+ _buffer = NULL;
+ _size = 0;
+ _realSize = 0;
+ _offset = 0;
+ _initialized = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseDynamicBuffer::getSize() {
+ return _size;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseDynamicBuffer::init(uint32 initSize) {
+ cleanup();
+
+ if (initSize == 0) {
+ initSize = _initSize;
+ }
+
+ _buffer = (byte *)malloc(initSize);
+ if (!_buffer) {
+ BaseEngine::LOG(0, "BaseDynamicBuffer::Init - Error allocating %d bytes", initSize);
+ return STATUS_FAILED;
+ }
+
+ _realSize = initSize;
+ _initialized = true;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseDynamicBuffer::putBytes(const byte *buffer, uint32 size) {
+ if (!_initialized) {
+ init();
+ }
+
+ while (_offset + size > _realSize) {
+ _realSize += _growBy;
+ _buffer = (byte *)realloc(_buffer, _realSize);
+ if (!_buffer) {
+ BaseEngine::LOG(0, "BaseDynamicBuffer::PutBytes - Error reallocating buffer to %d bytes", _realSize);
+ return STATUS_FAILED;
+ }
+ }
+
+ memcpy(_buffer + _offset, buffer, size);
+ _offset += size;
+ _size += size;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseDynamicBuffer::getBytes(byte *buffer, uint32 size) {
+ if (!_initialized) {
+ init();
+ }
+
+ if (_offset + size > _size) {
+ BaseEngine::LOG(0, "BaseDynamicBuffer::GetBytes - Buffer underflow");
+ return STATUS_FAILED;
+ }
+
+ memcpy(buffer, _buffer + _offset, size);
+ _offset += size;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::putDWORD(uint32 val) {
+ putBytes((byte *)&val, sizeof(uint32));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseDynamicBuffer::getDWORD() {
+ uint32 ret;
+ getBytes((byte *)&ret, sizeof(uint32));
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::putString(const char *val) {
+ if (!val) {
+ putString("(null)");
+ } else {
+ putDWORD(strlen(val) + 1);
+ putBytes((const byte *)val, strlen(val) + 1);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *BaseDynamicBuffer::getString() {
+ uint32 len = getDWORD();
+ char *ret = (char *)(_buffer + _offset);
+ _offset += len;
+
+ if (!strcmp(ret, "(null)")) {
+ return NULL;
+ } else {
+ return ret;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::putText(const char *fmt, ...) {
+ va_list va;
+
+ va_start(va, fmt);
+ putTextForm(fmt, va);
+ va_end(va);
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::putTextIndent(int indent, const char *fmt, ...) {
+ va_list va;
+
+ putText("%*s", indent, "");
+
+ va_start(va, fmt);
+ putTextForm(fmt, va);
+ va_end(va);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseDynamicBuffer::putTextForm(const char *format, va_list argptr) {
+ char buff[32768];
+ vsprintf(buff, format, argptr);
+ putBytes((byte *)buff, strlen(buff));
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_dynamic_buffer.h b/engines/wintermute/base/base_dynamic_buffer.h
new file mode 100644
index 0000000000..b6f3e12b9c
--- /dev/null
+++ b/engines/wintermute/base/base_dynamic_buffer.h
@@ -0,0 +1,66 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_DYNAMIC_BUFFER_H
+#define WINTERMUTE_BASE_DYNAMIC_BUFFER_H
+
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseDynamicBuffer {
+public:
+ bool _initialized;
+ void putText(const char *fmt, ...);
+ void putTextIndent(int indent, const char *fmt, ...);
+ uint32 getDWORD();
+ void putDWORD(uint32 val);
+ char *getString();
+ void putString(const char *val);
+ bool getBytes(byte *buffer, uint32 size);
+ bool putBytes(const byte *buffer, uint32 size);
+ uint32 getSize();
+ bool init(uint32 initSize = 0);
+ void cleanup();
+ uint32 _size;
+ byte *_buffer;
+ BaseDynamicBuffer(BaseGame *inGame, uint32 initSize = 1000, uint32 growBy = 1000);
+ virtual ~BaseDynamicBuffer();
+
+private:
+ uint32 _realSize;
+ uint32 _growBy;
+ uint32 _initSize;
+ uint32 _offset;
+ void putTextForm(const char *format, va_list argptr);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_engine.cpp b/engines/wintermute/base/base_engine.cpp
new file mode 100644
index 0000000000..2368f8b106
--- /dev/null
+++ b/engines/wintermute/base/base_engine.cpp
@@ -0,0 +1,93 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/wintermute.h"
+#include "engines/wintermute/system/sys_class_registry.h"
+#include "common/system.h"
+namespace Common {
+DECLARE_SINGLETON(Wintermute::BaseEngine);
+}
+
+namespace Wintermute {
+
+BaseEngine::BaseEngine() {
+ _fileManager = NULL;
+ _gameRef = NULL;
+ _classReg = NULL;
+ _rnd = NULL;
+ _gameId = "";
+}
+
+void BaseEngine::init(Common::Language lang) {
+ _fileManager = new BaseFileManager(lang);
+ // Don't forget to register your random source
+ _rnd = new Common::RandomSource("Wintermute");
+ _classReg = new SystemClassRegistry();
+ _classReg->registerClasses();
+}
+
+BaseEngine::~BaseEngine() {
+ delete _fileManager;
+ delete _rnd;
+ delete _classReg;
+}
+
+void BaseEngine::createInstance(const Common::String &gameid, Common::Language lang) {
+ instance()._gameId = gameid;
+ instance().init(lang);
+}
+
+void BaseEngine::LOG(bool res, const char *fmt, ...) {
+ uint32 secs = g_system->getMillis() / 1000;
+ uint32 hours = secs / 3600;
+ secs = secs % 3600;
+ uint32 mins = secs / 60;
+ secs = secs % 60;
+
+ char buff[512];
+ va_list va;
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ if (instance()._gameRef) {
+ instance()._gameRef->LOG("%s", buff);
+ } else {
+ debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);
+ }
+}
+
+uint32 BaseEngine::randInt(int from, int to) {
+ return _rnd->getRandomNumberRng(from, to);
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_engine.h b/engines/wintermute/base/base_engine.h
new file mode 100644
index 0000000000..1cef7b33ba
--- /dev/null
+++ b/engines/wintermute/base/base_engine.h
@@ -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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_ENGINE_H
+#define WINTERMUTE_BASE_ENGINE_H
+
+#include "common/str.h"
+#include "common/singleton.h"
+#include "common/random.h"
+#include "common/language.h"
+
+namespace Wintermute {
+
+class BaseFileManager;
+class BaseRegistry;
+class BaseGame;
+class SystemClassRegistry;
+class BaseEngine : public Common::Singleton<Wintermute::BaseEngine> {
+ void init(Common::Language lang);
+ BaseFileManager *_fileManager;
+ Common::String _gameId;
+ BaseGame *_gameRef;
+ // We need random numbers
+ Common::RandomSource *_rnd;
+ SystemClassRegistry *_classReg;
+public:
+ BaseEngine();
+ ~BaseEngine();
+ static void createInstance(const Common::String &gameid, Common::Language lang);
+ void setGameRef(BaseGame *gameRef) { _gameRef = gameRef; }
+
+ Common::RandomSource *getRandomSource() { return _rnd; }
+ uint32 randInt(int from, int to);
+
+ SystemClassRegistry *getClassRegistry(){ return _classReg; }
+ BaseGame *getGameRef() { return _gameRef; }
+ BaseFileManager *getFileManager() { return _fileManager; }
+ static void LOG(bool res, const char *fmt, ...);
+ const char *getGameId() { return _gameId.c_str(); }
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_fader.cpp b/engines/wintermute/base/base_fader.cpp
new file mode 100644
index 0000000000..08e6f689ba
--- /dev/null
+++ b/engines/wintermute/base/base_fader.cpp
@@ -0,0 +1,194 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_fader.h"
+#include "engines/wintermute/base/base_game.h"
+#include "common/util.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(BaseFader, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseFader::BaseFader(BaseGame *inGame) : BaseObject(inGame) {
+ _active = false;
+ _red = _green = _blue = 0;
+ _currentAlpha = 0x00;
+ _sourceAlpha = 0;
+ _targetAlpha = 0;
+ _duration = 1000;
+ _startTime = 0;
+ _system = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseFader::~BaseFader() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::update() {
+ if (!_active) {
+ return STATUS_OK;
+ }
+
+ int alphaDelta = _targetAlpha - _sourceAlpha;
+
+ uint32 time;
+
+ if (_system) {
+ time = g_system->getMillis() - _startTime;
+ } else {
+ time = _gameRef->_timer - _startTime;
+ }
+
+ if (time >= _duration) {
+ _currentAlpha = _targetAlpha;
+ } else {
+ _currentAlpha = (byte)(_sourceAlpha + (float)time / (float)_duration * alphaDelta);
+ }
+ _currentAlpha = MIN((unsigned char)255, MAX(_currentAlpha, (byte)0)); // TODO: clean
+
+ _ready = time >= _duration;
+ if (_ready && _currentAlpha == 0x00) {
+ _active = false;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::display() {
+ if (!_active) {
+ return STATUS_OK;
+ }
+
+ if (_currentAlpha > 0x00) {
+ _gameRef->_renderer->fadeToColor(_red, _green, _blue, _currentAlpha);
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::deactivate() {
+ _active = false;
+ _ready = true;
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::fadeIn(uint32 sourceColor, uint32 duration, bool system) {
+ _ready = false;
+ _active = true;
+
+ _red = RGBCOLGetR(sourceColor);
+ _green = RGBCOLGetG(sourceColor);
+ _blue = RGBCOLGetB(sourceColor);
+
+ _sourceAlpha = RGBCOLGetA(sourceColor);
+ _targetAlpha = 0;
+
+ _duration = duration;
+ _system = system;
+
+ if (_system) {
+ _startTime = g_system->getMillis();
+ } else {
+ _startTime = _gameRef->_timer;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::fadeOut(uint32 targetColor, uint32 duration, bool system) {
+ _ready = false;
+ _active = true;
+
+ _red = RGBCOLGetR(targetColor);
+ _green = RGBCOLGetG(targetColor);
+ _blue = RGBCOLGetB(targetColor);
+
+ //_sourceAlpha = 0;
+ _sourceAlpha = _currentAlpha;
+ _targetAlpha = RGBCOLGetA(targetColor);
+
+ _duration = duration;
+ _system = system;
+
+ if (_system) {
+ _startTime = g_system->getMillis();
+ } else {
+ _startTime = _gameRef->_timer;
+ }
+
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseFader::getCurrentColor() {
+ return BYTETORGBA(_red, _green, _blue, _currentAlpha);
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFader::persist(BasePersistenceManager *persistMgr) {
+ BaseObject::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_active));
+ persistMgr->transfer(TMEMBER(_blue));
+ persistMgr->transfer(TMEMBER(_currentAlpha));
+ persistMgr->transfer(TMEMBER(_duration));
+ persistMgr->transfer(TMEMBER(_green));
+ persistMgr->transfer(TMEMBER(_red));
+ persistMgr->transfer(TMEMBER(_sourceAlpha));
+ persistMgr->transfer(TMEMBER(_startTime));
+ persistMgr->transfer(TMEMBER(_targetAlpha));
+ persistMgr->transfer(TMEMBER(_system));
+
+ if (_system && !persistMgr->getIsSaving()) {
+ _startTime = 0;
+ }
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_fader.h b/engines/wintermute/base/base_fader.h
new file mode 100644
index 0000000000..d3ced4aacc
--- /dev/null
+++ b/engines/wintermute/base/base_fader.h
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FADER_H
+#define WINTERMUTE_BASE_FADER_H
+
+
+#include "engines/wintermute/base/base_object.h"
+
+namespace Wintermute {
+
+class BaseFader : public BaseObject {
+public:
+ bool _system;
+ uint32 getCurrentColor();
+ bool fadeOut(uint32 targetColor, uint32 duration, bool system = false);
+ bool fadeIn(uint32 sourceColor, uint32 duration, bool system = false);
+ bool deactivate();
+ bool display();
+ bool update();
+ DECLARE_PERSISTENT(BaseFader, BaseObject)
+ BaseFader(BaseGame *inGame);
+ virtual ~BaseFader();
+private:
+ bool _active;
+ byte _red;
+ byte _green;
+ byte _blue;
+ byte _currentAlpha;
+ byte _targetAlpha;
+ byte _sourceAlpha;
+ uint32 _duration;
+ uint32 _startTime;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_file_manager.cpp b/engines/wintermute/base/base_file_manager.cpp
new file mode 100644
index 0000000000..b726c0c66f
--- /dev/null
+++ b/engines/wintermute/base/base_file_manager.cpp
@@ -0,0 +1,340 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+#include "engines/wintermute/base/file/base_disk_file.h"
+#include "engines/wintermute/base/file/base_save_thumb_file.h"
+#include "engines/wintermute/base/file/base_package.h"
+#include "engines/wintermute/base/file/base_resources.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/wintermute.h"
+#include "common/debug.h"
+#include "common/str.h"
+#include "common/tokenizer.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+#include "common/config-manager.h"
+#include "common/system.h"
+#include "common/fs.h"
+#include "common/file.h"
+#include "common/savefile.h"
+#include "common/fs.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+//////////////////////////////////////////////////////////////////////
+BaseFileManager::BaseFileManager(Common::Language lang) {
+ _language = lang;
+ initPaths();
+ registerPackages();
+}
+
+//////////////////////////////////////////////////////////////////////
+BaseFileManager::~BaseFileManager() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::cleanup() {
+ // delete registered paths
+ _packagePaths.clear();
+
+ // close open files
+ for (uint32 i = 0; i < _openFiles.size(); i++) {
+ delete _openFiles[i];
+ }
+ _openFiles.clear();
+
+ // delete packages
+ _packages.clear();
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////
+byte *BaseFileManager::readWholeFile(const Common::String &filename, uint32 *size, bool mustExist) {
+ byte *buffer = NULL;
+
+ Common::SeekableReadStream *file = openFile(filename);
+ if (!file) {
+ if (mustExist) {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error opening file '%s'", filename.c_str());
+ }
+ return NULL;
+ }
+
+ buffer = new byte[file->size() + 1];
+ if (buffer == NULL) {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error allocating buffer for file '%s' (%d bytes)", filename.c_str(), file->size() + 1);
+ closeFile(file);
+ return NULL;
+ }
+
+ if (file->read(buffer, (uint32)file->size()) != (uint32)file->size()) {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Error reading file '%s'", filename.c_str());
+ closeFile(file);
+ delete[] buffer;
+ return NULL;
+ };
+
+ buffer[file->size()] = '\0';
+ if (size != NULL) {
+ *size = file->size();
+ }
+ closeFile(file);
+
+ return buffer;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::addPath(TPathType type, const Common::FSNode &path) {
+ if (!path.exists()) {
+ return STATUS_FAILED;
+ }
+
+ switch (type) {
+ case PATH_SINGLE:
+ // _singlePaths.push_back(path);
+ error("TODO: Allow adding single-paths");
+ break;
+ case PATH_PACKAGE:
+ _packagePaths.push_back(path);
+ break;
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::reloadPaths() {
+ // delete registered paths
+ //_singlePaths.clear();
+ _packagePaths.clear();
+
+ return initPaths();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::initPaths() {
+ // Removed: Config-based file-path choice.
+
+ // package files paths
+ const Common::FSNode gameData(ConfMan.get("path"));
+ addPath(PATH_PACKAGE, gameData);
+
+ Common::FSNode dataSubFolder = gameData.getChild("data");
+ if (dataSubFolder.exists()) {
+ addPath(PATH_PACKAGE, dataSubFolder);
+ }
+ Common::FSNode languageSubFolder = gameData.getChild("language");
+ if (languageSubFolder.exists()) {
+ addPath(PATH_PACKAGE, languageSubFolder);
+ }
+ return STATUS_OK;
+}
+
+bool BaseFileManager::registerPackages(const Common::FSList &fslist) {
+ for (Common::FSList::const_iterator it = fslist.begin(); it != fslist.end(); ++it) {
+ debugC(kWintermuteDebugFileAccess, "Adding %s", (*it).getName().c_str());
+ if ((*it).getName().contains(".dcp")) {
+ if (registerPackage((*it))) {
+ addPath(PATH_PACKAGE, (*it));
+ }
+ }
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::registerPackages() {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, "Scanning packages");
+
+ // Register without using SearchMan, as otherwise the FSNode-based lookup in openPackage will fail
+ // and that has to be like that to support the detection-scheme.
+ Common::FSList files;
+ for (Common::FSList::iterator it = _packagePaths.begin(); it != _packagePaths.end(); ++it) {
+ debugC(kWintermuteDebugFileAccess, "Should register folder: %s %s", (*it).getPath().c_str(), (*it).getName().c_str());
+ (*it).getChildren(files, Common::FSNode::kListFilesOnly);
+ for (Common::FSList::iterator fileIt = files.begin(); fileIt != files.end(); ++fileIt) {
+ if (!fileIt->getName().hasSuffix(".dcp")) {
+ continue;
+ }
+ // Avoid registering all the language files
+ // TODO: Select based on the gameDesc.
+ if (_language != Common::UNK_LANG && fileIt->getParent().getName() == "language") {
+ Common::String parentName = fileIt->getParent().getName();
+ Common::String dcpName = fileIt->getName();
+ if (_language == Common::EN_ANY && fileIt->getName() != "english.dcp") {
+ continue;
+ } else if (_language == Common::CZ_CZE && fileIt->getName() != "czech.dcp") {
+ continue;
+ } else if (_language == Common::IT_ITA && fileIt->getName() != "italian.dcp") {
+ continue;
+ } else if (_language == Common::PL_POL && fileIt->getName() != "polish.dcp") {
+ continue;
+ } else if (_language == Common::RU_RUS && fileIt->getName() != "russian.dcp") {
+ continue;
+ }
+ }
+ debugC(kWintermuteDebugFileAccess, "Registering %s %s", (*fileIt).getPath().c_str(), (*fileIt).getName().c_str());
+ registerPackage((*fileIt));
+ }
+ }
+
+// debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Registered %d files in %d package(s)", _files.size(), _packages.size());
+
+ return STATUS_OK;
+}
+
+bool BaseFileManager::registerPackage(Common::FSNode file, const Common::String &filename, bool searchSignature) {
+ PackageSet *pack = new PackageSet(file, filename, searchSignature);
+ _packages.add(file.getName(), pack, pack->getPriority() , true);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+Common::SeekableReadStream *BaseFileManager::openPkgFile(const Common::String &filename) {
+ Common::String upcName = filename;
+ upcName.toUppercase();
+ Common::SeekableReadStream *file = NULL;
+ char fileName[MAX_PATH_LENGTH];
+ strcpy(fileName, upcName.c_str());
+
+ // correct slashes
+ for (uint32 i = 0; i < upcName.size(); i++) {
+ if (upcName[(int32)i] == '/') {
+ upcName.setChar('\\', (uint32)i);
+ }
+ }
+ Common::ArchiveMemberPtr entry = _packages.getMember(upcName);
+ if (!entry) {
+ return NULL;
+ }
+ file = entry->createReadStream();
+ return file;
+}
+
+bool BaseFileManager::hasFile(const Common::String &filename) {
+ if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) {
+ BasePersistenceManager pm(BaseEngine::instance().getGameId());
+ if (filename.size() <= 9) {
+ return false;
+ }
+ int slot = atoi(filename.c_str() + 9);
+ return pm.getSaveExists(slot);
+ }
+ if (diskFileExists(filename)) {
+ return true;
+ }
+ if (_packages.hasFile(filename)) {
+ return true; // We don't bother checking if the file can actually be opened, something bigger is wrong if that is the case.
+ }
+ if (BaseResources::hasFile(filename)) {
+ return true;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+Common::SeekableReadStream *BaseFileManager::openFile(const Common::String &filename, bool absPathWarning, bool keepTrackOf) {
+ if (strcmp(filename.c_str(), "") == 0) {
+ return NULL;
+ }
+ debugC(kWintermuteDebugFileAccess, "Open file %s", filename.c_str());
+
+ Common::SeekableReadStream *file = openFileRaw(filename);
+ if (file && keepTrackOf) {
+ _openFiles.push_back(file);
+ }
+ return file;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFileManager::closeFile(Common::SeekableReadStream *File) {
+ for (uint32 i = 0; i < _openFiles.size(); i++) {
+ if (_openFiles[i] == File) {
+ delete _openFiles[i];
+ _openFiles.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+Common::SeekableReadStream *BaseFileManager::openFileRaw(const Common::String &filename) {
+ Common::SeekableReadStream *ret = NULL;
+
+ if (scumm_strnicmp(filename.c_str(), "savegame:", 9) == 0) {
+ if (!BaseEngine::instance().getGameRef()) {
+ error("Attempt to load filename: %s without BaseEngine-object, this is unsupported", filename.c_str());
+ }
+ BaseSaveThumbFile *saveThumbFile = new BaseSaveThumbFile();
+ if (DID_SUCCEED(saveThumbFile->open(filename))) {
+ ret = saveThumbFile->getMemStream();
+ }
+ delete saveThumbFile;
+ return ret;
+ }
+
+ ret = openDiskFile(filename);
+ if (ret) {
+ return ret;
+ }
+
+ ret = openPkgFile(filename);
+ if (ret) {
+ return ret;
+ }
+
+ ret = BaseResources::getFile(filename);
+ if (ret) {
+ return ret;
+ }
+
+ debugC(kWintermuteDebugFileAccess ,"BFileManager::OpenFileRaw - Failed to open %s", filename.c_str());
+ return NULL;
+}
+
+BaseFileManager *BaseFileManager::getEngineInstance() {
+ if (BaseEngine::instance().getFileManager()) {
+ return BaseEngine::instance().getFileManager();
+ }
+ return NULL;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_file_manager.h b/engines/wintermute/base/base_file_manager.h
new file mode 100644
index 0000000000..70aff49bbb
--- /dev/null
+++ b/engines/wintermute/base/base_file_manager.h
@@ -0,0 +1,76 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FILE_MANAGER_H
+#define WINTERMUTE_BASE_FILE_MANAGER_H
+
+#include "common/archive.h"
+#include "common/str.h"
+#include "common/fs.h"
+#include "common/file.h"
+#include "common/language.h"
+
+namespace Wintermute {
+class BaseFileManager {
+public:
+ bool cleanup();
+
+ bool closeFile(Common::SeekableReadStream *File);
+ bool hasFile(const Common::String &filename);
+ Common::SeekableReadStream *openFile(const Common::String &filename, bool absPathWarning = true, bool keepTrackOf = true);
+ byte *readWholeFile(const Common::String &filename, uint32 *size = NULL, bool mustExist = true);
+
+ BaseFileManager(Common::Language lang);
+ virtual ~BaseFileManager();
+ // Used only for detection
+ bool registerPackages(const Common::FSList &fslist);
+ static BaseFileManager *getEngineInstance();
+private:
+ typedef enum {
+ PATH_PACKAGE,
+ PATH_SINGLE
+ } TPathType;
+ bool reloadPaths();
+ bool initPaths();
+ bool addPath(TPathType type, const Common::FSNode &path);
+ bool registerPackages();
+ Common::SeekableReadStream *openFileRaw(const Common::String &filename);
+ Common::SeekableReadStream *openPkgFile(const Common::String &filename);
+ Common::FSList _packagePaths;
+ bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset);
+ bool registerPackage(Common::FSNode package, const Common::String &filename = "", bool searchSignature = false);
+ Common::SearchSet _packages;
+ Common::Array<Common::SeekableReadStream *> _openFiles;
+ Common::Language _language;
+ // This class is intentionally not a subclass of Base, as it needs to be used by
+ // the detector too, without launching the entire engine:
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_frame.cpp b/engines/wintermute/base/base_frame.cpp
new file mode 100644
index 0000000000..e1b29a3a5c
--- /dev/null
+++ b/engines/wintermute/base/base_frame.cpp
@@ -0,0 +1,760 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_frame.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseFrame, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseFrame::BaseFrame(BaseGame *inGame) : BaseScriptable(inGame, true) {
+ _delay = 0;
+ _moveX = _moveY = 0;
+
+ _sound = NULL;
+ _killSound = false;
+
+ _editorExpanded = false;
+ _keyframe = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseFrame::~BaseFrame() {
+ delete _sound;
+ _sound = NULL;
+
+ for (uint32 i = 0; i < _subframes.size(); i++) {
+ delete _subframes[i];
+ }
+ _subframes.clear();
+
+ for (uint32 i = 0; i < _applyEvent.size(); i++) {
+ delete[] _applyEvent[i];
+ _applyEvent[i] = NULL;
+ }
+ _applyEvent.clear();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, bool allFrames, float rotate, TSpriteBlendMode blendMode) {
+ bool res;
+
+ for (uint32 i = 0; i < _subframes.size(); i++) {
+ res = _subframes[i]->draw(x, y, registerOwner, zoomX, zoomY, precise, alpha, rotate, blendMode);
+ if (DID_FAIL(res)) {
+ return res;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::oneTimeDisplay(BaseObject *owner, bool muted) {
+ if (_sound && !muted) {
+ if (owner) {
+ owner->updateOneSound(_sound);
+ }
+ _sound->play();
+ /*
+ if (_gameRef->_state == GAME_FROZEN) {
+ _sound->Pause(true);
+ }
+ */
+ }
+ if (owner) {
+ for (uint32 i = 0; i < _applyEvent.size(); i++) {
+ owner->applyEvent(_applyEvent[i]);
+ }
+ }
+ return STATUS_OK;
+}
+
+
+
+TOKEN_DEF_START
+TOKEN_DEF(DELAY)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(TRANSPARENT)
+TOKEN_DEF(RECT)
+TOKEN_DEF(HOTSPOT)
+TOKEN_DEF(2D_ONLY)
+TOKEN_DEF(3D_ONLY)
+TOKEN_DEF(MIRROR_X)
+TOKEN_DEF(MIRROR_Y)
+TOKEN_DEF(MOVE)
+TOKEN_DEF(ALPHA_COLOR)
+TOKEN_DEF(ALPHA)
+TOKEN_DEF(SUBFRAME)
+TOKEN_DEF(SOUND)
+TOKEN_DEF(KEYFRAME)
+TOKEN_DEF(DECORATION)
+TOKEN_DEF(APPLY_EVENT)
+TOKEN_DEF(EDITOR_SELECTED)
+TOKEN_DEF(EDITOR_EXPANDED)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(KILL_SOUND)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////
+bool BaseFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(DELAY)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(TRANSPARENT)
+ TOKEN_TABLE(RECT)
+ TOKEN_TABLE(HOTSPOT)
+ TOKEN_TABLE(2D_ONLY)
+ TOKEN_TABLE(3D_ONLY)
+ TOKEN_TABLE(MIRROR_X)
+ TOKEN_TABLE(MIRROR_Y)
+ TOKEN_TABLE(MOVE)
+ TOKEN_TABLE(ALPHA_COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE(SUBFRAME)
+ TOKEN_TABLE(SOUND)
+ TOKEN_TABLE(KEYFRAME)
+ TOKEN_TABLE(DECORATION)
+ TOKEN_TABLE(APPLY_EVENT)
+ TOKEN_TABLE(EDITOR_SELECTED)
+ TOKEN_TABLE(EDITOR_EXPANDED)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(KILL_SOUND)
+ TOKEN_TABLE_END
+
+ char *params;
+ int cmd;
+ BaseParser parser;
+ Rect32 rect;
+ int r = 255, g = 255, b = 255;
+ int ar = 255, ag = 255, ab = 255, alpha = 255;
+ int hotspotX = 0, hotspotY = 0;
+ bool custoTrans = false;
+ bool editorSelected = false;
+ bool is2DOnly = false;
+ bool is3DOnly = false;
+ bool decoration = false;
+ bool mirrorX = false;
+ bool mirrorY = false;
+ BasePlatform::setRectEmpty(&rect);
+ char *surface_file = NULL;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, &params)) > 0) {
+ switch (cmd) {
+ case TOKEN_DELAY:
+ parser.scanStr(params, "%d", &_delay);
+ break;
+
+ case TOKEN_IMAGE:
+ surface_file = params;
+ break;
+
+ case TOKEN_TRANSPARENT:
+ parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
+ custoTrans = true;
+ break;
+
+ case TOKEN_RECT:
+ parser.scanStr(params, "%d,%d,%d,%d", &rect.left, &rect.top, &rect.right, &rect.bottom);
+ break;
+
+ case TOKEN_HOTSPOT:
+ parser.scanStr(params, "%d,%d", &hotspotX, &hotspotY);
+ break;
+
+ case TOKEN_MOVE:
+ parser.scanStr(params, "%d,%d", &_moveX, &_moveY);
+ break;
+
+ case TOKEN_2D_ONLY:
+ parser.scanStr(params, "%b", &is2DOnly);
+ break;
+
+ case TOKEN_3D_ONLY:
+ parser.scanStr(params, "%b", &is3DOnly);
+ break;
+
+ case TOKEN_MIRROR_X:
+ parser.scanStr(params, "%b", &mirrorX);
+ break;
+
+ case TOKEN_MIRROR_Y:
+ parser.scanStr(params, "%b", &mirrorY);
+ break;
+
+ case TOKEN_ALPHA_COLOR:
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
+ break;
+
+ case TOKEN_ALPHA:
+ parser.scanStr(params, "%d", &alpha);
+ break;
+
+ case TOKEN_EDITOR_SELECTED:
+ parser.scanStr(params, "%b", &editorSelected);
+ break;
+
+ case TOKEN_EDITOR_EXPANDED:
+ parser.scanStr(params, "%b", &_editorExpanded);
+ break;
+
+ case TOKEN_KILL_SOUND:
+ parser.scanStr(params, "%b", &_killSound);
+ break;
+
+ case TOKEN_SUBFRAME: {
+ BaseSubFrame *subframe = new BaseSubFrame(_gameRef);
+ if (!subframe || DID_FAIL(subframe->loadBuffer((byte *)params, lifeTime, keepLoaded))) {
+ delete subframe;
+ cmd = PARSERR_GENERIC;
+ } else {
+ _subframes.add(subframe);
+ }
+ }
+ break;
+
+ case TOKEN_SOUND: {
+ if (_sound) {
+ delete _sound;
+ _sound = NULL;
+ }
+ _sound = new BaseSound(_gameRef);
+ if (!_sound || DID_FAIL(_sound->setSound(params, Audio::Mixer::kSFXSoundType, false))) {
+ if (_gameRef->_soundMgr->_soundAvailable) {
+ _gameRef->LOG(0, "Error loading sound '%s'.", params);
+ }
+ delete _sound;
+ _sound = NULL;
+ }
+ }
+ break;
+
+ case TOKEN_APPLY_EVENT: {
+ char *event = new char[strlen(params) + 1];
+ strcpy(event, params);
+ _applyEvent.add(event);
+ }
+ break;
+
+ case TOKEN_KEYFRAME:
+ parser.scanStr(params, "%b", &_keyframe);
+ break;
+
+ case TOKEN_DECORATION:
+ parser.scanStr(params, "%b", &decoration);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ parseEditorProperty((byte *)params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in FRAME definition");
+ return STATUS_FAILED;
+ }
+
+ if (cmd == PARSERR_GENERIC) {
+ _gameRef->LOG(0, "Error loading FRAME definition");
+ return STATUS_FAILED;
+ }
+
+
+ BaseSubFrame *sub = new BaseSubFrame(_gameRef);
+ if (surface_file != NULL) {
+ if (custoTrans) {
+ sub->setSurface(surface_file, false, r, g, b, lifeTime, keepLoaded);
+ } else {
+ sub->setSurface(surface_file, true, 0, 0, 0, lifeTime, keepLoaded);
+ }
+
+ if (!sub->_surface) {
+ delete sub;
+ _gameRef->LOG(0, "Error loading SUBFRAME");
+ return STATUS_FAILED;
+ }
+
+ sub->_alpha = BYTETORGBA(ar, ag, ab, alpha);
+ if (custoTrans) {
+ sub->_transparent = BYTETORGBA(r, g, b, 0xFF);
+ }
+ }
+
+ if (BasePlatform::isRectEmpty(&rect)) {
+ sub->setDefaultRect();
+ } else {
+ sub->setRect(rect);
+ }
+
+ sub->_hotspotX = hotspotX;
+ sub->_hotspotY = hotspotY;
+ sub->_2DOnly = is2DOnly;
+ sub->_3DOnly = is3DOnly;
+ sub->_decoration = decoration;
+ sub->_mirrorX = mirrorX;
+ sub->_mirrorY = mirrorY;
+
+
+ sub->_editorSelected = editorSelected;
+ _subframes.insert_at(0, sub);
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) {
+ if (!rect) {
+ return false;
+ }
+ BasePlatform::setRectEmpty(rect);
+
+ Rect32 subRect;
+
+ for (uint32 i = 0; i < _subframes.size(); i++) {
+ _subframes[i]->getBoundingRect(&subRect, x, y, scaleX, scaleY);
+ BasePlatform::unionRect(rect, rect, &subRect);
+ }
+ return true;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ buffer->putTextIndent(indent, "FRAME {\n");
+ buffer->putTextIndent(indent + 2, "DELAY = %d\n", _delay);
+
+ if (_moveX != 0 || _moveY != 0) {
+ buffer->putTextIndent(indent + 2, "MOVE {%d, %d}\n", _moveX, _moveY);
+ }
+
+ if (_sound && _sound->getFilename()) {
+ buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sound->getFilename());
+ }
+
+ buffer->putTextIndent(indent + 2, "KEYFRAME=%s\n", _keyframe ? "TRUE" : "FALSE");
+
+ if (_killSound) {
+ buffer->putTextIndent(indent + 2, "KILL_SOUND=%s\n", _killSound ? "TRUE" : "FALSE");
+ }
+
+ if (_editorExpanded) {
+ buffer->putTextIndent(indent + 2, "EDITOR_EXPANDED=%s\n", _editorExpanded ? "TRUE" : "FALSE");
+ }
+
+ if (_subframes.size() > 0) {
+ _subframes[0]->saveAsText(buffer, indent, false);
+ }
+
+ for (uint32 i = 1; i < _subframes.size(); i++) {
+ _subframes[i]->saveAsText(buffer, indent + 2);
+ }
+
+ for (uint32 i = 0; i < _applyEvent.size(); i++) {
+ buffer->putTextIndent(indent + 2, "APPLY_EVENT=\"%s\"\n", _applyEvent[i]);
+ }
+
+ BaseClass::saveAsText(buffer, indent + 2);
+
+
+ buffer->putTextIndent(indent, "}\n\n");
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::persist(BasePersistenceManager *persistMgr) {
+ BaseScriptable::persist(persistMgr);
+
+ _applyEvent.persist(persistMgr);
+ persistMgr->transfer(TMEMBER(_delay));
+ persistMgr->transfer(TMEMBER(_editorExpanded));
+ persistMgr->transfer(TMEMBER(_keyframe));
+ persistMgr->transfer(TMEMBER(_killSound));
+ persistMgr->transfer(TMEMBER(_moveX));
+ persistMgr->transfer(TMEMBER(_moveY));
+ persistMgr->transfer(TMEMBER(_sound));
+ _subframes.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSound
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "GetSound") == 0) {
+ stack->correctParams(0);
+
+ if (_sound && _sound->getFilename()) {
+ stack->pushString(_sound->getFilename());
+ } else {
+ stack->pushNULL();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetSound
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SetSound") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ delete _sound;
+ _sound = NULL;
+
+ if (!val->isNULL()) {
+ _sound = new BaseSound(_gameRef);
+ if (!_sound || DID_FAIL(_sound->setSound(val->getString(), Audio::Mixer::kSFXSoundType, false))) {
+ stack->pushBool(false);
+ delete _sound;
+ _sound = NULL;
+ } else {
+ stack->pushBool(true);
+ }
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSubframe
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "GetSubframe") == 0) {
+ stack->correctParams(1);
+ int index = stack->pop()->getInt(-1);
+ if (index < 0 || index >= (int32)_subframes.size()) {
+ script->runtimeError("Frame.GetSubframe: Subframe index %d is out of range.", index);
+ stack->pushNULL();
+ } else {
+ stack->pushNative(_subframes[index], true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteSubframe
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeleteSubframe") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ if (val->isInt()) {
+ int index = val->getInt(-1);
+ if (index < 0 || index >= (int32)_subframes.size()) {
+ script->runtimeError("Frame.DeleteSubframe: Subframe index %d is out of range.", index);
+ }
+ } else {
+ BaseSubFrame *sub = (BaseSubFrame *)val->getNative();
+ for (uint32 i = 0; i < _subframes.size(); i++) {
+ if (_subframes[i] == sub) {
+ delete _subframes[i];
+ _subframes.remove_at(i);
+ break;
+ }
+ }
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddSubframe
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddSubframe") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ const char *filename = NULL;
+ if (!val->isNULL()) {
+ filename = val->getString();
+ }
+
+ BaseSubFrame *sub = new BaseSubFrame(_gameRef);
+ if (filename != NULL) {
+ sub->setSurface(filename);
+ sub->setDefaultRect();
+ }
+ _subframes.add(sub);
+
+ stack->pushNative(sub, true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InsertSubframe
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "InsertSubframe") == 0) {
+ stack->correctParams(2);
+ int index = stack->pop()->getInt();
+ if (index < 0) {
+ index = 0;
+ }
+
+ ScValue *val = stack->pop();
+ const char *filename = NULL;
+ if (!val->isNULL()) {
+ filename = val->getString();
+ }
+
+ BaseSubFrame *sub = new BaseSubFrame(_gameRef);
+ if (filename != NULL) {
+ sub->setSurface(filename);
+ }
+
+ if (index >= (int32)_subframes.size()) {
+ _subframes.add(sub);
+ } else {
+ _subframes.insert_at(index, sub);
+ }
+
+ stack->pushNative(sub, true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSubframe") == 0) {
+ stack->correctParams(1);
+ int index = stack->pop()->getInt(-1);
+ if (index < 0 || index >= (int32)_applyEvent.size()) {
+ script->runtimeError("Frame.GetEvent: Event index %d is out of range.", index);
+ stack->pushNULL();
+ } else {
+ stack->pushString(_applyEvent[index]);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddEvent") == 0) {
+ stack->correctParams(1);
+ const char *event = stack->pop()->getString();
+ for (uint32 i = 0; i < _applyEvent.size(); i++) {
+ if (scumm_stricmp(_applyEvent[i], event) == 0) {
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ }
+ _applyEvent.add(event);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeleteEvent") == 0) {
+ stack->correctParams(1);
+ const char *event = stack->pop()->getString();
+ for (uint32 i = 0; i < _applyEvent.size(); i++) {
+ if (scumm_stricmp(_applyEvent[i], event) == 0) {
+ delete[] _applyEvent[i];
+ _applyEvent.remove_at(i);
+ break;
+ }
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ else {
+ if (_subframes.size() == 1) {
+ return _subframes[0]->scCallMethod(script, stack, thisStack, name);
+ } else {
+ return BaseScriptable::scCallMethod(script, stack, thisStack, name);
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseFrame::scGetProperty(const char *name) {
+ if (!_scValue) {
+ _scValue = new ScValue(_gameRef);
+ }
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("frame");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Delay
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Delay") == 0) {
+ _scValue->setInt(_delay);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Keyframe
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Keyframe") == 0) {
+ _scValue->setBool(_keyframe);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // KillSounds
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "KillSounds") == 0) {
+ _scValue->setBool(_killSound);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MoveX") == 0) {
+ _scValue->setInt(_moveX);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MoveY") == 0) {
+ _scValue->setInt(_moveY);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumSubframes (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumSubframes") == 0) {
+ _scValue->setInt(_subframes.size());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumEvents (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumEvents") == 0) {
+ _scValue->setInt(_applyEvent.size());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ else {
+ if (_subframes.size() == 1) {
+ return _subframes[0]->scGetProperty(name);
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFrame::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Delay
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Delay") == 0) {
+ _delay = MAX(0, value->getInt());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Keyframe
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Keyframe") == 0) {
+ _keyframe = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // KillSounds
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "KillSounds") == 0) {
+ _killSound = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MoveX") == 0) {
+ _moveX = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MoveY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MoveY") == 0) {
+ _moveY = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ else {
+ if (_subframes.size() == 1) {
+ return _subframes[0]->scSetProperty(name, value);
+ } else {
+ return BaseScriptable::scSetProperty(name, value);
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseFrame::scToString() {
+ return "[frame]";
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_frame.h b/engines/wintermute/base/base_frame.h
new file mode 100644
index 0000000000..ea5467b6fe
--- /dev/null
+++ b/engines/wintermute/base/base_frame.h
@@ -0,0 +1,73 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FRAME_H
+#define WINTERMUTE_BASE_FRAME_H
+
+#include "engines/wintermute/base/base_scriptable.h"
+#include "engines/wintermute/coll_templ.h"
+
+namespace Wintermute {
+class BaseSound;
+class BaseSubFrame;
+class BaseObject;
+class ScScript;
+class ScStack;
+class BaseFrame: public BaseScriptable {
+public:
+ bool _killSound;
+ bool _keyframe;
+ bool oneTimeDisplay(BaseObject *owner, bool muted = false);
+ DECLARE_PERSISTENT(BaseFrame, BaseScriptable)
+ BaseSound *_sound;
+ bool _editorExpanded;
+ bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
+ bool saveAsText(BaseDynamicBuffer *buffer, int indent);
+ int _moveY;
+ int _moveX;
+ uint32 _delay;
+ BaseArray<BaseSubFrame *> _subframes;
+ bool draw(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, bool allFrames = false, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded);
+
+ BaseFrame(BaseGame *inGame);
+ virtual ~BaseFrame();
+
+ BaseArray<const char *> _applyEvent;
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_game.cpp b/engines/wintermute/base/base_game.cpp
new file mode 100644
index 0000000000..622e85cc11
--- /dev/null
+++ b/engines/wintermute/base/base_game.cpp
@@ -0,0 +1,4483 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_fader.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/font/base_font_storage.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/base_keyboard_state.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_quick_msg.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_transition_manager.h"
+#include "engines/wintermute/base/base_viewport.h"
+#include "engines/wintermute/base/base_string_table.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/base_save_thumb_helper.h"
+#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/saveload.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_engine.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_ext_math.h"
+#include "engines/wintermute/video/video_player.h"
+#include "engines/wintermute/video/video_theora_player.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/utils/crc.h"
+#include "engines/wintermute/utils/path_util.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "engines/wintermute/ui/ui_window.h"
+#include "engines/wintermute/wintermute.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/config-manager.h"
+#include "common/savefile.h"
+#include "common/textconsole.h"
+#include "common/util.h"
+#include "common/keyboard.h"
+#include "common/system.h"
+#include "common/file.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(BaseGame, true)
+
+
+//////////////////////////////////////////////////////////////////////
+BaseGame::BaseGame(const Common::String &gameId) : BaseObject(this), _gameId(gameId) {
+ _shuttingDown = false;
+
+ _state = GAME_RUNNING;
+ _origState = GAME_RUNNING;
+ _freezeLevel = 0;
+
+ _interactive = true;
+ _origInteractive = false;
+
+ _surfaceStorage = NULL;
+ _fontStorage = NULL;
+ _renderer = NULL;
+ _soundMgr = NULL;
+ _transMgr = NULL;
+ _scEngine = NULL;
+ _keyboardState = NULL;
+
+ _mathClass = NULL;
+
+ _debugLogFile = NULL;
+ _debugDebugMode = false;
+ _debugShowFPS = false;
+
+ _systemFont = NULL;
+ _videoFont = NULL;
+
+ _videoPlayer = NULL;
+ _theoraPlayer = NULL;
+
+ _mainObject = NULL;
+ _activeObject = NULL;
+
+ _fader = NULL;
+
+ _offsetX = _offsetY = 0;
+ _offsetPercentX = _offsetPercentY = 0.0f;
+
+ _subtitles = true;
+ _videoSubtitles = true;
+
+ _timer = 0;
+ _timerDelta = 0;
+ _timerLast = 0;
+
+ _liveTimer = 0;
+ _liveTimerDelta = 0;
+ _liveTimerLast = 0;
+
+ _sequence = 0;
+
+ _mousePos.x = _mousePos.y = 0;
+ _mouseLeftDown = _mouseRightDown = _mouseMidlleDown = false;
+ _capturedObject = NULL;
+
+ // FPS counters
+ _lastTime = _fpsTime = _deltaTime = _framesRendered = _fps = 0;
+
+ _cursorNoninteractive = NULL;
+
+ _useD3D = false;
+
+ _stringTable = new BaseStringTable(this);
+
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ _music[i] = NULL;
+ _musicStartTime[i] = 0;
+ }
+
+ _settingsResWidth = 800;
+ _settingsResHeight = 600;
+ _settingsRequireAcceleration = false;
+ _settingsRequireSound = false;
+ _settingsTLMode = 0;
+ _settingsAllowWindowed = true;
+ _settingsGameFile = NULL;
+ _settingsAllowAdvanced = false;
+ _settingsAllowAccessTab = true;
+ _settingsAllowAboutTab = true;
+ _settingsAllowDesktopRes = false;
+
+ _editorForceScripts = false;
+ _editorAlwaysRegister = false;
+
+ _focusedWindow = NULL;
+
+ _loadInProgress = false;
+
+ _quitting = false;
+ _loading = false;
+ _scheduledLoadSlot = -1;
+
+ _personalizedSave = false;
+ _compressedSavegames = true;
+
+ _editorMode = false;
+ //_doNotExpandStrings = false;
+
+ _engineLogCallback = NULL;
+ _engineLogCallbackData = NULL;
+
+ _smartCache = false;
+ _surfaceGCCycleTime = 10000;
+
+ _reportTextureFormat = false;
+
+ _viewportSP = -1;
+
+ _subtitlesSpeed = 70;
+
+ _forceNonStreamedSounds = false;
+
+ _thumbnailWidth = _thumbnailHeight = 0;
+
+ _richSavedGames = false;
+ _savedGameExt = NULL;
+ BaseUtils::setString(&_savedGameExt, "dsv");
+
+ _musicCrossfadeRunning = false;
+ _musicCrossfadeStartTime = 0;
+ _musicCrossfadeLength = 0;
+ _musicCrossfadeChannel1 = -1;
+ _musicCrossfadeChannel2 = -1;
+ _musicCrossfadeSwap = false;
+
+ _localSaveDir = NULL;
+ BaseUtils::setString(&_localSaveDir, "saves");
+ _saveDirChecked = false;
+
+ _loadingIcon = NULL;
+ _loadingIconX = _loadingIconY = 0;
+ _loadingIconPersistent = false;
+
+ _textEncoding = TEXT_ANSI;
+ _textRTL = false;
+
+ _soundBufferSizeSec = 3;
+ _suspendedRendering = false;
+
+ _lastCursor = NULL;
+
+
+ BasePlatform::setRectEmpty(&_mouseLockRect);
+
+ _suppressScriptErrors = false;
+ _lastMiniUpdate = 0;
+ _miniUpdateEnabled = false;
+
+ _cachedThumbnail = NULL;
+
+ _autorunDisabled = false;
+
+ // compatibility bits
+ _compatKillMethodThreads = false;
+
+ _usedMem = 0;
+
+
+ _autoSaveOnExit = true;
+ _autoSaveSlot = 999;
+ _cursorHidden = false;
+
+ // Block kept as a reminder that the engine CAN run in constrained/touch-mode
+ /*#ifdef __IPHONEOS__
+ _touchInterface = true;
+ _constrainedMemory = true; // TODO differentiate old and new iOS devices
+ #else*/
+ _touchInterface = false;
+ _constrainedMemory = false;
+//#endif
+
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseGame::~BaseGame() {
+ _shuttingDown = true;
+
+ LOG(0, "");
+ LOG(0, "Shutting down...");
+
+ ConfMan.setBool("last_run", true);
+
+ cleanup();
+
+ delete[] _localSaveDir;
+ delete[] _settingsGameFile;
+ delete[] _savedGameExt;
+
+ delete _cachedThumbnail;
+
+ delete _mathClass;
+
+ delete _transMgr;
+ delete _scEngine;
+ delete _fontStorage;
+ delete _surfaceStorage;
+ delete _videoPlayer;
+ delete _theoraPlayer;
+ delete _soundMgr;
+ //SAFE_DELETE(_keyboardState);
+
+ delete _renderer;
+ delete _stringTable;
+
+ _localSaveDir = NULL;
+ _settingsGameFile = NULL;
+ _savedGameExt = NULL;
+
+ _cachedThumbnail = NULL;
+
+ _mathClass = NULL;
+
+ _transMgr = NULL;
+ _scEngine = NULL;
+ _fontStorage = NULL;
+ _surfaceStorage = NULL;
+ _videoPlayer = NULL;
+ _theoraPlayer = NULL;
+ _soundMgr = NULL;
+
+ _renderer = NULL;
+ _stringTable = NULL;
+
+ DEBUG_DebugDisable();
+ debugC(kWintermuteDebugLog, "--- shutting down normally ---\n");
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::cleanup() {
+ delete _loadingIcon;
+ _loadingIcon = NULL;
+
+ _engineLogCallback = NULL;
+ _engineLogCallbackData = NULL;
+
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ delete _music[i];
+ _music[i] = NULL;
+ _musicStartTime[i] = 0;
+ }
+
+ unregisterObject(_fader);
+ _fader = NULL;
+
+ for (uint32 i = 0; i < _regObjects.size(); i++) {
+ delete _regObjects[i];
+ _regObjects[i] = NULL;
+ }
+ _regObjects.clear();
+
+ _windows.clear(); // refs only
+ _focusedWindow = NULL; // ref only
+
+ delete _cursorNoninteractive;
+ delete _cursor;
+ delete _activeCursor;
+ _cursorNoninteractive = NULL;
+ _cursor = NULL;
+ _activeCursor = NULL;
+
+ delete _scValue;
+ delete _sFX;
+ _scValue = NULL;
+ _sFX = NULL;
+
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ _scripts[i]->_owner = NULL;
+ _scripts[i]->finish();
+ }
+ _scripts.clear();
+
+ _fontStorage->removeFont(_systemFont);
+ _systemFont = NULL;
+
+ _fontStorage->removeFont(_videoFont);
+ _videoFont = NULL;
+
+ for (uint32 i = 0; i < _quickMessages.size(); i++) {
+ delete _quickMessages[i];
+ }
+ _quickMessages.clear();
+
+ _viewportStack.clear();
+ _viewportSP = -1;
+
+ setName(NULL);
+ setFilename(NULL);
+ for (int i = 0; i < 7; i++) {
+ delete[] _caption[i];
+ _caption[i] = NULL;
+ }
+
+ _lastCursor = NULL;
+
+ delete _keyboardState;
+ _keyboardState = NULL;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseGame::initialize1() {
+ bool loaded = false; // Not really a loop, but a goto-replacement.
+ while (!loaded) {
+ _surfaceStorage = new BaseSurfaceStorage(this);
+ if (_surfaceStorage == NULL) {
+ break;
+ }
+
+ _fontStorage = new BaseFontStorage(this);
+ if (_fontStorage == NULL) {
+ break;
+ }
+
+ _soundMgr = new BaseSoundMgr(this);
+ if (_soundMgr == NULL) {
+ break;
+ }
+
+ _mathClass = new SXMath(this);
+ if (_mathClass == NULL) {
+ break;
+ }
+
+ _scEngine = new ScEngine(this);
+ if (_scEngine == NULL) {
+ break;
+ }
+
+ _videoPlayer = new VideoPlayer(this);
+ if (_videoPlayer == NULL) {
+ break;
+ }
+
+ _transMgr = new BaseTransitionMgr(this);
+ if (_transMgr == NULL) {
+ break;
+ }
+
+ _keyboardState = new BaseKeyboardState(this);
+ if (_keyboardState == NULL) {
+ break;
+ }
+
+ _fader = new BaseFader(this);
+ if (_fader == NULL) {
+ break;
+ }
+ registerObject(_fader);
+
+ loaded = true;
+ }
+ if (loaded == true) {
+ return STATUS_OK;
+ } else {
+ delete _mathClass;
+ delete _keyboardState;
+ delete _transMgr;
+ delete _surfaceStorage;
+ delete _fontStorage;
+ delete _soundMgr;
+ delete _scEngine;
+ delete _videoPlayer;
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseGame::initialize2() { // we know whether we are going to be accelerated
+ _renderer = makeOSystemRenderer(this);
+ if (_renderer == NULL) {
+ return STATUS_FAILED;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseGame::initialize3() { // renderer is initialized
+ _posX = _renderer->_width / 2;
+ _posY = _renderer->_height / 2;
+ _renderer->initIndicator();
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseGame::DEBUG_DebugEnable(const char *filename) {
+ _debugDebugMode = true;
+
+ int secs = g_system->getMillis() / 1000;
+ int hours = secs / 3600;
+ secs = secs % 3600;
+ int mins = secs / 60;
+ secs = secs % 60;
+
+#ifdef _DEBUG
+ LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%02d (Debug Build) *******************", hours, mins, secs);
+#else
+ LOG(0, "********** DEBUG LOG OPENED %02d-%02d-%02d (Release Build) *****************", hours, mins, secs);
+#endif
+
+ LOG(0, "%s ver %d.%d.%d%s, Compiled on " __DATE__ ", " __TIME__, DCGF_NAME, DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, DCGF_VER_SUFFIX);
+
+ AnsiString platform = BasePlatform::getPlatformName();
+ LOG(0, "Platform: %s", platform.c_str());
+ LOG(0, "");
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseGame::DEBUG_DebugDisable() {
+ if (_debugLogFile != NULL) {
+ LOG(0, "********** DEBUG LOG CLOSED ********************************************");
+ //fclose((FILE *)_debugLogFile);
+ _debugLogFile = NULL;
+ }
+ _debugDebugMode = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseGame::LOG(bool res, const char *fmt, ...) {
+ uint32 secs = g_system->getMillis() / 1000;
+ uint32 hours = secs / 3600;
+ secs = secs % 3600;
+ uint32 mins = secs / 60;
+ secs = secs % 60;
+
+ char buff[512];
+ va_list va;
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ // redirect to an engine's own callback
+ if (_engineLogCallback) {
+ _engineLogCallback(buff, res, _engineLogCallbackData);
+ }
+
+ debugCN(kWintermuteDebugLog, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);
+
+ //fprintf((FILE *)_debugLogFile, "%02d:%02d:%02d: %s\n", hours, mins, secs, buff);
+ //fflush((FILE *)_debugLogFile);
+
+ //QuickMessage(buff);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::setEngineLogCallback(ENGINE_LOG_CALLBACK callback, void *data) {
+ _engineLogCallback = callback;
+ _engineLogCallbackData = data;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseGame::initLoop() {
+ _viewportSP = -1;
+
+ _currentTime = g_system->getMillis();
+
+ _renderer->initLoop();
+ updateMusicCrossfade();
+
+ _surfaceStorage->initLoop();
+ _fontStorage->initLoop();
+
+
+ //_activeObject = NULL;
+
+ // count FPS
+ _deltaTime = _currentTime - _lastTime;
+ _lastTime = _currentTime;
+ _fpsTime += _deltaTime;
+
+ _liveTimerDelta = _liveTimer - _liveTimerLast;
+ _liveTimerLast = _liveTimer;
+ _liveTimer += MIN((uint32)1000, _deltaTime);
+
+ if (_state != GAME_FROZEN) {
+ _timerDelta = _timer - _timerLast;
+ _timerLast = _timer;
+ _timer += MIN((uint32)1000, _deltaTime);
+ } else {
+ _timerDelta = 0;
+ }
+
+ _framesRendered++;
+ if (_fpsTime > 1000) {
+ _fps = _framesRendered;
+ _framesRendered = 0;
+ _fpsTime = 0;
+ }
+ //_gameRef->LOG(0, "%d", _fps);
+
+ getMousePos(&_mousePos);
+
+ _focusedWindow = NULL;
+ for (int i = _windows.size() - 1; i >= 0; i--) {
+ if (_windows[i]->_visible) {
+ _focusedWindow = _windows[i];
+ break;
+ }
+ }
+
+ updateSounds();
+
+ if (_fader) {
+ _fader->update();
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseGame::initInput() {
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseGame::getSequence() {
+ return ++_sequence;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::setOffset(int offsetX, int offsetY) {
+ _offsetX = offsetX;
+ _offsetY = offsetY;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::getOffset(int *offsetX, int *offsetY) {
+ if (offsetX != NULL) {
+ *offsetX = _offsetX;
+ }
+ if (offsetY != NULL) {
+ *offsetY = _offsetY;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::loadFile(const char *filename) {
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer == NULL) {
+ _gameRef->LOG(0, "BaseGame::LoadFile failed for file '%s'", filename);
+ return STATUS_FAILED;
+ }
+
+ bool ret;
+
+ setFilename(filename);
+
+ if (DID_FAIL(ret = loadBuffer(buffer, true))) {
+ _gameRef->LOG(0, "Error parsing GAME file '%s'", filename);
+ }
+
+ delete[] buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(GAME)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(NAME)
+TOKEN_DEF(SYSTEM_FONT)
+TOKEN_DEF(VIDEO_FONT)
+TOKEN_DEF(EVENTS)
+TOKEN_DEF(CURSOR)
+TOKEN_DEF(ACTIVE_CURSOR)
+TOKEN_DEF(NONINTERACTIVE_CURSOR)
+TOKEN_DEF(STRING_TABLE)
+TOKEN_DEF(RESOLUTION)
+TOKEN_DEF(SETTINGS)
+TOKEN_DEF(REQUIRE_3D_ACCELERATION)
+TOKEN_DEF(REQUIRE_SOUND)
+TOKEN_DEF(HWTL_MODE)
+TOKEN_DEF(ALLOW_WINDOWED_MODE)
+TOKEN_DEF(ALLOW_ACCESSIBILITY_TAB)
+TOKEN_DEF(ALLOW_ABOUT_TAB)
+TOKEN_DEF(ALLOW_ADVANCED)
+TOKEN_DEF(ALLOW_DESKTOP_RES)
+TOKEN_DEF(REGISTRY_PATH)
+TOKEN_DEF(PERSONAL_SAVEGAMES)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(PROPERTY)
+TOKEN_DEF(SUBTITLES_SPEED)
+TOKEN_DEF(SUBTITLES)
+TOKEN_DEF(VIDEO_SUBTITLES)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(THUMBNAIL_WIDTH)
+TOKEN_DEF(THUMBNAIL_HEIGHT)
+TOKEN_DEF(INDICATOR_X)
+TOKEN_DEF(INDICATOR_Y)
+TOKEN_DEF(INDICATOR_WIDTH)
+TOKEN_DEF(INDICATOR_HEIGHT)
+TOKEN_DEF(INDICATOR_COLOR)
+TOKEN_DEF(SAVE_IMAGE_X)
+TOKEN_DEF(SAVE_IMAGE_Y)
+TOKEN_DEF(SAVE_IMAGE)
+TOKEN_DEF(LOAD_IMAGE_X)
+TOKEN_DEF(LOAD_IMAGE_Y)
+TOKEN_DEF(LOAD_IMAGE)
+TOKEN_DEF(LOCAL_SAVE_DIR)
+TOKEN_DEF(RICH_SAVED_GAMES)
+TOKEN_DEF(SAVED_GAME_EXT)
+TOKEN_DEF(GUID)
+TOKEN_DEF(COMPAT_KILL_METHOD_THREADS)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::loadBuffer(byte *buffer, bool complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(GAME)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(SYSTEM_FONT)
+ TOKEN_TABLE(VIDEO_FONT)
+ TOKEN_TABLE(EVENTS)
+ TOKEN_TABLE(CURSOR)
+ TOKEN_TABLE(ACTIVE_CURSOR)
+ TOKEN_TABLE(NONINTERACTIVE_CURSOR)
+ TOKEN_TABLE(PERSONAL_SAVEGAMES)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(PROPERTY)
+ TOKEN_TABLE(SUBTITLES_SPEED)
+ TOKEN_TABLE(SUBTITLES)
+ TOKEN_TABLE(VIDEO_SUBTITLES)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(THUMBNAIL_WIDTH)
+ TOKEN_TABLE(THUMBNAIL_HEIGHT)
+ TOKEN_TABLE(INDICATOR_X)
+ TOKEN_TABLE(INDICATOR_Y)
+ TOKEN_TABLE(INDICATOR_WIDTH)
+ TOKEN_TABLE(INDICATOR_HEIGHT)
+ TOKEN_TABLE(INDICATOR_COLOR)
+ TOKEN_TABLE(SAVE_IMAGE_X)
+ TOKEN_TABLE(SAVE_IMAGE_Y)
+ TOKEN_TABLE(SAVE_IMAGE)
+ TOKEN_TABLE(LOAD_IMAGE_X)
+ TOKEN_TABLE(LOAD_IMAGE_Y)
+ TOKEN_TABLE(LOAD_IMAGE)
+ TOKEN_TABLE(LOCAL_SAVE_DIR)
+ TOKEN_TABLE(COMPAT_KILL_METHOD_THREADS)
+ TOKEN_TABLE_END
+
+ // Declare a few variables necessary for moving data from these settings over to the renderer:
+ // The values are the same as the defaults set in BaseRenderer.
+ int loadImageX = 0;
+ int loadImageY = 0;
+ int saveImageX = 0;
+ int saveImageY = 0;
+ int indicatorX = -1;
+ int indicatorY = -1;
+ int indicatorWidth = -1;
+ int indicatorHeight = 8;
+ uint32 indicatorColor = BYTETORGBA(255, 0, 0, 128);
+ Common::String loadImageName = "";
+ Common::String saveImageName = "";
+
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ if (complete) {
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_GAME) {
+ _gameRef->LOG(0, "'GAME' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ }
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (DID_FAIL(loadFile((char *)params))) {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_NAME:
+ setName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ setCaption((char *)params);
+ break;
+
+ case TOKEN_SYSTEM_FONT:
+ if (_systemFont) {
+ _fontStorage->removeFont(_systemFont);
+ }
+ _systemFont = NULL;
+
+ _systemFont = _gameRef->_fontStorage->addFont((char *)params);
+ break;
+
+ case TOKEN_VIDEO_FONT:
+ if (_videoFont) {
+ _fontStorage->removeFont(_videoFont);
+ }
+ _videoFont = NULL;
+
+ _videoFont = _gameRef->_fontStorage->addFont((char *)params);
+ break;
+
+
+ case TOKEN_CURSOR:
+ delete _cursor;
+ _cursor = new BaseSprite(_gameRef);
+ if (!_cursor || DID_FAIL(_cursor->loadFile((char *)params))) {
+ delete _cursor;
+ _cursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_ACTIVE_CURSOR:
+ delete _activeCursor;
+ _activeCursor = NULL;
+ _activeCursor = new BaseSprite(_gameRef);
+ if (!_activeCursor || DID_FAIL(_activeCursor->loadFile((char *)params))) {
+ delete _activeCursor;
+ _activeCursor = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_NONINTERACTIVE_CURSOR:
+ delete _cursorNoninteractive;
+ _cursorNoninteractive = new BaseSprite(_gameRef);
+ if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile((char *)params))) {
+ delete _cursorNoninteractive;
+ _cursorNoninteractive = NULL;
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ addScript((char *)params);
+ break;
+
+ case TOKEN_PERSONAL_SAVEGAMES:
+ parser.scanStr((char *)params, "%b", &_personalizedSave);
+ break;
+
+ case TOKEN_SUBTITLES:
+ parser.scanStr((char *)params, "%b", &_subtitles);
+ break;
+
+ case TOKEN_SUBTITLES_SPEED:
+ parser.scanStr((char *)params, "%d", &_subtitlesSpeed);
+ break;
+
+ case TOKEN_VIDEO_SUBTITLES:
+ parser.scanStr((char *)params, "%b", &_videoSubtitles);
+ break;
+
+ case TOKEN_PROPERTY:
+ parseProperty(params, false);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ parseEditorProperty(params, false);
+ break;
+
+ case TOKEN_THUMBNAIL_WIDTH:
+ parser.scanStr((char *)params, "%d", &_thumbnailWidth);
+ break;
+
+ case TOKEN_THUMBNAIL_HEIGHT:
+ parser.scanStr((char *)params, "%d", &_thumbnailHeight);
+ break;
+
+ case TOKEN_INDICATOR_X:
+ parser.scanStr((char *)params, "%d", &indicatorX);
+ break;
+
+ case TOKEN_INDICATOR_Y:
+ parser.scanStr((char *)params, "%d", &indicatorY);
+ break;
+
+ case TOKEN_INDICATOR_COLOR: {
+ int r, g, b, a;
+ parser.scanStr((char *)params, "%d,%d,%d,%d", &r, &g, &b, &a);
+ indicatorColor = BYTETORGBA(r, g, b, a);
+ }
+ break;
+
+ case TOKEN_INDICATOR_WIDTH:
+ parser.scanStr((char *)params, "%d", &indicatorWidth);
+ break;
+
+ case TOKEN_INDICATOR_HEIGHT:
+ parser.scanStr((char *)params, "%d", &indicatorHeight);
+ break;
+
+ case TOKEN_SAVE_IMAGE:
+ saveImageName = (char *) params;
+ break;
+
+ case TOKEN_SAVE_IMAGE_X:
+ parser.scanStr((char *)params, "%d", &saveImageX);
+ break;
+
+ case TOKEN_SAVE_IMAGE_Y:
+ parser.scanStr((char *)params, "%d", &saveImageY);
+ break;
+
+ case TOKEN_LOAD_IMAGE:
+ loadImageName = (char *) params;
+ break;
+
+ case TOKEN_LOAD_IMAGE_X:
+ parser.scanStr((char *)params, "%d", &loadImageX);
+ break;
+
+ case TOKEN_LOAD_IMAGE_Y:
+ parser.scanStr((char *)params, "%d", &loadImageY);
+ break;
+
+ case TOKEN_LOCAL_SAVE_DIR:
+ BaseUtils::setString(&_localSaveDir, (char *)params);
+ break;
+
+ case TOKEN_COMPAT_KILL_METHOD_THREADS:
+ parser.scanStr((char *)params, "%b", &_compatKillMethodThreads);
+ break;
+ }
+ }
+
+ _renderer->setIndicator(indicatorWidth, indicatorHeight, indicatorX, indicatorY, indicatorColor);
+ _renderer->initIndicator(); // In case we just reset the values.
+ _renderer->setSaveImage(saveImageName.c_str(), saveImageX, saveImageY);
+ _renderer->setLoadingScreen(loadImageName.c_str(), loadImageX, loadImageY);
+
+ if (!_systemFont) {
+ _systemFont = _gameRef->_fontStorage->addFont("system_font.fnt");
+ }
+
+
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in GAME definition");
+ return STATUS_FAILED;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ _gameRef->LOG(0, "Error loading GAME definition");
+ return STATUS_FAILED;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // LOG
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "LOG") == 0) {
+ stack->correctParams(1);
+ LOG(0, stack->pop()->getString());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Caption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Caption") == 0) {
+ bool res = BaseObject::scCallMethod(script, stack, thisStack, name);
+ setWindowTitle();
+ return res;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Msg
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Msg") == 0) {
+ stack->correctParams(1);
+ quickMessage(stack->pop()->getString());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RunScript
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RunScript") == 0) {
+ _gameRef->LOG(0, "**Warning** The 'RunScript' method is now obsolete. Use 'AttachScript' instead (same syntax)");
+ stack->correctParams(1);
+ if (DID_FAIL(addScript(stack->pop()->getString()))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadStringTable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LoadStringTable") == 0) {
+ stack->correctParams(2);
+ const char *filename = stack->pop()->getString();
+ ScValue *val = stack->pop();
+
+ bool clearOld;
+ if (val->isNULL()) {
+ clearOld = true;
+ } else {
+ clearOld = val->getBool();
+ }
+
+ if (DID_FAIL(_stringTable->loadFile(filename, clearOld))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ValidObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ValidObject") == 0) {
+ stack->correctParams(1);
+ BaseScriptable *obj = stack->pop()->getNative();
+ if (validObject((BaseObject *) obj)) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Reset
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Reset") == 0) {
+ stack->correctParams(0);
+ resetContent();
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // UnloadObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "UnloadObject") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ BaseObject *obj = (BaseObject *)val->getNative();
+ unregisterObject(obj);
+ if (val->getType() == VAL_VARIABLE_REF) {
+ val->setNULL();
+ }
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LoadWindow") == 0) {
+ stack->correctParams(1);
+ UIWindow *win = new UIWindow(_gameRef);
+ if (win && DID_SUCCEED(win->loadFile(stack->pop()->getString()))) {
+ _windows.add(win);
+ registerObject(win);
+ stack->pushNative(win, true);
+ } else {
+ delete win;
+ win = NULL;
+ stack->pushNULL();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ExpandString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ExpandString") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ char *str = new char[strlen(val->getString()) + 1];
+ strcpy(str, val->getString());
+ _stringTable->expand(&str);
+ stack->pushString(str);
+ delete[] str;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PlayMusic / PlayMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PlayMusic") == 0 || strcmp(name, "PlayMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "PlayMusic") == 0) {
+ stack->correctParams(3);
+ } else {
+ stack->correctParams(4);
+ channel = stack->pop()->getInt();
+ }
+
+ const char *filename = stack->pop()->getString();
+ ScValue *valLooping = stack->pop();
+ bool looping = valLooping->isNULL() ? true : valLooping->getBool();
+
+ ScValue *valLoopStart = stack->pop();
+ uint32 loopStart = (uint32)(valLoopStart->isNULL() ? 0 : valLoopStart->getInt());
+
+
+ if (DID_FAIL(playMusic(channel, filename, looping, loopStart))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // StopMusic / StopMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "StopMusic") == 0 || strcmp(name, "StopMusicChannel") == 0) {
+ int channel = 0;
+
+ if (strcmp(name, "StopMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(stopMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseMusic / PauseMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PauseMusic") == 0 || strcmp(name, "PauseMusicChannel") == 0) {
+ int channel = 0;
+
+ if (strcmp(name, "PauseMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(pauseMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ResumeMusic / ResumeMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ResumeMusic") == 0 || strcmp(name, "ResumeMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "ResumeMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (DID_FAIL(resumeMusic(channel))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusic / GetMusicChannel
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusic") == 0 || strcmp(name, "GetMusicChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusic") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS) {
+ stack->pushNULL();
+ } else {
+ if (!_music[channel] || !_music[channel]->getFilename()) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_music[channel]->getFilename());
+ }
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetMusicPosition / SetMusicChannelPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMusicPosition") == 0 || strcmp(name, "SetMusicChannelPosition") == 0 || strcmp(name, "SetMusicPositionChannel") == 0) {
+ int channel = 0;
+ if (strcmp(name, "SetMusicPosition") == 0) {
+ stack->correctParams(1);
+ } else {
+ stack->correctParams(2);
+ channel = stack->pop()->getInt();
+ }
+
+ uint32 time = stack->pop()->getInt();
+
+ if (DID_FAIL(setMusicStartTime(channel, time))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusicPosition / GetMusicChannelPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusicPosition") == 0 || strcmp(name, "GetMusicChannelPosition") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusicPosition") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushInt(0);
+ } else {
+ stack->pushInt(_music[channel]->getPositionTime());
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsMusicPlaying / IsMusicChannelPlaying
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsMusicPlaying") == 0 || strcmp(name, "IsMusicChannelPlaying") == 0) {
+ int channel = 0;
+ if (strcmp(name, "IsMusicPlaying") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(_music[channel]->isPlaying());
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetMusicVolume / SetMusicChannelVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMusicVolume") == 0 || strcmp(name, "SetMusicChannelVolume") == 0) {
+ int channel = 0;
+ if (strcmp(name, "SetMusicVolume") == 0) {
+ stack->correctParams(1);
+ } else {
+ stack->correctParams(2);
+ channel = stack->pop()->getInt();
+ }
+
+ int volume = stack->pop()->getInt();
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushBool(false);
+ } else {
+ if (DID_FAIL(_music[channel]->setVolumePercent(volume))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetMusicVolume / GetMusicChannelVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMusicVolume") == 0 || strcmp(name, "GetMusicChannelVolume") == 0) {
+ int channel = 0;
+ if (strcmp(name, "GetMusicVolume") == 0) {
+ stack->correctParams(0);
+ } else {
+ stack->correctParams(1);
+ channel = stack->pop()->getInt();
+ }
+
+ if (channel < 0 || channel >= NUM_MUSIC_CHANNELS || !_music[channel]) {
+ stack->pushInt(0);
+ } else {
+ stack->pushInt(_music[channel]->getVolumePercent());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MusicCrossfade
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MusicCrossfade") == 0) {
+ stack->correctParams(4);
+ int channel1 = stack->pop()->getInt(0);
+ int channel2 = stack->pop()->getInt(0);
+ uint32 fadeLength = (uint32)stack->pop()->getInt(0);
+ bool swap = stack->pop()->getBool(true);
+
+ if (_musicCrossfadeRunning) {
+ script->runtimeError("Game.MusicCrossfade: Music crossfade is already in progress.");
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ _musicCrossfadeStartTime = _liveTimer;
+ _musicCrossfadeChannel1 = channel1;
+ _musicCrossfadeChannel2 = channel2;
+ _musicCrossfadeLength = fadeLength;
+ _musicCrossfadeSwap = swap;
+
+ _musicCrossfadeRunning = true;
+
+ stack->pushBool(true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSoundLength
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSoundLength") == 0) {
+ stack->correctParams(1);
+
+ int length = 0;
+ const char *filename = stack->pop()->getString();
+
+ BaseSound *sound = new BaseSound(_gameRef);
+ if (sound && DID_SUCCEED(sound->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
+ length = sound->getLength();
+ delete sound;
+ sound = NULL;
+ }
+ stack->pushInt(length);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetMousePos
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMousePos") == 0) {
+ stack->correctParams(2);
+ int x = stack->pop()->getInt();
+ int y = stack->pop()->getInt();
+ x = MAX(x, 0);
+ x = MIN(x, _renderer->_width);
+ y = MAX(y, 0);
+ y = MIN(y, _renderer->_height);
+ Point32 p;
+ p.x = x + _renderer->_drawOffsetX;
+ p.y = y + _renderer->_drawOffsetY;
+
+ BasePlatform::setCursorPos(p.x, p.y);
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LockMouseRect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LockMouseRect") == 0) {
+ stack->correctParams(4);
+ int left = stack->pop()->getInt();
+ int top = stack->pop()->getInt();
+ int right = stack->pop()->getInt();
+ int bottom = stack->pop()->getInt();
+
+ if (right < left) {
+ BaseUtils::swap(&left, &right);
+ }
+ if (bottom < top) {
+ BaseUtils::swap(&top, &bottom);
+ }
+
+ BasePlatform::setRect(&_mouseLockRect, left, top, right, bottom);
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PlayVideo
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PlayVideo") == 0) {
+ _gameRef->LOG(0, "Warning: Game.PlayVideo() is now deprecated. Use Game.PlayTheora() instead.");
+
+ stack->correctParams(6);
+ const char *filename = stack->pop()->getString();
+ warning("PlayVideo: %s - not implemented yet", filename);
+ ScValue *valType = stack->pop();
+ int type;
+ if (valType->isNULL()) {
+ type = (int)VID_PLAY_STRETCH;
+ } else {
+ type = valType->getInt();
+ }
+
+ int xVal = stack->pop()->getInt();
+ int yVal = stack->pop()->getInt();
+ bool freezeMusic = stack->pop()->getBool(true);
+
+ ScValue *valSub = stack->pop();
+ const char *subtitleFile = valSub->isNULL() ? NULL : valSub->getString();
+
+ if (type < (int)VID_PLAY_POS || type > (int)VID_PLAY_CENTER) {
+ type = (int)VID_PLAY_STRETCH;
+ }
+
+ if (DID_SUCCEED(_gameRef->_videoPlayer->initialize(filename, subtitleFile))) {
+ if (DID_SUCCEED(_gameRef->_videoPlayer->play((TVideoPlayback)type, xVal, yVal, freezeMusic))) {
+ stack->pushBool(true);
+ script->sleep(0);
+ } else {
+ stack->pushBool(false);
+ }
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PlayTheora
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PlayTheora") == 0) {
+ stack->correctParams(7);
+ const char *filename = stack->pop()->getString();
+ ScValue *valType = stack->pop();
+ int type;
+ if (valType->isNULL()) {
+ type = (int)VID_PLAY_STRETCH;
+ } else {
+ type = valType->getInt();
+ }
+
+ int xVal = stack->pop()->getInt();
+ int yVal = stack->pop()->getInt();
+ bool freezeMusic = stack->pop()->getBool(true);
+ bool dropFrames = stack->pop()->getBool(true);
+
+ ScValue *valSub = stack->pop();
+ const char *subtitleFile = valSub->isNULL() ? NULL : valSub->getString();
+
+ if (type < (int)VID_PLAY_POS || type > (int)VID_PLAY_CENTER) {
+ type = (int)VID_PLAY_STRETCH;
+ }
+
+ delete _theoraPlayer;
+ _theoraPlayer = new VideoTheoraPlayer(this);
+ if (_theoraPlayer && DID_SUCCEED(_theoraPlayer->initialize(filename, subtitleFile))) {
+ _theoraPlayer->_dontDropFrames = !dropFrames;
+ if (DID_SUCCEED(_theoraPlayer->play((TVideoPlayback)type, xVal, yVal, true, freezeMusic))) {
+ stack->pushBool(true);
+ script->sleep(0);
+ } else {
+ stack->pushBool(false);
+ }
+ } else {
+ stack->pushBool(false);
+ delete _theoraPlayer;
+ _theoraPlayer = NULL;
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // QuitGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "QuitGame") == 0) {
+ stack->correctParams(0);
+ stack->pushNULL();
+ _quitting = true;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RegWriteNumber
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RegWriteNumber") == 0) {
+ stack->correctParams(2);
+ const char *key = stack->pop()->getString();
+ int val = stack->pop()->getInt();
+ Common::String privKey = "priv_" + StringUtil::encodeSetting(key);
+ ConfMan.setInt(privKey, val);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RegReadNumber
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RegReadNumber") == 0) {
+ stack->correctParams(2);
+ const char *key = stack->pop()->getString();
+ int initVal = stack->pop()->getInt();
+ Common::String privKey = "priv_" + StringUtil::encodeSetting(key);
+ int result = initVal;
+ if (ConfMan.hasKey(privKey)) {
+ result = ConfMan.getInt(privKey);
+ }
+ stack->pushInt(result);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RegWriteString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RegWriteString") == 0) {
+ stack->correctParams(2);
+ const char *key = stack->pop()->getString();
+ const char *val = stack->pop()->getString();
+ Common::String privKey = "priv_" + StringUtil::encodeSetting(key);
+ Common::String privVal = StringUtil::encodeSetting(val);
+ ConfMan.set(privKey, privVal);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RegReadString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RegReadString") == 0) {
+ stack->correctParams(2);
+ const char *key = stack->pop()->getString();
+ const char *initVal = stack->pop()->getString();
+ Common::String privKey = "priv_" + StringUtil::encodeSetting(key);
+ Common::String result = initVal;
+ if (ConfMan.hasKey(privKey)) {
+ result = StringUtil::decodeSetting(ConfMan.get(key));
+ }
+ stack->pushString(result.c_str());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SaveGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SaveGame") == 0) {
+ stack->correctParams(3);
+ int slot = stack->pop()->getInt();
+ const char *xdesc = stack->pop()->getString();
+ bool quick = stack->pop()->getBool(false);
+
+ char *desc = new char[strlen(xdesc) + 1];
+ strcpy(desc, xdesc);
+ stack->pushBool(true);
+ if (DID_FAIL(saveGame(slot, desc, quick))) {
+ stack->pop();
+ stack->pushBool(false);
+ }
+ delete[] desc;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadGame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LoadGame") == 0) {
+ stack->correctParams(1);
+ _scheduledLoadSlot = stack->pop()->getInt();
+ _loading = true;
+ stack->pushBool(false);
+ script->sleep(0);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsSaveSlotUsed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsSaveSlotUsed") == 0) {
+ stack->correctParams(1);
+ int slot = stack->pop()->getInt();
+ stack->pushBool(SaveLoad::isSaveSlotUsed(slot));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSaveSlotDescription
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSaveSlotDescription") == 0) {
+ stack->correctParams(1);
+ int slot = stack->pop()->getInt();
+ char desc[512];
+ desc[0] = '\0';
+ SaveLoad::getSaveSlotDescription(slot, desc);
+ stack->pushString(desc);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EmptySaveSlot
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EmptySaveSlot") == 0) {
+ stack->correctParams(1);
+ int slot = stack->pop()->getInt();
+ SaveLoad::emptySaveSlot(slot);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetGlobalSFXVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetGlobalSFXVolume") == 0) {
+ stack->correctParams(1);
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kSFXSoundType, (byte)stack->pop()->getInt());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetGlobalSpeechVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetGlobalSpeechVolume") == 0) {
+ stack->correctParams(1);
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kSpeechSoundType, (byte)stack->pop()->getInt());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetGlobalMusicVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetGlobalMusicVolume") == 0) {
+ stack->correctParams(1);
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kMusicSoundType, (byte)stack->pop()->getInt());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetGlobalMasterVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetGlobalMasterVolume") == 0) {
+ stack->correctParams(1);
+ _gameRef->_soundMgr->setMasterVolumePercent((byte)stack->pop()->getInt());
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetGlobalSFXVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetGlobalSFXVolume") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_soundMgr->getVolumePercent(Audio::Mixer::kSFXSoundType));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetGlobalSpeechVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetGlobalSpeechVolume") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_soundMgr->getVolumePercent(Audio::Mixer::kSpeechSoundType));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetGlobalMusicVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetGlobalMusicVolume") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_soundMgr->getVolumePercent(Audio::Mixer::kMusicSoundType));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetGlobalMasterVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetGlobalMasterVolume") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_soundMgr->getMasterVolumePercent());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetActiveCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetActiveCursor") == 0) {
+ stack->correctParams(1);
+ if (DID_SUCCEED(setActiveCursor(stack->pop()->getString()))) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetActiveCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetActiveCursor") == 0) {
+ stack->correctParams(0);
+ if (!_activeCursor || !_activeCursor->getFilename()) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_activeCursor->getFilename());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetActiveCursorObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetActiveCursorObject") == 0) {
+ stack->correctParams(0);
+ if (!_activeCursor) {
+ stack->pushNULL();
+ } else {
+ stack->pushNative(_activeCursor, true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveActiveCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveActiveCursor") == 0) {
+ stack->correctParams(0);
+ delete _activeCursor;
+ _activeCursor = NULL;
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HasActiveCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HasActiveCursor") == 0) {
+ stack->correctParams(0);
+
+ if (_activeCursor) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FileExists
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FileExists") == 0) {
+ stack->correctParams(1);
+ const char *filename = stack->pop()->getString();
+
+ bool exists = BaseFileManager::getEngineInstance()->hasFile(filename); // Had absPathWarning = false
+ stack->pushBool(exists);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeOut / FadeOutAsync / SystemFadeOut / SystemFadeOutAsync
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeOut") == 0 || strcmp(name, "FadeOutAsync") == 0 || strcmp(name, "SystemFadeOut") == 0 || strcmp(name, "SystemFadeOutAsync") == 0) {
+ stack->correctParams(5);
+ uint32 duration = stack->pop()->getInt(500);
+ byte red = stack->pop()->getInt(0);
+ byte green = stack->pop()->getInt(0);
+ byte blue = stack->pop()->getInt(0);
+ byte alpha = stack->pop()->getInt(0xFF);
+
+ bool system = (strcmp(name, "SystemFadeOut") == 0 || strcmp(name, "SystemFadeOutAsync") == 0);
+
+ _fader->fadeOut(BYTETORGBA(red, green, blue, alpha), duration, system);
+ if (strcmp(name, "FadeOutAsync") != 0 && strcmp(name, "SystemFadeOutAsync") != 0) {
+ script->waitFor(_fader);
+ }
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeIn / FadeInAsync / SystemFadeIn / SystemFadeInAsync
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeIn") == 0 || strcmp(name, "FadeInAsync") == 0 || strcmp(name, "SystemFadeIn") == 0 || strcmp(name, "SystemFadeInAsync") == 0) {
+ stack->correctParams(5);
+ uint32 duration = stack->pop()->getInt(500);
+ byte red = stack->pop()->getInt(0);
+ byte green = stack->pop()->getInt(0);
+ byte blue = stack->pop()->getInt(0);
+ byte alpha = stack->pop()->getInt(0xFF);
+
+ bool system = (strcmp(name, "SystemFadeIn") == 0 || strcmp(name, "SystemFadeInAsync") == 0);
+
+ _fader->fadeIn(BYTETORGBA(red, green, blue, alpha), duration, system);
+ if (strcmp(name, "FadeInAsync") != 0 && strcmp(name, "SystemFadeInAsync") != 0) {
+ script->waitFor(_fader);
+ }
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFadeColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetFadeColor") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_fader->getCurrentColor());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Screenshot
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Screenshot") == 0) {
+ stack->correctParams(1);
+ char filename[MAX_PATH_LENGTH];
+
+ ScValue *val = stack->pop();
+
+ warning("BGame::ScCallMethod - Screenshot not reimplemented"); //TODO
+ int fileNum = 0;
+
+ while (true) {
+ sprintf(filename, "%s%03d.bmp", val->isNULL() ? getName() : val->getString(), fileNum);
+ if (!Common::File::exists(filename)) {
+ break;
+ }
+ fileNum++;
+ }
+
+ bool ret = false;
+ BaseImage *image = _gameRef->_renderer->takeScreenshot();
+ if (image) {
+ ret = DID_SUCCEED(image->saveBMPFile(filename));
+ delete image;
+ } else {
+ ret = false;
+ }
+
+ stack->pushBool(ret);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScreenshotEx
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScreenshotEx") == 0) {
+ stack->correctParams(3);
+ const char *filename = stack->pop()->getString();
+ int sizeX = stack->pop()->getInt(_renderer->_width);
+ int sizeY = stack->pop()->getInt(_renderer->_height);
+
+ bool ret = false;
+ BaseImage *image = _gameRef->_renderer->takeScreenshot();
+ if (image) {
+ ret = DID_SUCCEED(image->resize(sizeX, sizeY));
+ if (ret) {
+ ret = DID_SUCCEED(image->saveBMPFile(filename));
+ }
+ delete image;
+ } else {
+ ret = false;
+ }
+
+ stack->pushBool(ret);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CreateWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CreateWindow") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+
+ UIWindow *win = new UIWindow(_gameRef);
+ _windows.add(win);
+ registerObject(win);
+ if (!val->isNULL()) {
+ win->setName(val->getString());
+ }
+ stack->pushNative(win, true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteWindow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeleteWindow") == 0) {
+ stack->correctParams(1);
+ BaseObject *obj = (BaseObject *)stack->pop()->getNative();
+ for (uint32 i = 0; i < _windows.size(); i++) {
+ if (_windows[i] == obj) {
+ unregisterObject(_windows[i]);
+ stack->pushBool(true);
+ return STATUS_OK;
+ }
+ }
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // OpenDocument
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "OpenDocument") == 0) {
+ stack->correctParams(0);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DEBUG_DumpClassRegistry
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DEBUG_DumpClassRegistry") == 0) {
+ stack->correctParams(0);
+ DEBUG_DumpClassRegistry();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetLoadingScreen
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetLoadingScreen") == 0) {
+ stack->correctParams(3);
+ ScValue *val = stack->pop();
+ int loadImageX = stack->pop()->getInt();
+ int loadImageY = stack->pop()->getInt();
+
+ if (val->isNULL()) {
+ _renderer->setLoadingScreen(NULL, loadImageX, loadImageY);
+ } else {
+ _renderer->setLoadingScreen(val->getString(), loadImageX, loadImageY);
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetSavingScreen
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetSavingScreen") == 0) {
+ stack->correctParams(3);
+ ScValue *val = stack->pop();
+ int saveImageX = stack->pop()->getInt();
+ int saveImageY = stack->pop()->getInt();
+
+ if (val->isNULL()) {
+ _renderer->setSaveImage(NULL, saveImageX, saveImageY);
+ } else {
+ _renderer->setSaveImage(NULL, saveImageX, saveImageY);
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetWaitCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetWaitCursor") == 0) {
+ stack->correctParams(1);
+ if (DID_SUCCEED(setWaitCursor(stack->pop()->getString()))) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveWaitCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveWaitCursor") == 0) {
+ stack->correctParams(0);
+ delete _cursorNoninteractive;
+ _cursorNoninteractive = NULL;
+
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetWaitCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetWaitCursor") == 0) {
+ stack->correctParams(0);
+ if (!_cursorNoninteractive || !_cursorNoninteractive->getFilename()) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_cursorNoninteractive->getFilename());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetWaitCursorObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetWaitCursorObject") == 0) {
+ stack->correctParams(0);
+ if (!_cursorNoninteractive) {
+ stack->pushNULL();
+ } else {
+ stack->pushNative(_cursorNoninteractive, true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ClearScriptCache
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ClearScriptCache") == 0) {
+ stack->correctParams(0);
+ stack->pushBool(DID_SUCCEED(_scEngine->emptyScriptCache()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DisplayLoadingIcon
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DisplayLoadingIcon") == 0) {
+ stack->correctParams(4);
+
+ const char *filename = stack->pop()->getString();
+ _loadingIconX = stack->pop()->getInt();
+ _loadingIconY = stack->pop()->getInt();
+ _loadingIconPersistent = stack->pop()->getBool();
+
+ delete _loadingIcon;
+ _loadingIcon = new BaseSprite(this);
+ if (!_loadingIcon || DID_FAIL(_loadingIcon->loadFile(filename))) {
+ delete _loadingIcon;
+ _loadingIcon = NULL;
+ } else {
+ displayContent(false, true);
+ _gameRef->_renderer->flip();
+ _gameRef->_renderer->initLoop();
+ }
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HideLoadingIcon
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HideLoadingIcon") == 0) {
+ stack->correctParams(0);
+ delete _loadingIcon;
+ _loadingIcon = NULL;
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DumpTextureStats
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DumpTextureStats") == 0) {
+ stack->correctParams(1);
+ const char *filename = stack->pop()->getString();
+
+ _renderer->dumpData(filename);
+
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccOutputText
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccOutputText") == 0) {
+ stack->correctParams(2);
+ /* const char *str = */ stack->pop()->getString();
+ /* int type = */ stack->pop()->getInt();
+ // do nothing
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // StoreSaveThumbnail
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "StoreSaveThumbnail") == 0) {
+ stack->correctParams(0);
+ delete _cachedThumbnail;
+ _cachedThumbnail = new BaseSaveThumbHelper(this);
+ if (DID_FAIL(_cachedThumbnail->storeThumbnail())) {
+ delete _cachedThumbnail;
+ _cachedThumbnail = NULL;
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteSaveThumbnail
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeleteSaveThumbnail") == 0) {
+ stack->correctParams(0);
+ delete _cachedThumbnail;
+ _cachedThumbnail = NULL;
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFileChecksum
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetFileChecksum") == 0) {
+ stack->correctParams(2);
+ const char *filename = stack->pop()->getString();
+ bool asHex = stack->pop()->getBool(false);
+
+ Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(filename, false);
+ if (file) {
+ crc remainder = crc_initialize();
+ byte buf[1024];
+ int bytesRead = 0;
+
+ while (bytesRead < file->size()) {
+ int bufSize = MIN((uint32)1024, (uint32)(file->size() - bytesRead));
+ bytesRead += file->read(buf, bufSize);
+
+ for (int i = 0; i < bufSize; i++) {
+ remainder = crc_process_byte(buf[i], remainder);
+ }
+ }
+ crc checksum = crc_finalize(remainder);
+
+ if (asHex) {
+ char hex[100];
+ sprintf(hex, "%x", checksum);
+ stack->pushString(hex);
+ } else {
+ stack->pushInt(checksum);
+ }
+
+ BaseFileManager::getEngineInstance()->closeFile(file);
+ file = NULL;
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EnableScriptProfiling
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EnableScriptProfiling") == 0) {
+ stack->correctParams(0);
+ _scEngine->enableProfiling();
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DisableScriptProfiling
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DisableScriptProfiling") == 0) {
+ stack->correctParams(0);
+ _scEngine->disableProfiling();
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ShowStatusLine
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ShowStatusLine") == 0) {
+ stack->correctParams(0);
+ // Block kept to show intention of opcode.
+ /*#ifdef __IPHONEOS__
+ IOS_ShowStatusLine(TRUE);
+ #endif*/
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HideStatusLine
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HideStatusLine") == 0) {
+ stack->correctParams(0);
+ // Block kept to show intention of opcode.
+ /*#ifdef __IPHONEOS__
+ IOS_ShowStatusLine(FALSE);
+ #endif*/
+ stack->pushNULL();
+
+ return STATUS_OK;
+ } else {
+ return BaseObject::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseGame::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("game");
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Name") == 0) {
+ _scValue->setString(getName());
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Hwnd (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Hwnd") == 0) {
+ _scValue->setInt((int)_renderer->_window);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CurrentTime (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CurrentTime") == 0) {
+ _scValue->setInt((int)_timer);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WindowsTime (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WindowsTime") == 0) {
+ _scValue->setInt((int)g_system->getMillis());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WindowedMode (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WindowedMode") == 0) {
+ _scValue->setBool(_renderer->_windowed);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MouseX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MouseX") == 0) {
+ _scValue->setInt(_mousePos.x);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MouseY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MouseY") == 0) {
+ _scValue->setInt(_mousePos.y);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MainObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MainObject") == 0) {
+ _scValue->setNative(_mainObject, true);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ActiveObject (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ActiveObject") == 0) {
+ _scValue->setNative(_activeObject, true);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScreenWidth (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScreenWidth") == 0) {
+ _scValue->setInt(_renderer->_width);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScreenHeight (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScreenHeight") == 0) {
+ _scValue->setInt(_renderer->_height);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Interactive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Interactive") == 0) {
+ _scValue->setBool(_interactive);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DebugMode (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DebugMode") == 0) {
+ _scValue->setBool(_debugDebugMode);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundAvailable (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundAvailable") == 0) {
+ _scValue->setBool(_soundMgr->_soundAvailable);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SFXVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SFXVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The SFXVolume attribute is obsolete");
+ _scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kSFXSoundType));
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SpeechVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SpeechVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The SpeechVolume attribute is obsolete");
+ _scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kSpeechSoundType));
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MusicVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MusicVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The MusicVolume attribute is obsolete");
+ _scValue->setInt(_soundMgr->getVolumePercent(Audio::Mixer::kMusicSoundType));
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MasterVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MasterVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The MasterVolume attribute is obsolete");
+ _scValue->setInt(_soundMgr->getMasterVolumePercent());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Keyboard (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Keyboard") == 0) {
+ if (_keyboardState) {
+ _scValue->setNative(_keyboardState, true);
+ } else {
+ _scValue->setNULL();
+ }
+
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Subtitles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Subtitles") == 0) {
+ _scValue->setBool(_subtitles);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SubtitlesSpeed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SubtitlesSpeed") == 0) {
+ _scValue->setInt(_subtitlesSpeed);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // VideoSubtitles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VideoSubtitles") == 0) {
+ _scValue->setBool(_videoSubtitles);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FPS (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FPS") == 0) {
+ _scValue->setInt(_fps);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AcceleratedMode / Accelerated (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AcceleratedMode") == 0 || strcmp(name, "Accelerated") == 0) {
+ _scValue->setBool(_useD3D);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextEncoding
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TextEncoding") == 0) {
+ _scValue->setInt(_textEncoding);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextRTL
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TextRTL") == 0) {
+ _scValue->setBool(_textRTL);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundBufferSize
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundBufferSize") == 0) {
+ _scValue->setInt(_soundBufferSizeSec);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SuspendedRendering
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SuspendedRendering") == 0) {
+ _scValue->setBool(_suspendedRendering);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SuppressScriptErrors
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SuppressScriptErrors") == 0) {
+ _scValue->setBool(_suppressScriptErrors);
+ return _scValue;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // Frozen
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Frozen") == 0) {
+ _scValue->setBool(_state == GAME_FROZEN);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccTTSEnabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccTTSEnabled") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccTTSTalk
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccTTSTalk") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccTTSCaptions
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccTTSCaptions") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccTTSKeypress
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccTTSKeypress") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccKeyboardEnabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccKeyboardEnabled") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccKeyboardCursorSkip
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccKeyboardCursorSkip") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccKeyboardPause
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccKeyboardPause") == 0) {
+ _scValue->setBool(false);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutorunDisabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutorunDisabled") == 0) {
+ _scValue->setBool(_autorunDisabled);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SaveDirectory (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SaveDirectory") == 0) {
+ AnsiString dataDir = "saves/"; // TODO: This is just to avoid telling the engine actual paths.
+ _scValue->setString(dataDir.c_str());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutoSaveOnExit
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutoSaveOnExit") == 0) {
+ _scValue->setBool(_autoSaveOnExit);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutoSaveSlot
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutoSaveSlot") == 0) {
+ _scValue->setInt(_autoSaveSlot);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorHidden
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CursorHidden") == 0) {
+ _scValue->setBool(_cursorHidden);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Platform (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Platform") == 0) {
+ _scValue->setString(BasePlatform::getPlatformName().c_str());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeviceType (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeviceType") == 0) {
+ _scValue->setString(getDeviceType().c_str());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MostRecentSaveSlot (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MostRecentSaveSlot") == 0) {
+ if (!ConfMan.hasKey("most_recent_saveslot")) {
+ _scValue->setInt(-1);
+ } else {
+ _scValue->setInt(ConfMan.getInt("most_recent_saveslot"));
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Store (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Store") == 0) {
+ _scValue->setNULL();
+ error("Request for a SXStore-object, which is not supported by ScummVM");
+
+ return _scValue;
+ } else {
+ return BaseObject::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Name") == 0) {
+ setName(value->getString());
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MouseX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MouseX") == 0) {
+ _mousePos.x = value->getInt();
+ resetMousePos();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MouseY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MouseY") == 0) {
+ _mousePos.y = value->getInt();
+ resetMousePos();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Caption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Name") == 0) {
+ bool res = BaseObject::scSetProperty(name, value);
+ setWindowTitle();
+ return res;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MainObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MainObject") == 0) {
+ BaseScriptable *obj = value->getNative();
+ if (obj == NULL || validObject((BaseObject *)obj)) {
+ _mainObject = (BaseObject *)obj;
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Interactive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Interactive") == 0) {
+ setInteractive(value->getBool());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SFXVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SFXVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The SFXVolume attribute is obsolete");
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kSFXSoundType, (byte)value->getInt());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SpeechVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SpeechVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The SpeechVolume attribute is obsolete");
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kSpeechSoundType, (byte)value->getInt());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MusicVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MusicVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The MusicVolume attribute is obsolete");
+ _gameRef->_soundMgr->setVolumePercent(Audio::Mixer::kMusicSoundType, (byte)value->getInt());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MasterVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MasterVolume") == 0) {
+ _gameRef->LOG(0, "**Warning** The MasterVolume attribute is obsolete");
+ _gameRef->_soundMgr->setMasterVolumePercent((byte)value->getInt());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Subtitles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Subtitles") == 0) {
+ _subtitles = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SubtitlesSpeed
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SubtitlesSpeed") == 0) {
+ _subtitlesSpeed = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // VideoSubtitles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VideoSubtitles") == 0) {
+ _videoSubtitles = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextEncoding
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TextEncoding") == 0) {
+ int enc = value->getInt();
+ if (enc < 0) {
+ enc = 0;
+ }
+ if (enc >= NUM_TEXT_ENCODINGS) {
+ enc = NUM_TEXT_ENCODINGS - 1;
+ }
+ _textEncoding = (TTextEncoding)enc;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextRTL
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TextRTL") == 0) {
+ _textRTL = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundBufferSize
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundBufferSize") == 0) {
+ _soundBufferSizeSec = value->getInt();
+ _soundBufferSizeSec = MAX(3, _soundBufferSizeSec);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SuspendedRendering
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SuspendedRendering") == 0) {
+ _suspendedRendering = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SuppressScriptErrors
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SuppressScriptErrors") == 0) {
+ _suppressScriptErrors = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutorunDisabled
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutorunDisabled") == 0) {
+ _autorunDisabled = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutoSaveOnExit
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutoSaveOnExit") == 0) {
+ _autoSaveOnExit = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AutoSaveSlot
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AutoSaveSlot") == 0) {
+ _autoSaveSlot = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CursorHidden
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CursorHidden") == 0) {
+ _cursorHidden = value->getBool();
+ return STATUS_OK;
+ } else {
+ return BaseObject::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseGame::scToString() {
+ return "[game object]";
+}
+
+
+
+#define QUICK_MSG_DURATION 3000
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::displayQuickMsg() {
+ if (_quickMessages.size() == 0 || !_systemFont) {
+ return STATUS_OK;
+ }
+
+ // update
+ for (uint32 i = 0; i < _quickMessages.size(); i++) {
+ if (_currentTime - _quickMessages[i]->_startTime >= QUICK_MSG_DURATION) {
+ delete _quickMessages[i];
+ _quickMessages.remove_at(i);
+ i--;
+ }
+ }
+
+ int posY = 20;
+
+ // display
+ for (uint32 i = 0; i < _quickMessages.size(); i++) {
+ _systemFont->drawText((byte *)_quickMessages[i]->getText(), 0, posY, _renderer->_width);
+ posY += _systemFont->getTextHeight((byte *)_quickMessages[i]->getText(), _renderer->_width);
+ }
+ return STATUS_OK;
+}
+
+
+#define MAX_QUICK_MSG 5
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::quickMessage(const char *text) {
+ if (_quickMessages.size() >= MAX_QUICK_MSG) {
+ delete _quickMessages[0];
+ _quickMessages.remove_at(0);
+ }
+ _quickMessages.add(new BaseQuickMsg(_gameRef, text));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::quickMessageForm(char *fmt, ...) {
+ char buff[256];
+ va_list va;
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ quickMessage(buff);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::registerObject(BaseObject *object) {
+ _regObjects.add(object);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::unregisterObject(BaseObject *object) {
+ if (!object) {
+ return STATUS_OK;
+ }
+
+ // is it a window?
+ for (uint32 i = 0; i < _windows.size(); i++) {
+ if ((BaseObject *)_windows[i] == object) {
+ _windows.remove_at(i);
+
+ // get new focused window
+ if (_focusedWindow == object) {
+ _focusedWindow = NULL;
+ }
+
+ break;
+ }
+ }
+
+ // is it active object?
+ if (_activeObject == object) {
+ _activeObject = NULL;
+ }
+
+ // is it main object?
+ if (_mainObject == object) {
+ _mainObject = NULL;
+ }
+
+ // destroy object
+ for (uint32 i = 0; i < _regObjects.size(); i++) {
+ if (_regObjects[i] == object) {
+ _regObjects.remove_at(i);
+ if (!_loadInProgress) {
+ SystemClassRegistry::getInstance()->enumInstances(invalidateValues, "ScValue", (void *)object);
+ }
+ delete object;
+ return STATUS_OK;
+ }
+ }
+
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::invalidateValues(void *value, void *data) {
+ ScValue *val = (ScValue *)value;
+ if (val->isNative() && val->getNative() == data) {
+ if (!val->_persistent && ((BaseScriptable *)data)->_refCount == 1) {
+ ((BaseScriptable *)data)->_refCount++;
+ }
+ val->setNative(NULL);
+ val->setNULL();
+ }
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::validObject(BaseObject *object) {
+ if (!object) {
+ return false;
+ }
+ if (object == this) {
+ return true;
+ }
+
+ for (uint32 i = 0; i < _regObjects.size(); i++) {
+ if (_regObjects[i] == object) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name) {
+ ScValue *thisObj;
+
+ //////////////////////////////////////////////////////////////////////////
+ // LOG
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "LOG") == 0) {
+ stack->correctParams(1);
+ _gameRef->LOG(0, "sc: %s", stack->pop()->getString());
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // String
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "String") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXString(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MemBuffer
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MemBuffer") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXMemBuffer(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // File
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "File") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXFile(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Date
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Date") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXDate(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Array
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Array") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXArray(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Object
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Object") == 0) {
+ thisObj = thisStack->getTop();
+
+ thisObj->setNative(makeSXObject(_gameRef, stack));
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sleep
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Sleep") == 0) {
+ stack->correctParams(1);
+
+ script->sleep((uint32)stack->pop()->getInt());
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WaitFor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WaitFor") == 0) {
+ stack->correctParams(1);
+
+ BaseScriptable *obj = stack->pop()->getNative();
+ if (validObject((BaseObject *)obj)) {
+ script->waitForExclusive((BaseObject *)obj);
+ }
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Random
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Random") == 0) {
+ stack->correctParams(2);
+
+ int from = stack->pop()->getInt();
+ int to = stack->pop()->getInt();
+
+ stack->pushInt(BaseUtils::randomInt(from, to));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetScriptTimeSlice
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetScriptTimeSlice") == 0) {
+ stack->correctParams(1);
+
+ script->_timeSlice = (uint32)stack->pop()->getInt();
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MakeRGBA / MakeRGB / RGB
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MakeRGBA") == 0 || strcmp(name, "MakeRGB") == 0 || strcmp(name, "RGB") == 0) {
+ stack->correctParams(4);
+ int r = stack->pop()->getInt();
+ int g = stack->pop()->getInt();
+ int b = stack->pop()->getInt();
+ int a;
+ ScValue *val = stack->pop();
+ if (val->isNULL()) {
+ a = 255;
+ } else {
+ a = val->getInt();
+ }
+
+ stack->pushInt(BYTETORGBA(r, g, b, a));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MakeHSL
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MakeHSL") == 0) {
+ stack->correctParams(3);
+ int h = stack->pop()->getInt();
+ int s = stack->pop()->getInt();
+ int l = stack->pop()->getInt();
+
+ stack->pushInt(BaseUtils::HSLtoRGB(h, s, l));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetRValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetRValue") == 0) {
+ stack->correctParams(1);
+
+ uint32 rgba = (uint32)stack->pop()->getInt();
+ stack->pushInt(RGBCOLGetR(rgba));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetGValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetGValue") == 0) {
+ stack->correctParams(1);
+
+ uint32 rgba = (uint32)stack->pop()->getInt();
+ stack->pushInt(RGBCOLGetG(rgba));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetBValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetBValue") == 0) {
+ stack->correctParams(1);
+
+ uint32 rgba = (uint32)stack->pop()->getInt();
+ stack->pushInt(RGBCOLGetB(rgba));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetAValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetAValue") == 0) {
+ stack->correctParams(1);
+
+ uint32 rgba = (uint32)stack->pop()->getInt();
+ stack->pushInt(RGBCOLGetA(rgba));
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetHValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetHValue") == 0) {
+ stack->correctParams(1);
+ uint32 rgb = (uint32)stack->pop()->getInt();
+
+ byte H, S, L;
+ BaseUtils::RGBtoHSL(rgb, &H, &S, &L);
+ stack->pushInt(H);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSValue") == 0) {
+ stack->correctParams(1);
+ uint32 rgb = (uint32)stack->pop()->getInt();
+
+ byte H, S, L;
+ BaseUtils::RGBtoHSL(rgb, &H, &S, &L);
+ stack->pushInt(S);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetLValue
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetLValue") == 0) {
+ stack->correctParams(1);
+ uint32 rgb = (uint32)stack->pop()->getInt();
+
+ byte H, S, L;
+ BaseUtils::RGBtoHSL(rgb, &H, &S, &L);
+ stack->pushInt(L);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Debug
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Debug") == 0) {
+ stack->correctParams(0);
+ stack->pushNULL();
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToString") == 0) {
+ stack->correctParams(1);
+ const char *str = stack->pop()->getString();
+ char *str2 = new char[strlen(str) + 1];
+ strcpy(str2, str);
+ stack->pushString(str2);
+ delete[] str2;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToInt
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToInt") == 0) {
+ stack->correctParams(1);
+ int val = stack->pop()->getInt();
+ stack->pushInt(val);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToFloat
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToFloat") == 0) {
+ stack->correctParams(1);
+ double val = stack->pop()->getFloat();
+ stack->pushFloat(val);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToBool
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToBool") == 0) {
+ stack->correctParams(1);
+ bool val = stack->pop()->getBool();
+ stack->pushBool(val);
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // failure
+ else {
+ script->runtimeError("Call to undefined function '%s'. Ignored.", name);
+ stack->correctParams(0);
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::showCursor() {
+ if (_cursorHidden) {
+ return STATUS_OK;
+ }
+
+ if (!_interactive && _gameRef->_state == GAME_RUNNING) {
+ if (_cursorNoninteractive) {
+ return drawCursor(_cursorNoninteractive);
+ }
+ } else {
+ if (_activeObject && !DID_FAIL(_activeObject->showCursor())) {
+ return STATUS_OK;
+ } else {
+ if (_activeObject && _activeCursor && _activeObject->getExtendedFlag("usable")) {
+ return drawCursor(_activeCursor);
+ } else if (_cursor) {
+ return drawCursor(_cursor);
+ }
+ }
+ }
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::saveGame(int slot, const char *desc, bool quickSave) {
+ return SaveLoad::saveGame(slot, desc, quickSave, _gameRef);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::loadGame(int slot) {
+ //_gameRef->LOG(0, "Load start %d", BaseUtils::GetUsedMemMB());
+
+ _loading = false;
+ _scheduledLoadSlot = -1;
+
+ Common::String filename = SaveLoad::getSaveSlotFilename(slot);
+
+ return loadGame(filename.c_str());
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::loadGame(const char *filename) {
+ return SaveLoad::loadGame(filename, _gameRef);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::displayWindows(bool inGame) {
+ bool res;
+
+ // did we lose focus? focus topmost window
+ if (_focusedWindow == NULL || !_focusedWindow->_visible || _focusedWindow->_disable) {
+ _focusedWindow = NULL;
+ for (int i = _windows.size() - 1; i >= 0; i--) {
+ if (_windows[i]->_visible && !_windows[i]->_disable) {
+ _focusedWindow = _windows[i];
+ break;
+ }
+ }
+ }
+
+ // display all windows
+ for (uint32 i = 0; i < _windows.size(); i++) {
+ if (_windows[i]->_visible && _windows[i]->_inGame == inGame) {
+
+ res = _windows[i]->display();
+ if (DID_FAIL(res)) {
+ return res;
+ }
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::playMusic(int channel, const char *filename, bool looping, uint32 loopStart) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ delete _music[channel];
+ _music[channel] = NULL;
+
+ _music[channel] = new BaseSound(_gameRef);
+ if (_music[channel] && DID_SUCCEED(_music[channel]->setSound(filename, Audio::Mixer::kMusicSoundType, true))) {
+ if (_musicStartTime[channel]) {
+ _music[channel]->setPositionTime(_musicStartTime[channel]);
+ _musicStartTime[channel] = 0;
+ }
+ if (loopStart) {
+ _music[channel]->setLoopStart(loopStart);
+ }
+ return _music[channel]->play(looping);
+ } else {
+ delete _music[channel];
+ _music[channel] = NULL;
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::stopMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ _music[channel]->stop();
+ delete _music[channel];
+ _music[channel] = NULL;
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::pauseMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ return _music[channel]->pause();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::resumeMusic(int channel) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ if (_music[channel]) {
+ return _music[channel]->resume();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::setMusicStartTime(int channel, uint32 time) {
+ if (channel >= NUM_MUSIC_CHANNELS) {
+ _gameRef->LOG(0, "**Error** Attempting to use music channel %d (max num channels: %d)", channel, NUM_MUSIC_CHANNELS);
+ return STATUS_FAILED;
+ }
+
+ _musicStartTime[channel] = time;
+ if (_music[channel] && _music[channel]->isPlaying()) {
+ return _music[channel]->setPositionTime(time);
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::loadSettings(const char *filename) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(SETTINGS)
+ TOKEN_TABLE(GAME)
+ TOKEN_TABLE(STRING_TABLE)
+ TOKEN_TABLE(RESOLUTION)
+ TOKEN_TABLE(REQUIRE_3D_ACCELERATION)
+ TOKEN_TABLE(REQUIRE_SOUND)
+ TOKEN_TABLE(HWTL_MODE)
+ TOKEN_TABLE(ALLOW_WINDOWED_MODE)
+ TOKEN_TABLE(ALLOW_ACCESSIBILITY_TAB)
+ TOKEN_TABLE(ALLOW_ABOUT_TAB)
+ TOKEN_TABLE(ALLOW_ADVANCED)
+ TOKEN_TABLE(ALLOW_DESKTOP_RES)
+ TOKEN_TABLE(REGISTRY_PATH)
+ TOKEN_TABLE(RICH_SAVED_GAMES)
+ TOKEN_TABLE(SAVED_GAME_EXT)
+ TOKEN_TABLE(GUID)
+ TOKEN_TABLE_END
+
+
+ byte *origBuffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (origBuffer == NULL) {
+ _gameRef->LOG(0, "BaseGame::LoadSettings failed for file '%s'", filename);
+ return STATUS_FAILED;
+ }
+
+ bool ret = STATUS_OK;
+
+ byte *buffer = origBuffer;
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SETTINGS) {
+ _gameRef->LOG(0, "'SETTINGS' keyword expected in game settings file.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_GAME:
+ delete[] _settingsGameFile;
+ _settingsGameFile = new char[strlen((char *)params) + 1];
+ if (_settingsGameFile) {
+ strcpy(_settingsGameFile, (char *)params);
+ }
+ break;
+
+ case TOKEN_STRING_TABLE:
+ if (DID_FAIL(_stringTable->loadFile((char *)params))) {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_RESOLUTION:
+ parser.scanStr((char *)params, "%d,%d", &_settingsResWidth, &_settingsResHeight);
+ break;
+
+ case TOKEN_REQUIRE_3D_ACCELERATION:
+ parser.scanStr((char *)params, "%b", &_settingsRequireAcceleration);
+ break;
+
+ case TOKEN_REQUIRE_SOUND:
+ parser.scanStr((char *)params, "%b", &_settingsRequireSound);
+ break;
+
+ case TOKEN_HWTL_MODE:
+ parser.scanStr((char *)params, "%d", &_settingsTLMode);
+ break;
+
+ case TOKEN_ALLOW_WINDOWED_MODE:
+ parser.scanStr((char *)params, "%b", &_settingsAllowWindowed);
+ break;
+
+ case TOKEN_ALLOW_DESKTOP_RES:
+ parser.scanStr((char *)params, "%b", &_settingsAllowDesktopRes);
+ break;
+
+ case TOKEN_ALLOW_ADVANCED:
+ parser.scanStr((char *)params, "%b", &_settingsAllowAdvanced);
+ break;
+
+ case TOKEN_ALLOW_ACCESSIBILITY_TAB:
+ parser.scanStr((char *)params, "%b", &_settingsAllowAccessTab);
+ break;
+
+ case TOKEN_ALLOW_ABOUT_TAB:
+ parser.scanStr((char *)params, "%b", &_settingsAllowAboutTab);
+ break;
+
+ case TOKEN_REGISTRY_PATH:
+ //BaseEngine::instance().getRegistry()->setBasePath((char *)params);
+ break;
+
+ case TOKEN_RICH_SAVED_GAMES:
+ parser.scanStr((char *)params, "%b", &_richSavedGames);
+ break;
+
+ case TOKEN_SAVED_GAME_EXT:
+ BaseUtils::setString(&_savedGameExt, (char *)params);
+ break;
+
+ case TOKEN_GUID:
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in game settings '%s'", filename);
+ ret = STATUS_FAILED;
+ }
+ if (cmd == PARSERR_GENERIC) {
+ _gameRef->LOG(0, "Error loading game settings '%s'", filename);
+ ret = STATUS_FAILED;
+ }
+
+ _settingsAllowWindowed = true; // TODO: These two settings should probably be cleaned out altogether.
+ _compressedSavegames = true;
+
+ delete[] origBuffer;
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::persist(BasePersistenceManager *persistMgr) {
+ if (!persistMgr->getIsSaving()) {
+ cleanup();
+ }
+
+ BaseObject::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_activeObject));
+ persistMgr->transfer(TMEMBER(_capturedObject));
+ persistMgr->transfer(TMEMBER(_cursorNoninteractive));
+ persistMgr->transfer(TMEMBER(_editorMode));
+ persistMgr->transfer(TMEMBER(_fader));
+ persistMgr->transfer(TMEMBER(_freezeLevel));
+ persistMgr->transfer(TMEMBER(_focusedWindow));
+ persistMgr->transfer(TMEMBER(_fontStorage));
+ persistMgr->transfer(TMEMBER(_interactive));
+ persistMgr->transfer(TMEMBER(_keyboardState));
+ persistMgr->transfer(TMEMBER(_lastTime));
+ persistMgr->transfer(TMEMBER(_mainObject));
+ for (int i = 0; i < NUM_MUSIC_CHANNELS; i++) {
+ persistMgr->transfer(TMEMBER(_music[i]));
+ persistMgr->transfer(TMEMBER(_musicStartTime[i]));
+ }
+
+ persistMgr->transfer(TMEMBER(_offsetX));
+ persistMgr->transfer(TMEMBER(_offsetY));
+ persistMgr->transfer(TMEMBER(_offsetPercentX));
+ persistMgr->transfer(TMEMBER(_offsetPercentY));
+
+ persistMgr->transfer(TMEMBER(_origInteractive));
+ persistMgr->transfer(TMEMBER_INT(_origState));
+ persistMgr->transfer(TMEMBER(_personalizedSave));
+ persistMgr->transfer(TMEMBER(_quitting));
+
+ _regObjects.persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_scEngine));
+ //persistMgr->transfer(TMEMBER(_soundMgr));
+ persistMgr->transfer(TMEMBER_INT(_state));
+ //persistMgr->transfer(TMEMBER(_surfaceStorage));
+ persistMgr->transfer(TMEMBER(_subtitles));
+ persistMgr->transfer(TMEMBER(_subtitlesSpeed));
+ persistMgr->transfer(TMEMBER(_systemFont));
+ persistMgr->transfer(TMEMBER(_videoFont));
+ persistMgr->transfer(TMEMBER(_videoSubtitles));
+
+ persistMgr->transfer(TMEMBER(_timer));
+ persistMgr->transfer(TMEMBER(_timerDelta));
+ persistMgr->transfer(TMEMBER(_timerLast));
+
+ persistMgr->transfer(TMEMBER(_liveTimer));
+ persistMgr->transfer(TMEMBER(_liveTimerDelta));
+ persistMgr->transfer(TMEMBER(_liveTimerLast));
+
+ persistMgr->transfer(TMEMBER(_musicCrossfadeRunning));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeStartTime));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeLength));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeChannel1));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeChannel2));
+ persistMgr->transfer(TMEMBER(_musicCrossfadeSwap));
+
+ _renderer->persistSaveLoadImages(persistMgr);
+
+ persistMgr->transfer(TMEMBER_INT(_textEncoding));
+ persistMgr->transfer(TMEMBER(_textRTL));
+
+ persistMgr->transfer(TMEMBER(_soundBufferSizeSec));
+ persistMgr->transfer(TMEMBER(_suspendedRendering));
+
+ persistMgr->transfer(TMEMBER(_mouseLockRect));
+
+ _windows.persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_suppressScriptErrors));
+ persistMgr->transfer(TMEMBER(_autorunDisabled));
+
+ persistMgr->transfer(TMEMBER(_autoSaveOnExit));
+ persistMgr->transfer(TMEMBER(_autoSaveSlot));
+ persistMgr->transfer(TMEMBER(_cursorHidden));
+
+ if (!persistMgr->getIsSaving()) {
+ _quitting = false;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::focusWindow(UIWindow *window) {
+ UIWindow *prev = _focusedWindow;
+
+ for (uint32 i = 0; i < _windows.size(); i++) {
+ if (_windows[i] == window) {
+ if (i < _windows.size() - 1) {
+ _windows.remove_at(i);
+ _windows.add(window);
+
+ _gameRef->_focusedWindow = window;
+ }
+
+ if (window->_mode == WINDOW_NORMAL && prev != window && _gameRef->validObject(prev) && (prev->_mode == WINDOW_EXCLUSIVE || prev->_mode == WINDOW_SYSTEM_EXCLUSIVE)) {
+ return focusWindow(prev);
+ } else {
+ return STATUS_OK;
+ }
+ }
+ }
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::freeze(bool includingMusic) {
+ if (_freezeLevel == 0) {
+ _scEngine->pauseAll();
+ _soundMgr->pauseAll(includingMusic);
+ _origState = _state;
+ _origInteractive = _interactive;
+ _interactive = true;
+ }
+ _state = GAME_FROZEN;
+ _freezeLevel++;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::unfreeze() {
+ if (_freezeLevel == 0) {
+ return STATUS_OK;
+ }
+
+ _freezeLevel--;
+ if (_freezeLevel == 0) {
+ _state = _origState;
+ _interactive = _origInteractive;
+ _scEngine->resumeAll();
+ _soundMgr->resumeAll();
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::handleKeypress(Common::Event *event, bool printable) {
+ if (isVideoPlaying()) {
+ if (event->kbd.keycode == Common::KEYCODE_ESCAPE) {
+ stopVideo();
+ }
+ return true;
+ }
+
+ if (event->type == Common::EVENT_QUIT) {
+ onWindowClose();
+ return true;
+ }
+
+ _keyboardState->handleKeyPress(event);
+ _keyboardState->readKey(event);
+// TODO
+
+ if (_focusedWindow) {
+ if (!_gameRef->_focusedWindow->handleKeypress(event, _keyboardState->_currentPrintable)) {
+ /*if (event->type != SDL_TEXTINPUT) {*/
+ if (_gameRef->_focusedWindow->canHandleEvent("Keypress")) {
+ _gameRef->_focusedWindow->applyEvent("Keypress");
+ } else {
+ applyEvent("Keypress");
+ }
+ /*}*/
+ }
+ return true;
+ } else { /*if (event->type != SDL_TEXTINPUT)*/
+ applyEvent("Keypress");
+ return true;
+ }
+
+ return false;
+}
+
+void BaseGame::handleKeyRelease(Common::Event *event) {
+ _keyboardState->handleKeyRelease(event);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::handleMouseWheel(int delta) {
+ bool handled = false;
+ if (_focusedWindow) {
+ handled = _gameRef->_focusedWindow->handleMouseWheel(delta);
+
+ if (!handled) {
+ if (delta < 0 && _gameRef->_focusedWindow->canHandleEvent("MouseWheelDown")) {
+ _gameRef->_focusedWindow->applyEvent("MouseWheelDown");
+ handled = true;
+ } else if (_gameRef->_focusedWindow->canHandleEvent("MouseWheelUp")) {
+ _gameRef->_focusedWindow->applyEvent("MouseWheelUp");
+ handled = true;
+ }
+
+ }
+ }
+
+ if (!handled) {
+ if (delta < 0) {
+ applyEvent("MouseWheelDown");
+ } else {
+ applyEvent("MouseWheelUp");
+ }
+ }
+
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) {
+ if (verMajor) {
+ *verMajor = DCGF_VER_MAJOR;
+ }
+ if (verMinor) {
+ *verMinor = DCGF_VER_MINOR;
+ }
+
+ if (extMajor) {
+ *extMajor = 0;
+ }
+ if (extMinor) {
+ *extMinor = 0;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::setWindowTitle() {
+ if (_renderer) {
+ char title[512];
+ strcpy(title, _caption[0]);
+ if (title[0] != '\0') {
+ strcat(title, " - ");
+ }
+ strcat(title, "WME Lite");
+
+
+ Utf8String utf8Title;
+ if (_textEncoding == TEXT_UTF8) {
+ utf8Title = Utf8String(title);
+ } else {
+ warning("BaseGame::SetWindowTitle - Ignoring textencoding");
+ utf8Title = Utf8String(title);
+ /* WideString wstr = StringUtil::AnsiToWide(Title);
+ title = StringUtil::WideToUtf8(wstr);*/
+ }
+ warning("BaseGame::SetWindowTitle: Ignoring value: %s", utf8Title.c_str());
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::setActiveObject(BaseObject *obj) {
+ // not-active when game is frozen
+ if (obj && !_gameRef->_interactive && !obj->_nonIntMouseEvents) {
+ obj = NULL;
+ }
+
+ if (obj == _activeObject) {
+ return STATUS_OK;
+ }
+
+ if (_activeObject) {
+ _activeObject->applyEvent("MouseLeave");
+ }
+ //if (ValidObject(_activeObject)) _activeObject->applyEvent("MouseLeave");
+ _activeObject = obj;
+ if (_activeObject) {
+ _activeObject->applyEvent("MouseEntry");
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::pushViewport(BaseViewport *viewport) {
+ _viewportSP++;
+ if (_viewportSP >= (int32)_viewportStack.size()) {
+ _viewportStack.add(viewport);
+ } else {
+ _viewportStack[_viewportSP] = viewport;
+ }
+
+ _renderer->setViewport(viewport->getRect());
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::popViewport() {
+ _viewportSP--;
+ if (_viewportSP < -1) {
+ _gameRef->LOG(0, "Fatal: Viewport stack underflow!");
+ }
+
+ if (_viewportSP >= 0 && _viewportSP < (int32)_viewportStack.size()) {
+ _renderer->setViewport(_viewportStack[_viewportSP]->getRect());
+ } else _renderer->setViewport(_renderer->_drawOffsetX,
+ _renderer->_drawOffsetY,
+ _renderer->_width + _renderer->_drawOffsetX,
+ _renderer->_height + _renderer->_drawOffsetY);
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::getCurrentViewportRect(Rect32 *rect, bool *custom) {
+ if (rect == NULL) {
+ return STATUS_FAILED;
+ } else {
+ if (_viewportSP >= 0) {
+ BasePlatform::copyRect(rect, _viewportStack[_viewportSP]->getRect());
+ if (custom) {
+ *custom = true;
+ }
+ } else {
+ BasePlatform::setRect(rect, _renderer->_drawOffsetX,
+ _renderer->_drawOffsetY,
+ _renderer->_width + _renderer->_drawOffsetX,
+ _renderer->_height + _renderer->_drawOffsetY);
+ if (custom) {
+ *custom = false;
+ }
+ }
+
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::getCurrentViewportOffset(int *offsetX, int *offsetY) {
+ if (_viewportSP >= 0) {
+ if (offsetX) {
+ *offsetX = _viewportStack[_viewportSP]->_offsetX;
+ }
+ if (offsetY) {
+ *offsetY = _viewportStack[_viewportSP]->_offsetY;
+ }
+ } else {
+ if (offsetX) {
+ *offsetX = 0;
+ }
+ if (offsetY) {
+ *offsetY = 0;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::windowLoadHook(UIWindow *win, char **buf, char **params) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::setInteractive(bool state) {
+ _interactive = state;
+ if (_transMgr) {
+ _transMgr->_origInteractive = state;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::resetMousePos() {
+ Common::Point p;
+ p.x = _mousePos.x + _renderer->_drawOffsetX;
+ p.y = _mousePos.y + _renderer->_drawOffsetY;
+
+ BasePlatform::setCursorPos(p.x, p.y);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::displayContent(bool doUpdate, bool displayAll) {
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::displayContentSimple() {
+ // fill black
+ _renderer->fill(0, 0, 0);
+ _renderer->displayIndicator();
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::updateMusicCrossfade() {
+ /* byte globMusicVol = _soundMgr->getVolumePercent(SOUND_MUSIC); */
+
+ if (!_musicCrossfadeRunning) {
+ return STATUS_OK;
+ }
+ if (_state == GAME_FROZEN) {
+ return STATUS_OK;
+ }
+
+ if (_musicCrossfadeChannel1 < 0 || _musicCrossfadeChannel1 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel1]) {
+ _musicCrossfadeRunning = false;
+ return STATUS_OK;
+ }
+ if (_musicCrossfadeChannel2 < 0 || _musicCrossfadeChannel2 >= NUM_MUSIC_CHANNELS || !_music[_musicCrossfadeChannel2]) {
+ _musicCrossfadeRunning = false;
+ return STATUS_OK;
+ }
+
+ if (!_music[_musicCrossfadeChannel1]->isPlaying()) {
+ _music[_musicCrossfadeChannel1]->play();
+ }
+ if (!_music[_musicCrossfadeChannel2]->isPlaying()) {
+ _music[_musicCrossfadeChannel2]->play();
+ }
+
+ uint32 currentTime = _gameRef->_liveTimer - _musicCrossfadeStartTime;
+
+ if (currentTime >= _musicCrossfadeLength) {
+ _musicCrossfadeRunning = false;
+ //_music[_musicCrossfadeChannel2]->setVolume(GlobMusicVol);
+ _music[_musicCrossfadeChannel2]->setVolumePercent(100);
+
+ _music[_musicCrossfadeChannel1]->stop();
+ //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol);
+ _music[_musicCrossfadeChannel1]->setVolumePercent(100);
+
+
+ if (_musicCrossfadeSwap) {
+ // swap channels
+ BaseSound *dummy = _music[_musicCrossfadeChannel1];
+ int dummyInt = _musicStartTime[_musicCrossfadeChannel1];
+
+ _music[_musicCrossfadeChannel1] = _music[_musicCrossfadeChannel2];
+ _musicStartTime[_musicCrossfadeChannel1] = _musicStartTime[_musicCrossfadeChannel2];
+
+ _music[_musicCrossfadeChannel2] = dummy;
+ _musicStartTime[_musicCrossfadeChannel2] = dummyInt;
+ }
+ } else {
+ //_music[_musicCrossfadeChannel1]->setVolume(GlobMusicVol - (float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
+ //_music[_musicCrossfadeChannel2]->setVolume((float)CurrentTime / (float)_musicCrossfadeLength * GlobMusicVol);
+ _music[_musicCrossfadeChannel1]->setVolumePercent((int)(100.0f - (float)currentTime / (float)_musicCrossfadeLength * 100.0f));
+ _music[_musicCrossfadeChannel2]->setVolumePercent((int)((float)currentTime / (float)_musicCrossfadeLength * 100.0f));
+
+ //_gameRef->QuickMessageForm("%d %d", _music[_musicCrossfadeChannel1]->GetVolume(), _music[_musicCrossfadeChannel2]->GetVolume());
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::resetContent() {
+ _scEngine->clearGlobals();
+ //_timer = 0;
+ //_liveTimer = 0;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::DEBUG_DumpClassRegistry() {
+ warning("DEBUG_DumpClassRegistry - untested");
+ Common::DumpFile *f = new Common::DumpFile;
+ f->open("zz_class_reg_dump.log");
+
+ SystemClassRegistry::getInstance()->dumpClasses(f);
+
+ f->close();
+ delete f;
+ _gameRef->quickMessage("Classes dump completed.");
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::invalidateDeviceObjects() {
+ for (uint32 i = 0; i < _regObjects.size(); i++) {
+ _regObjects[i]->invalidateDeviceObjects();
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::restoreDeviceObjects() {
+ for (uint32 i = 0; i < _regObjects.size(); i++) {
+ _regObjects[i]->restoreDeviceObjects();
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::setWaitCursor(const char *filename) {
+ delete _cursorNoninteractive;
+ _cursorNoninteractive = NULL;
+
+ _cursorNoninteractive = new BaseSprite(_gameRef);
+ if (!_cursorNoninteractive || DID_FAIL(_cursorNoninteractive->loadFile(filename))) {
+ delete _cursorNoninteractive;
+ _cursorNoninteractive = NULL;
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::isVideoPlaying() {
+ if (_videoPlayer->isPlaying()) {
+ return true;
+ }
+ if (_theoraPlayer && _theoraPlayer->isPlaying()) {
+ return true;
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::stopVideo() {
+ if (_videoPlayer->isPlaying()) {
+ _videoPlayer->stop();
+ }
+ if (_theoraPlayer && _theoraPlayer->isPlaying()) {
+ _theoraPlayer->stop();
+ delete _theoraPlayer;
+ _theoraPlayer = NULL;
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::drawCursor(BaseSprite *cursor) {
+ if (!cursor) {
+ return STATUS_FAILED;
+ }
+ if (cursor != _lastCursor) {
+ cursor->reset();
+ _lastCursor = cursor;
+ }
+ return cursor->draw(_mousePos.x, _mousePos.y);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onActivate(bool activate, bool refreshMouse) {
+ if (_shuttingDown || !_renderer) {
+ return STATUS_OK;
+ }
+
+ _renderer->_active = activate;
+
+ if (refreshMouse) {
+ Point32 p;
+ getMousePos(&p);
+ setActiveObject(_renderer->getObjectAt(p.x, p.y));
+ }
+
+ if (activate) {
+ _soundMgr->resumeAll();
+ } else {
+ _soundMgr->pauseAll();
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseLeftDown() {
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_CLICK, MOUSE_BUTTON_LEFT);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftClick"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("LeftClick");
+ }
+ }
+
+ if (_activeObject != NULL) {
+ _capturedObject = _activeObject;
+ }
+ _mouseLeftDown = true;
+ BasePlatform::setCapture(/*_renderer->_window*/);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseLeftUp() {
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_LEFT);
+ }
+
+ BasePlatform::releaseCapture();
+ _capturedObject = NULL;
+ _mouseLeftDown = false;
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftRelease"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("LeftRelease");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseLeftDblClick() {
+ if (_state == GAME_RUNNING && !_interactive) {
+ return STATUS_OK;
+ }
+
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_DBLCLICK, MOUSE_BUTTON_LEFT);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("LeftDoubleClick"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("LeftDoubleClick");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseRightDblClick() {
+ if (_state == GAME_RUNNING && !_interactive) {
+ return STATUS_OK;
+ }
+
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_DBLCLICK, MOUSE_BUTTON_RIGHT);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightDoubleClick"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("RightDoubleClick");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseRightDown() {
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_CLICK, MOUSE_BUTTON_RIGHT);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightClick"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("RightClick");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseRightUp() {
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_RIGHT);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("RightRelease"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("RightRelease");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseMiddleDown() {
+ if (_state == GAME_RUNNING && !_interactive) {
+ return STATUS_OK;
+ }
+
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_CLICK, MOUSE_BUTTON_MIDDLE);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("MiddleClick"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("MiddleClick");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onMouseMiddleUp() {
+ if (_activeObject) {
+ _activeObject->handleMouse(MOUSE_RELEASE, MOUSE_BUTTON_MIDDLE);
+ }
+
+ bool handled = _state == GAME_RUNNING && DID_SUCCEED(applyEvent("MiddleRelease"));
+ if (!handled) {
+ if (_activeObject != NULL) {
+ _activeObject->applyEvent("MiddleRelease");
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onPaint() {
+ if (_renderer && _renderer->_windowed && _renderer->_ready) {
+ _renderer->initLoop();
+ displayContent(false, true);
+ displayDebugInfo();
+ _renderer->windowedBlt();
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onWindowClose() {
+ if (canHandleEvent("QuitGame")) {
+ if (_state != GAME_FROZEN) {
+ _gameRef->applyEvent("QuitGame");
+ }
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::displayDebugInfo() {
+ char str[100];
+
+ if (_debugShowFPS) {
+ sprintf(str, "FPS: %d", _gameRef->_fps);
+ _systemFont->drawText((byte *)str, 0, 0, 100, TAL_LEFT);
+ }
+
+ if (_gameRef->_debugDebugMode) {
+ if (!_gameRef->_renderer->_windowed) {
+ sprintf(str, "Mode: %dx%dx%d", _renderer->_width, _renderer->_height, _renderer->_bPP);
+ } else {
+ sprintf(str, "Mode: %dx%d windowed", _renderer->_width, _renderer->_height);
+ }
+
+ strcat(str, " (");
+ strcat(str, _renderer->getName().c_str());
+ strcat(str, ")");
+ _systemFont->drawText((byte *)str, 0, 0, _renderer->_width, TAL_RIGHT);
+
+ _renderer->displayDebugInfo();
+
+ int scrTotal, scrRunning, scrWaiting, scrPersistent;
+ scrTotal = _scEngine->getNumScripts(&scrRunning, &scrWaiting, &scrPersistent);
+ sprintf(str, "Running scripts: %d (r:%d w:%d p:%d)", scrTotal, scrRunning, scrWaiting, scrPersistent);
+ _systemFont->drawText((byte *)str, 0, 70, _renderer->_width, TAL_RIGHT);
+
+
+ sprintf(str, "Timer: %d", _timer);
+ _gameRef->_systemFont->drawText((byte *)str, 0, 130, _renderer->_width, TAL_RIGHT);
+
+ if (_activeObject != NULL) {
+ _systemFont->drawText((const byte *)_activeObject->getName(), 0, 150, _renderer->_width, TAL_RIGHT);
+ }
+
+ sprintf(str, "GfxMem: %dMB", _usedMem / (1024 * 1024));
+ _systemFont->drawText((byte *)str, 0, 170, _renderer->_width, TAL_RIGHT);
+
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::getMousePos(Point32 *pos) {
+ BasePlatform::getCursorPos(pos);
+
+ pos->x -= _renderer->_drawOffsetX;
+ pos->y -= _renderer->_drawOffsetY;
+
+ /*
+ // Windows can squish maximized window if it's larger than desktop
+ // so we need to modify mouse position appropriately (tnx mRax)
+ if (_renderer->_windowed && ::IsZoomed(_renderer->_window)) {
+ Common::Rect rc;
+ ::GetClientRect(_renderer->_window, &rc);
+ Pos->x *= _gameRef->_renderer->_realWidth;
+ Pos->x /= (rc.right - rc.left);
+ Pos->y *= _gameRef->_renderer->_realHeight;
+ Pos->y /= (rc.bottom - rc.top);
+ }
+ */
+
+ if (_mouseLockRect.left != 0 && _mouseLockRect.right != 0 && _mouseLockRect.top != 0 && _mouseLockRect.bottom != 0) {
+ if (!BasePlatform::ptInRect(&_mouseLockRect, *pos)) {
+ pos->x = MAX(_mouseLockRect.left, pos->x);
+ pos->y = MAX(_mouseLockRect.top, pos->y);
+
+ pos->x = MIN(_mouseLockRect.right, pos->x);
+ pos->y = MIN(_mouseLockRect.bottom, pos->y);
+
+ Point32 newPos = *pos;
+
+ newPos.x += _renderer->_drawOffsetX;
+ newPos.y += _renderer->_drawOffsetY;
+
+ BasePlatform::setCursorPos(newPos.x, newPos.y);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::miniUpdate() { // TODO: Is this really necessary, it used to update sound, but the mixer does that now.
+ if (!_miniUpdateEnabled) {
+ return;
+ }
+
+ if (g_system->getMillis() - _lastMiniUpdate > 200) {
+ _lastMiniUpdate = g_system->getMillis();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::onScriptShutdown(ScScript *script) {
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::isLeftDoubleClick() {
+ return isDoubleClick(0);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::isRightDoubleClick() {
+ return isDoubleClick(1);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseGame::isDoubleClick(int buttonIndex) {
+ uint32 maxDoubleCLickTime = 500;
+ int maxMoveX = 4;
+ int maxMoveY = 4;
+
+ Point32 pos;
+ BasePlatform::getCursorPos(&pos);
+
+ int moveX = abs(pos.x - _lastClick[buttonIndex].posX);
+ int moveY = abs(pos.y - _lastClick[buttonIndex].posY);
+
+
+ if (_lastClick[buttonIndex].time == 0 || g_system->getMillis() - _lastClick[buttonIndex].time > maxDoubleCLickTime || moveX > maxMoveX || moveY > maxMoveY) {
+ _lastClick[buttonIndex].time = g_system->getMillis();
+ _lastClick[buttonIndex].posX = pos.x;
+ _lastClick[buttonIndex].posY = pos.y;
+ return false;
+ } else {
+ _lastClick[buttonIndex].time = 0;
+ return true;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::autoSaveOnExit() {
+ _soundMgr->saveSettings();
+ ConfMan.flushToDisk();
+
+ if (!_autoSaveOnExit) {
+ return;
+ }
+ if (_state == GAME_FROZEN) {
+ return;
+ }
+
+ saveGame(_autoSaveSlot, "autosave", true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseGame::addMem(int bytes) {
+ _usedMem += bytes;
+}
+
+//////////////////////////////////////////////////////////////////////////
+AnsiString BaseGame::getDeviceType() const {
+ return "computer";
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_game.h b/engines/wintermute/base/base_game.h
new file mode 100644
index 0000000000..93cbc4536b
--- /dev/null
+++ b/engines/wintermute/base/base_game.h
@@ -0,0 +1,362 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_GAME_H
+#define WINTERMUTE_BASE_GAME_H
+
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/base_object.h"
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/math/rect32.h"
+#include "common/events.h"
+
+namespace Wintermute {
+
+typedef void (*ENGINE_LOG_CALLBACK)(char *text, bool result, void *data);
+
+class BaseSoundMgr;
+class BaseFader;
+class BaseFont;
+class BaseFileManager;
+class BaseTransitionMgr;
+class ScEngine;
+class BaseFontStorage;
+class BaseStringTable;
+class BaseQuickMsg;
+class UIWindow;
+class BaseViewport;
+class BaseRenderer;
+class BaseRegistry;
+class BaseSaveThumbHelper;
+class BaseSurfaceStorage;
+class SXMath;
+class BaseKeyboardState;
+class VideoPlayer;
+class VideoTheoraPlayer;
+
+#define NUM_MUSIC_CHANNELS 5
+
+class BaseGame: public BaseObject {
+public:
+ DECLARE_PERSISTENT(BaseGame, BaseObject)
+
+ virtual bool onScriptShutdown(ScScript *script);
+
+ virtual bool onActivate(bool activate, bool refreshMouse);
+ virtual bool onMouseLeftDown();
+ virtual bool onMouseLeftUp();
+ virtual bool onMouseLeftDblClick();
+ virtual bool onMouseRightDblClick();
+ virtual bool onMouseRightDown();
+ virtual bool onMouseRightUp();
+ virtual bool onMouseMiddleDown();
+ virtual bool onMouseMiddleUp();
+ virtual bool onPaint();
+ virtual bool onWindowClose();
+
+ bool isLeftDoubleClick();
+ bool isRightDoubleClick();
+
+ bool _autorunDisabled;
+
+ uint32 _lastMiniUpdate;
+ bool _miniUpdateEnabled;
+
+ virtual void miniUpdate();
+
+ void getMousePos(Point32 *Pos);
+ Rect32 _mouseLockRect;
+
+ bool _shuttingDown;
+
+ virtual bool displayDebugInfo();
+ bool _debugShowFPS;
+
+ bool _suspendedRendering;
+ int _soundBufferSizeSec;
+
+ TTextEncoding _textEncoding;
+ bool _textRTL;
+
+ virtual bool resetContent();
+
+ void DEBUG_DumpClassRegistry();
+ bool setWaitCursor(const char *filename);
+
+ int _thumbnailWidth;
+ int _thumbnailHeight;
+
+ bool _editorMode;
+ void getOffset(int *offsetX, int *offsetY);
+ void setOffset(int offsetX, int offsetY);
+ int getSequence();
+
+ int _offsetY;
+ int _offsetX;
+ float _offsetPercentX;
+ float _offsetPercentY;
+ BaseObject *_mainObject;
+
+ bool initInput();
+ bool initLoop();
+ uint32 _currentTime;
+ uint32 _deltaTime;
+ BaseFont *_systemFont;
+ BaseFont *_videoFont;
+ bool initialize1();
+ bool initialize2();
+ bool initialize3();
+ BaseTransitionMgr *_transMgr;
+
+ void LOG(bool res, const char *fmt, ...);
+
+ BaseRenderer *_renderer;
+ BaseSoundMgr *_soundMgr;
+ ScEngine *_scEngine;
+ SXMath *_mathClass;
+ BaseSurfaceStorage *_surfaceStorage;
+ BaseFontStorage *_fontStorage;
+ BaseGame(const Common::String &gameId);
+ virtual ~BaseGame();
+
+ void DEBUG_DebugDisable();
+ void DEBUG_DebugEnable(const char *filename = NULL);
+ bool _debugDebugMode;
+
+ void *_debugLogFile;
+ int _sequence;
+ virtual bool loadFile(const char *filename);
+ virtual bool loadBuffer(byte *buffer, bool complete = true);
+
+ int _viewportSP;
+
+ BaseStringTable *_stringTable;
+ int _settingsResWidth;
+ int _settingsResHeight;
+ char *_settingsGameFile;
+ bool _suppressScriptErrors;
+ bool _mouseLeftDown; // TODO: Hide
+
+ virtual bool externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name);
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+ // compatibility bits
+ bool _compatKillMethodThreads;
+
+ const char* getGameId() { return _gameId.c_str(); }
+ void setGameId(const Common::String& gameId) { _gameId = gameId; }
+ uint32 _surfaceGCCycleTime;
+ bool _smartCache; // RO
+ bool _subtitles; // RO
+
+ int _scheduledLoadSlot;
+ bool _loading;
+
+ virtual bool handleMouseWheel(int delta);
+ bool _quitting;
+ virtual bool getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor);
+
+ virtual bool handleKeypress(Common::Event *event, bool printable = false);
+ virtual void handleKeyRelease(Common::Event *event);
+
+ bool unfreeze();
+ bool freeze(bool includingMusic = true);
+ bool focusWindow(UIWindow *window);
+ bool _loadInProgress;
+ UIWindow *_focusedWindow;
+ bool _editorForceScripts;
+
+ static void invalidateValues(void *value, void *data);
+
+ bool loadSettings(const char *filename);
+
+ bool displayWindows(bool inGame = false);
+ bool _useD3D;
+ virtual bool cleanup();
+ bool loadGame(int slot);
+ bool loadGame(const char *filename);
+ bool saveGame(int slot, const char *desc, bool quickSave = false);
+ virtual bool showCursor();
+
+ BaseObject *_activeObject;
+
+ bool _interactive;
+ TGameState _state;
+ TGameState _origState;
+ bool _origInteractive;
+ uint32 _timer;
+ uint32 _timerDelta;
+ uint32 _timerLast;
+
+ uint32 _liveTimer;
+ uint32 _liveTimerDelta;
+ uint32 _liveTimerLast;
+
+ BaseObject *_capturedObject;
+ Point32 _mousePos;
+ bool validObject(BaseObject *object);
+ bool unregisterObject(BaseObject *object);
+ bool registerObject(BaseObject *object);
+ void quickMessage(const char *text);
+ void quickMessageForm(char *fmt, ...);
+ bool displayQuickMsg();
+
+ virtual bool displayContent(bool update = true, bool displayAll = false);
+ virtual bool displayContentSimple();
+ bool _forceNonStreamedSounds;
+ void resetMousePos();
+ int _subtitlesSpeed;
+ void setInteractive(bool state);
+ virtual bool windowLoadHook(UIWindow *win, char **buf, char **params);
+ virtual bool windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name);
+ bool getCurrentViewportOffset(int *offsetX = NULL, int *offsetY = NULL);
+ bool getCurrentViewportRect(Rect32 *rect, bool *custom = NULL);
+ bool popViewport();
+ bool pushViewport(BaseViewport *Viewport);
+ bool setActiveObject(BaseObject *Obj);
+ BaseSprite *_lastCursor;
+ bool drawCursor(BaseSprite *Cursor);
+
+ BaseSaveThumbHelper *_cachedThumbnail;
+ void addMem(int bytes);
+ bool _touchInterface;
+ bool _constrainedMemory;
+protected:
+ BaseSprite *_loadingIcon;
+ int _loadingIconX;
+ int _loadingIconY;
+ int _loadingIconPersistent;
+
+ BaseFader *_fader;
+
+ int _freezeLevel;
+ VideoPlayer *_videoPlayer;
+ VideoTheoraPlayer *_theoraPlayer;
+private:
+ bool _mouseRightDown;
+ bool _mouseMidlleDown;
+ bool _settingsRequireAcceleration;
+ bool _settingsAllowWindowed;
+ bool _settingsAllowAdvanced;
+ bool _settingsAllowAccessTab;
+ bool _settingsAllowAboutTab;
+ bool _settingsRequireSound;
+ bool _settingsAllowDesktopRes;
+ int _settingsTLMode;
+ virtual bool invalidateDeviceObjects();
+ virtual bool restoreDeviceObjects();
+
+ char *_localSaveDir;
+ bool _saveDirChecked;
+ bool _richSavedGames;
+ char *_savedGameExt;
+
+ bool _reportTextureFormat;
+
+ // FPS stuff
+ uint32 _lastTime;
+ uint32 _fpsTime;
+ uint32 _framesRendered;
+ Common::String _gameId;
+
+ void setEngineLogCallback(ENGINE_LOG_CALLBACK callback = NULL, void *data = NULL);
+ ENGINE_LOG_CALLBACK _engineLogCallback;
+ void *_engineLogCallbackData;
+
+ bool _videoSubtitles;
+ uint32 _musicStartTime[NUM_MUSIC_CHANNELS];
+ bool _compressedSavegames;
+
+ bool _personalizedSave;
+
+ void setWindowTitle();
+
+ bool resumeMusic(int channel);
+ bool setMusicStartTime(int channel, uint32 time);
+ bool pauseMusic(int channel);
+ bool stopMusic(int channel);
+ bool playMusic(int channel, const char *filename, bool looping = true, uint32 loopStart = 0);
+ BaseSound *_music[NUM_MUSIC_CHANNELS];
+ bool _musicCrossfadeRunning;
+ bool _musicCrossfadeSwap;
+ uint32 _musicCrossfadeStartTime;
+ uint32 _musicCrossfadeLength;
+ int _musicCrossfadeChannel1;
+ int _musicCrossfadeChannel2;
+
+ BaseSprite *_cursorNoninteractive;
+ BaseKeyboardState *_keyboardState;
+
+ uint32 _fps;
+ bool updateMusicCrossfade();
+
+ bool isVideoPlaying();
+ bool stopVideo();
+
+ BaseArray<BaseQuickMsg *> _quickMessages;
+ BaseArray<UIWindow *> _windows;
+ BaseArray<BaseViewport *> _viewportStack;
+ BaseArray<BaseObject *> _regObjects;
+
+ AnsiString getDeviceType() const;
+
+ struct LastClickInfo {
+ LastClickInfo() {
+ posX = posY = 0;
+ time = 0;
+ }
+
+ int posX;
+ int posY;
+ uint32 time;
+ };
+
+ LastClickInfo _lastClick[2];
+ bool isDoubleClick(int buttonIndex);
+ uint32 _usedMem;
+
+
+
+protected:
+ // WME Lite specific
+ bool _autoSaveOnExit;
+ int _autoSaveSlot;
+ bool _cursorHidden;
+
+public:
+ void autoSaveOnExit();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_keyboard_state.cpp b/engines/wintermute/base/base_keyboard_state.cpp
new file mode 100644
index 0000000000..fd5f2b0e1d
--- /dev/null
+++ b/engines/wintermute/base/base_keyboard_state.cpp
@@ -0,0 +1,309 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_keyboard_state.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "common/system.h"
+#include "common/keyboard.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseKeyboardState, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseKeyboardState::BaseKeyboardState(BaseGame *inGame) : BaseScriptable(inGame) {
+ _currentPrintable = false;
+ _currentCharCode = 0;
+ _currentKeyData = 0;
+
+ _currentShift = false;
+ _currentAlt = false;
+ _currentControl = false;
+
+ _keyStates = new uint8[323]; // Hardcoded size for the common/keyboard.h enum
+ for (int i = 0; i < 323; i++) {
+ _keyStates[i] = false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseKeyboardState::~BaseKeyboardState() {
+ delete[] _keyStates;
+}
+
+void BaseKeyboardState::handleKeyPress(Common::Event *event) {
+ if (event->type == Common::EVENT_KEYDOWN) {
+ _keyStates[event->kbd.keycode] = true;
+ }
+}
+
+void BaseKeyboardState::handleKeyRelease(Common::Event *event) {
+ if (event->type == Common::EVENT_KEYUP) {
+ _keyStates[event->kbd.keycode] = false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // IsKeyDown
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "IsKeyDown") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ int vKey;
+
+ if (val->_type == VAL_STRING && strlen(val->getString()) > 0) {
+ const char *str = val->getString();
+ char temp = str[0];
+ if (temp >= 'A' && temp <= 'Z') {
+ temp += ('a' - 'A');
+ }
+ vKey = (int)temp;
+ } else {
+ vKey = val->getInt();
+ }
+
+ bool isDown = _keyStates[vKeyToKeyCode(vKey)];
+
+ stack->pushBool(isDown);
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseKeyboardState::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("keyboard");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Key
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Key") == 0) {
+ if (_currentPrintable) {
+ char key[2];
+ key[0] = (char)_currentCharCode;
+ key[1] = '\0';
+ _scValue->setString(key);
+ } else {
+ _scValue->setString("");
+ }
+
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Printable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Printable") == 0) {
+ _scValue->setBool(_currentPrintable);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // KeyCode
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "KeyCode") == 0) {
+ _scValue->setInt(_currentCharCode);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsShift
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsShift") == 0) {
+ _scValue->setBool(_currentShift);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsAlt
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsAlt") == 0) {
+ _scValue->setBool(_currentAlt);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsControl
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsControl") == 0) {
+ _scValue->setBool(_currentControl);
+ return _scValue;
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::scSetProperty(const char *name, ScValue *value) {
+ /*
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Name") == 0) {
+ setName(value->getString());
+ if (_renderer) SetWindowText(_renderer->_window, _name);
+ return STATUS_OK;
+ }
+
+ else*/ return BaseScriptable::scSetProperty(name, value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseKeyboardState::scToString() {
+ return "[keyboard state]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::readKey(Common::Event *event) {
+ //_currentPrintable = (event->type == SDL_TEXTINPUT); // TODO
+ _currentCharCode = keyCodeToVKey(event);
+ if ((_currentCharCode <= Common::KEYCODE_z && _currentCharCode >= Common::KEYCODE_a) ||
+ (_currentCharCode <= Common::KEYCODE_9 && _currentCharCode >= Common::KEYCODE_0) ||
+ (_currentCharCode == Common::KEYCODE_SPACE)) {
+ _currentPrintable = true;
+ } else {
+ _currentPrintable = false;
+ }
+ //_currentKeyData = KeyData;
+
+ _currentControl = isControlDown();
+ _currentAlt = isAltDown();
+ _currentShift = isShiftDown();
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::persist(BasePersistenceManager *persistMgr) {
+ //if (!persistMgr->getIsSaving()) cleanup();
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_currentAlt));
+ persistMgr->transfer(TMEMBER(_currentCharCode));
+ persistMgr->transfer(TMEMBER(_currentControl));
+ persistMgr->transfer(TMEMBER(_currentKeyData));
+ persistMgr->transfer(TMEMBER(_currentPrintable));
+ persistMgr->transfer(TMEMBER(_currentShift));
+
+ if (!persistMgr->getIsSaving()) {
+ _keyStates = new uint8[323]; // Hardcoded size for the common/keyboard.h enum
+ for (int i = 0; i < 323; i++) {
+ _keyStates[i] = false;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::isShiftDown() {
+ int mod = g_system->getEventManager()->getModifierState();
+ return (mod & Common::KBD_SHIFT);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::isControlDown() {
+ int mod = g_system->getEventManager()->getModifierState();
+ return (mod & Common::KBD_CTRL);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseKeyboardState::isAltDown() {
+ int mod = g_system->getEventManager()->getModifierState();
+ return (mod & Common::KBD_ALT);
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseKeyboardState::keyCodeToVKey(Common::Event *event) {
+ if (event->type != Common::EVENT_KEYDOWN) {
+ return 0;
+ }
+
+ switch (event->kbd.keycode) {
+ case Common::KEYCODE_KP_ENTER:
+ return Common::KEYCODE_RETURN;
+ default:
+ return (uint32)event->kbd.keycode;
+ }
+}
+
+enum VKeyCodes {
+ kVkSpace = 32,
+ kVkLeft = 37,
+ kVkUp = 38,
+ kVkRight = 39,
+ kVkDown = 40
+};
+
+//////////////////////////////////////////////////////////////////////////
+Common::KeyCode BaseKeyboardState::vKeyToKeyCode(uint32 vkey) {
+ // todo
+ switch (vkey) {
+ case kVkSpace:
+ return Common::KEYCODE_SPACE;
+ break;
+ case kVkLeft:
+ return Common::KEYCODE_LEFT;
+ break;
+ case kVkRight:
+ return Common::KEYCODE_RIGHT;
+ break;
+ case kVkUp:
+ return Common::KEYCODE_UP;
+ break;
+ case kVkDown:
+ return Common::KEYCODE_DOWN;
+ break;
+ default:
+ warning("Unknown VKEY: %d", vkey);
+ return (Common::KeyCode)vkey;
+ break;
+ }
+
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_keyboard_state.h b/engines/wintermute/base/base_keyboard_state.h
new file mode 100644
index 0000000000..ebc0c83ee1
--- /dev/null
+++ b/engines/wintermute/base/base_keyboard_state.h
@@ -0,0 +1,75 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_KEYBOARD_STATE_H
+#define WINTERMUTE_BASE_KEYBOARD_STATE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/base/base_scriptable.h"
+#include "common/keyboard.h"
+#include "common/events.h"
+
+namespace Wintermute {
+
+class BaseKeyboardState : public BaseScriptable {
+public:
+ uint32 _currentKeyData;
+ uint32 _currentCharCode;
+ bool _currentPrintable;
+
+ bool _currentShift;
+ bool _currentAlt;
+ bool _currentControl;
+
+ DECLARE_PERSISTENT(BaseKeyboardState, BaseScriptable)
+ BaseKeyboardState(BaseGame *inGame);
+ virtual ~BaseKeyboardState();
+ bool readKey(Common::Event *event);
+
+ void handleKeyPress(Common::Event *event);
+ void handleKeyRelease(Common::Event *event);
+ static bool isShiftDown();
+ static bool isControlDown();
+ static bool isAltDown();
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+
+private:
+ uint8 *_keyStates;
+ uint32 keyCodeToVKey(Common::Event *event);
+ Common::KeyCode vKeyToKeyCode(uint32 vkey); //TODO, reimplement using ScummVM-backend
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_named_object.cpp b/engines/wintermute/base/base_named_object.cpp
new file mode 100644
index 0000000000..915bf24d7f
--- /dev/null
+++ b/engines/wintermute/base/base_named_object.cpp
@@ -0,0 +1,71 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_named_object.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseNamedObject::BaseNamedObject(BaseGame *inGame) : BaseClass(inGame) {
+ _name = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseNamedObject::BaseNamedObject() : BaseClass() {
+ _name = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseNamedObject::BaseNamedObject(TDynamicConstructor, TDynamicConstructor) {
+ _name = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseNamedObject::~BaseNamedObject(void) {
+ delete[] _name;
+ _name = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseNamedObject::setName(const char *name) {
+ delete[] _name;
+ _name = NULL;
+
+ if (name == NULL) {
+ return;
+ }
+
+ _name = new char [strlen(name) + 1];
+ if (_name != NULL) {
+ strcpy(_name, name);
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_named_object.h b/engines/wintermute/base/base_named_object.h
new file mode 100644
index 0000000000..77a00cee45
--- /dev/null
+++ b/engines/wintermute/base/base_named_object.h
@@ -0,0 +1,51 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_NAMED_OBJECT_H
+#define WINTERMUTE_BASE_NAMED_OBJECT_H
+
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseNamedObject : public BaseClass {
+ char *_name;
+public:
+ BaseNamedObject(BaseGame *inGame);
+ BaseNamedObject();
+ virtual ~BaseNamedObject(void);
+ BaseNamedObject(TDynamicConstructor, TDynamicConstructor);
+
+ const char *getName() { return _name; }
+ void setName(const char *name);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_object.cpp b/engines/wintermute/base/base_object.cpp
new file mode 100644
index 0000000000..b6a6887624
--- /dev/null
+++ b/engines/wintermute/base/base_object.cpp
@@ -0,0 +1,1246 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_object.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_string_table.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/platform_osystem.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseObject, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseObject::BaseObject(BaseGame *inGame) : BaseScriptHolder(inGame) {
+ _posX = _posY = 0;
+ _movable = true;
+ _zoomable = true;
+ _registrable = true;
+ _shadowable = true;
+ _rotatable = false;
+ _is3D = false;
+
+ _alphaColor = 0;
+ _scale = -1;
+ _relativeScale = 0;
+
+ _scaleX = -1;
+ _scaleY = -1;
+
+ _ready = true;
+
+ _soundEvent = NULL;
+
+ _iD = _gameRef->getSequence();
+
+ BasePlatform::setRectEmpty(&_rect);
+ _rectSet = false;
+
+ _cursor = NULL;
+ _activeCursor = NULL;
+ _sharedCursors = false;
+
+ _sFX = NULL;
+ _sFXStart = 0;
+ _sFXVolume = 100;
+ _autoSoundPanning = true;
+
+ _editorAlwaysRegister = false;
+ _editorSelected = false;
+
+ _editorOnly = false;
+
+ _rotate = 0.0f;
+ _rotateValid = false;
+ _relativeRotate = 0.0f;
+
+ for (int i = 0; i < 7; i++) {
+ _caption[i] = NULL;
+ }
+ _saveState = true;
+
+ _nonIntMouseEvents = false;
+
+ // sound FX
+ _sFXType = SFX_NONE;
+ _sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0;
+
+ _blendMode = BLEND_NORMAL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseObject::~BaseObject() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::cleanup() {
+ if (_gameRef && _gameRef->_activeObject == this) {
+ _gameRef->_activeObject = NULL;
+ }
+
+ BaseScriptHolder::cleanup();
+ delete[] _soundEvent;
+ _soundEvent = NULL;
+
+ if (!_sharedCursors) {
+ delete _cursor;
+ delete _activeCursor;
+ _cursor = NULL;
+ _activeCursor = NULL;
+ }
+ delete _sFX;
+ _sFX = NULL;
+
+ for (int i = 0; i < 7; i++) {
+ delete[] _caption[i];
+ _caption[i] = NULL;
+ }
+
+ _sFXType = SFX_NONE;
+ _sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseObject::setCaption(const char *caption, int caseVal) {
+ if (caseVal == 0) {
+ caseVal = 1;
+ }
+ if (caseVal < 1 || caseVal > 7) {
+ return;
+ }
+
+ delete[] _caption[caseVal - 1];
+ _caption[caseVal - 1] = new char[strlen(caption) + 1];
+ if (_caption[caseVal - 1]) {
+ strcpy(_caption[caseVal - 1], caption);
+ _gameRef->_stringTable->expand(&_caption[caseVal - 1]);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseObject::getCaption(int caseVal) {
+ if (caseVal == 0) {
+ caseVal = 1;
+ }
+ if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) {
+ return "";
+ } else {
+ return _caption[caseVal - 1];
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::listen(BaseScriptHolder *param1, uint32 param2) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+
+ //////////////////////////////////////////////////////////////////////////
+ // SkipTo
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SkipTo") == 0) {
+ stack->correctParams(2);
+ _posX = stack->pop()->getInt();
+ _posY = stack->pop()->getInt();
+ afterMove();
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Caption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Caption") == 0) {
+ stack->correctParams(1);
+ stack->pushString(getCaption(stack->pop()->getInt()));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetCursor") == 0) {
+ stack->correctParams(1);
+ if (DID_SUCCEED(setCursor(stack->pop()->getString()))) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveCursor") == 0) {
+ stack->correctParams(0);
+ if (!_sharedCursors) {
+ delete _cursor;
+ _cursor = NULL;
+ } else {
+ _cursor = NULL;
+
+ }
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetCursor") == 0) {
+ stack->correctParams(0);
+ if (!_cursor || !_cursor->getFilename()) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_cursor->getFilename());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetCursorObject
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetCursorObject") == 0) {
+ stack->correctParams(0);
+ if (!_cursor) {
+ stack->pushNULL();
+ } else {
+ stack->pushNative(_cursor, true);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HasCursor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HasCursor") == 0) {
+ stack->correctParams(0);
+
+ if (_cursor) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetCaption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetCaption") == 0) {
+ stack->correctParams(2);
+ setCaption(stack->pop()->getString(), stack->pop()->getInt());
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LoadSound
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LoadSound") == 0) {
+ stack->correctParams(1);
+ const char *filename = stack->pop()->getString();
+ if (DID_SUCCEED(playSFX(filename, false, false))) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PlaySound
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PlaySound") == 0) {
+ stack->correctParams(3);
+
+ const char *filename;
+ bool looping;
+ uint32 loopStart;
+
+ ScValue *val1 = stack->pop();
+ ScValue *val2 = stack->pop();
+ ScValue *val3 = stack->pop();
+
+ if (val1->_type == VAL_BOOL) {
+ filename = NULL;
+ looping = val1->getBool();
+ loopStart = val2->getInt();
+ } else {
+ if (val1->isNULL()) {
+ filename = NULL;
+ } else {
+ filename = val1->getString();
+ }
+ looping = val2->isNULL() ? false : val2->getBool();
+ loopStart = val3->getInt();
+ }
+
+ if (DID_FAIL(playSFX(filename, looping, true, NULL, loopStart))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PlaySoundEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PlaySoundEvent") == 0) {
+ stack->correctParams(2);
+
+ const char *filename;
+ const char *eventName;
+
+ ScValue *val1 = stack->pop();
+ ScValue *val2 = stack->pop();
+
+ if (val2->isNULL()) {
+ filename = NULL;
+ eventName = val1->getString();
+ } else {
+ filename = val1->getString();
+ eventName = val2->getString();
+ }
+
+ if (DID_FAIL(playSFX(filename, false, true, eventName))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // StopSound
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "StopSound") == 0) {
+ stack->correctParams(0);
+
+ if (DID_FAIL(stopSFX())) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PauseSound
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PauseSound") == 0) {
+ stack->correctParams(0);
+
+ if (DID_FAIL(pauseSFX())) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ResumeSound
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ResumeSound") == 0) {
+ stack->correctParams(0);
+
+ if (DID_FAIL(resumeSFX())) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsSoundPlaying
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsSoundPlaying") == 0) {
+ stack->correctParams(0);
+
+ if (_sFX && _sFX->isPlaying()) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetSoundPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetSoundPosition") == 0) {
+ stack->correctParams(1);
+
+ uint32 time = stack->pop()->getInt();
+ if (DID_FAIL(setSFXTime(time))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSoundPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSoundPosition") == 0) {
+ stack->correctParams(0);
+
+ if (!_sFX) {
+ stack->pushInt(0);
+ } else {
+ stack->pushInt(_sFX->getPositionTime());
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetSoundVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetSoundVolume") == 0) {
+ stack->correctParams(1);
+
+ int volume = stack->pop()->getInt();
+ if (DID_FAIL(setSFXVolume(volume))) {
+ stack->pushBool(false);
+ } else {
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetSoundVolume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSoundVolume") == 0) {
+ stack->correctParams(0);
+
+ if (!_sFX) {
+ stack->pushInt(_sFXVolume);
+ } else {
+ stack->pushInt(_sFX->getVolumePercent());
+ }
+ return STATUS_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundFXNone
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundFXNone") == 0) {
+ stack->correctParams(0);
+ _sFXType = SFX_NONE;
+ _sFXParam1 = 0;
+ _sFXParam2 = 0;
+ _sFXParam3 = 0;
+ _sFXParam4 = 0;
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundFXEcho
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundFXEcho") == 0) {
+ stack->correctParams(4);
+ _sFXType = SFX_ECHO;
+ _sFXParam1 = (float)stack->pop()->getFloat(0); // Wet/Dry Mix [%] (0-100)
+ _sFXParam2 = (float)stack->pop()->getFloat(0); // Feedback [%] (0-100)
+ _sFXParam3 = (float)stack->pop()->getFloat(333.0f); // Left Delay [ms] (1-2000)
+ _sFXParam4 = (float)stack->pop()->getFloat(333.0f); // Right Delay [ms] (1-2000)
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundFXReverb
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundFXReverb") == 0) {
+ stack->correctParams(4);
+ _sFXType = SFX_REVERB;
+ _sFXParam1 = (float)stack->pop()->getFloat(0); // In Gain [dB] (-96 - 0)
+ _sFXParam2 = (float)stack->pop()->getFloat(0); // Reverb Mix [dB] (-96 - 0)
+ _sFXParam3 = (float)stack->pop()->getFloat(1000.0f); // Reverb Time [ms] (0.001 - 3000)
+ _sFXParam4 = (float)stack->pop()->getFloat(0.001f); // HighFreq RT Ratio (0.001 - 0.999)
+ stack->pushNULL();
+
+ return STATUS_OK;
+ } else {
+ return BaseScriptHolder::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseObject::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("object");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Caption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Caption") == 0) {
+ _scValue->setString(getCaption(1));
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "X") == 0) {
+ _scValue->setInt(_posX);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _scValue->setInt(_posY);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Height (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Height") == 0) {
+ _scValue->setInt(getHeight());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Ready (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Ready") == 0) {
+ _scValue->setBool(_ready);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Movable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Movable") == 0) {
+ _scValue->setBool(_movable);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Registrable/Interactive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Registrable") == 0 || strcmp(name, "Interactive") == 0) {
+ _scValue->setBool(_registrable);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Zoomable/Scalable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Zoomable") == 0 || strcmp(name, "Scalable") == 0) {
+ _scValue->setBool(_zoomable);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Rotatable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotatable") == 0) {
+ _scValue->setBool(_rotatable);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaColor") == 0) {
+ _scValue->setInt((int)_alphaColor);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // BlendMode
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "BlendMode") == 0) {
+ _scValue->setInt((int)_blendMode);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale") == 0) {
+ if (_scale < 0) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setFloat((double)_scale);
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleX") == 0) {
+ if (_scaleX < 0) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setFloat((double)_scaleX);
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleY") == 0) {
+ if (_scaleY < 0) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setFloat((double)_scaleY);
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RelativeScale
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RelativeScale") == 0) {
+ _scValue->setFloat((double)_relativeScale);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotate") == 0) {
+ if (!_rotateValid) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setFloat((double)_rotate);
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RelativeRotate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RelativeRotate") == 0) {
+ _scValue->setFloat((double)_relativeRotate);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Colorable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Colorable") == 0) {
+ _scValue->setBool(_shadowable);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SoundPanning
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundPanning") == 0) {
+ _scValue->setBool(_autoSoundPanning);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SaveState
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SaveState") == 0) {
+ _scValue->setBool(_saveState);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NonIntMouseEvents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NonIntMouseEvents") == 0) {
+ _scValue->setBool(_nonIntMouseEvents);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccCaption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccCaption") == 0) {
+ _scValue->setNULL();
+ return _scValue;
+ } else {
+ return BaseScriptHolder::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Caption
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Caption") == 0) {
+ setCaption(value->getString());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "X") == 0) {
+ _posX = value->getInt();
+ afterMove();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _posY = value->getInt();
+ afterMove();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Movable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Movable") == 0) {
+ _movable = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Registrable/Interactive
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Registrable") == 0 || strcmp(name, "Interactive") == 0) {
+ _registrable = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Zoomable/Scalable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Zoomable") == 0 || strcmp(name, "Scalable") == 0) {
+ _zoomable = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotatable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotatable") == 0) {
+ _rotatable = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaColor") == 0) {
+ _alphaColor = (uint32)value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // BlendMode
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "BlendMode") == 0) {
+ int i = value->getInt();
+ if (i < BLEND_NORMAL || i >= NUM_BLEND_MODES) {
+ i = BLEND_NORMAL;
+ }
+ _blendMode = (TSpriteBlendMode)i;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale") == 0) {
+ if (value->isNULL()) {
+ _scale = -1;
+ } else {
+ _scale = (float)value->getFloat();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleX") == 0) {
+ if (value->isNULL()) {
+ _scaleX = -1;
+ } else {
+ _scaleX = (float)value->getFloat();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleY") == 0) {
+ if (value->isNULL()) {
+ _scaleY = -1;
+ } else {
+ _scaleY = (float)value->getFloat();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RelativeScale
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RelativeScale") == 0) {
+ _relativeScale = (float)value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotate") == 0) {
+ if (value->isNULL()) {
+ _rotate = 0.0f;
+ _rotateValid = false;
+ } else {
+ _rotate = (float)value->getFloat();
+ _rotateValid = true;
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RelativeRotate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RelativeRotate") == 0) {
+ _relativeRotate = (float)value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Colorable
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Colorable") == 0) {
+ _shadowable = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SoundPanning
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SoundPanning") == 0) {
+ _autoSoundPanning = value->getBool();
+ if (!_autoSoundPanning) {
+ resetSoundPan();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SaveState
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SaveState") == 0) {
+ _saveState = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NonIntMouseEvents
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NonIntMouseEvents") == 0) {
+ _nonIntMouseEvents = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccCaption
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccCaption") == 0) {
+ return STATUS_OK;
+ } else {
+ return BaseScriptHolder::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseObject::scToString() {
+ return "[object]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::showCursor() {
+ if (_cursor) {
+ return _gameRef->drawCursor(_cursor);
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::persist(BasePersistenceManager *persistMgr) {
+ BaseScriptHolder::persist(persistMgr);
+
+ for (int i = 0; i < 7; i++) {
+ persistMgr->transfer(TMEMBER(_caption[i]));
+ }
+ persistMgr->transfer(TMEMBER(_activeCursor));
+ persistMgr->transfer(TMEMBER(_alphaColor));
+ persistMgr->transfer(TMEMBER(_autoSoundPanning));
+ persistMgr->transfer(TMEMBER(_cursor));
+ persistMgr->transfer(TMEMBER(_sharedCursors));
+ persistMgr->transfer(TMEMBER(_editorAlwaysRegister));
+ persistMgr->transfer(TMEMBER(_editorOnly));
+ persistMgr->transfer(TMEMBER(_editorSelected));
+ persistMgr->transfer(TMEMBER(_iD));
+ persistMgr->transfer(TMEMBER(_is3D));
+ persistMgr->transfer(TMEMBER(_movable));
+ persistMgr->transfer(TMEMBER(_posX));
+ persistMgr->transfer(TMEMBER(_posY));
+ persistMgr->transfer(TMEMBER(_relativeScale));
+ persistMgr->transfer(TMEMBER(_rotatable));
+ persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transfer(TMEMBER(_sFX));
+ persistMgr->transfer(TMEMBER(_sFXStart));
+ persistMgr->transfer(TMEMBER(_sFXVolume));
+ persistMgr->transfer(TMEMBER(_ready));
+ persistMgr->transfer(TMEMBER(_rect));
+ persistMgr->transfer(TMEMBER(_rectSet));
+ persistMgr->transfer(TMEMBER(_registrable));
+ persistMgr->transfer(TMEMBER(_shadowable));
+ persistMgr->transfer(TMEMBER(_soundEvent));
+ persistMgr->transfer(TMEMBER(_zoomable));
+
+ persistMgr->transfer(TMEMBER(_scaleX));
+ persistMgr->transfer(TMEMBER(_scaleY));
+
+ persistMgr->transfer(TMEMBER(_rotate));
+ persistMgr->transfer(TMEMBER(_rotateValid));
+ persistMgr->transfer(TMEMBER(_relativeRotate));
+
+ persistMgr->transfer(TMEMBER(_saveState));
+ persistMgr->transfer(TMEMBER(_nonIntMouseEvents));
+
+ persistMgr->transfer(TMEMBER_INT(_sFXType));
+ persistMgr->transfer(TMEMBER(_sFXParam1));
+ persistMgr->transfer(TMEMBER(_sFXParam2));
+ persistMgr->transfer(TMEMBER(_sFXParam3));
+ persistMgr->transfer(TMEMBER(_sFXParam4));
+
+
+ persistMgr->transfer(TMEMBER_INT(_blendMode));
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::setCursor(const char *filename) {
+ if (!_sharedCursors) {
+ delete _cursor;
+ _cursor = NULL;
+ }
+
+ _sharedCursors = false;
+ _cursor = new BaseSprite(_gameRef);
+ if (!_cursor || DID_FAIL(_cursor->loadFile(filename))) {
+ delete _cursor;
+ _cursor = NULL;
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::setActiveCursor(const char *filename) {
+ delete _activeCursor;
+ _activeCursor = new BaseSprite(_gameRef);
+ if (!_activeCursor || DID_FAIL(_activeCursor->loadFile(filename))) {
+ delete _activeCursor;
+ _activeCursor = NULL;
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseObject::getHeight() {
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::handleMouse(TMouseEvent event, TMouseButton button) {
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::handleKeypress(Common::Event *event, bool printable) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::handleMouseWheel(int delta) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::playSFX(const char *filename, bool looping, bool playNow, const char *eventName, uint32 loopStart) {
+ // just play loaded sound
+ if (filename == NULL && _sFX) {
+ if (_gameRef->_editorMode || _sFXStart) {
+ _sFX->setVolumePercent(_sFXVolume);
+ _sFX->setPositionTime(_sFXStart);
+ if (!_gameRef->_editorMode) {
+ _sFXStart = 0;
+ }
+ }
+ if (playNow) {
+ setSoundEvent(eventName);
+ if (loopStart) {
+ _sFX->setLoopStart(loopStart);
+ }
+ return _sFX->play(looping);
+ } else {
+ return STATUS_OK;
+ }
+ }
+
+ if (filename == NULL) {
+ return STATUS_FAILED;
+ }
+
+ // create new sound
+ delete _sFX;
+
+ _sFX = new BaseSound(_gameRef);
+ if (_sFX && DID_SUCCEED(_sFX->setSound(filename, Audio::Mixer::kSFXSoundType, true))) {
+ _sFX->setVolumePercent(_sFXVolume);
+ if (_sFXStart) {
+ _sFX->setPositionTime(_sFXStart);
+ _sFXStart = 0;
+ }
+ _sFX->applyFX(_sFXType, _sFXParam1, _sFXParam2, _sFXParam3, _sFXParam4);
+ if (playNow) {
+ setSoundEvent(eventName);
+ if (loopStart) {
+ _sFX->setLoopStart(loopStart);
+ }
+ return _sFX->play(looping);
+ } else {
+ return STATUS_OK;
+ }
+ } else {
+ delete _sFX;
+ _sFX = NULL;
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::stopSFX(bool deleteSound) {
+ if (_sFX) {
+ _sFX->stop();
+ if (deleteSound) {
+ delete _sFX;
+ _sFX = NULL;
+ }
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::pauseSFX() {
+ if (_sFX) {
+ return _sFX->pause();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::resumeSFX() {
+ if (_sFX) {
+ return _sFX->resume();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::setSFXTime(uint32 time) {
+ _sFXStart = time;
+ if (_sFX && _sFX->isPlaying()) {
+ return _sFX->setPositionTime(time);
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::setSFXVolume(int volume) {
+ _sFXVolume = volume;
+ if (_sFX) {
+ return _sFX->setVolumePercent(volume);
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::updateSounds() {
+ if (_soundEvent) {
+ if (_sFX && !_sFX->isPlaying()) {
+ applyEvent(_soundEvent);
+ setSoundEvent(NULL);
+ }
+ }
+
+ if (_sFX) {
+ updateOneSound(_sFX);
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::updateOneSound(BaseSound *sound) {
+ bool ret = STATUS_OK;
+
+ if (sound) {
+ if (_autoSoundPanning) {
+ ret = sound->setPan(_gameRef->_soundMgr->posToPan(_posX - _gameRef->_offsetX, _posY - _gameRef->_offsetY));
+ }
+
+ ret = sound->applyFX(_sFXType, _sFXParam1, _sFXParam2, _sFXParam3, _sFXParam4);
+ }
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::resetSoundPan() {
+ if (!_sFX) {
+ return STATUS_OK;
+ } else {
+ return _sFX->setPan(0.0f);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::getExtendedFlag(const char *flagName) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::isReady() {
+ return _ready;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseObject::setSoundEvent(const char *eventName) {
+ delete[] _soundEvent;
+ _soundEvent = NULL;
+ if (eventName) {
+ _soundEvent = new char[strlen(eventName) + 1];
+ if (_soundEvent) {
+ strcpy(_soundEvent, eventName);
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseObject::afterMove() {
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_object.h b/engines/wintermute/base/base_object.h
new file mode 100644
index 0000000000..34adbdb585
--- /dev/null
+++ b/engines/wintermute/base/base_object.h
@@ -0,0 +1,147 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_OBJECT_H
+#define WINTERMUTE_BASE_OBJECT_H
+
+
+#include "engines/wintermute/base/base_script_holder.h"
+#include "engines/wintermute/persistent.h"
+#include "common/events.h"
+
+namespace Wintermute {
+
+class BaseSprite;
+class BaseSound;
+class BaseSurface;
+class BaseScriptHolder;
+class ScValue;
+class ScStack;
+class ScScript;
+class BaseObject : public BaseScriptHolder {
+protected:
+ bool _autoSoundPanning;
+ uint32 _sFXStart;
+ bool setSFXTime(uint32 time);
+ bool setSFXVolume(int volume);
+ bool resumeSFX();
+ bool pauseSFX();
+ bool stopSFX(bool deleteSound = true);
+ bool playSFX(const char *filename, bool looping = false, bool playNow = true, const char *eventName = NULL, uint32 loopStart = 0);
+ BaseSound *_sFX;
+ TSFXType _sFXType;
+ float _sFXParam1;
+ float _sFXParam2;
+ float _sFXParam3;
+ float _sFXParam4;
+ float _relativeRotate;
+ bool _rotateValid;
+ float _rotate;
+ void setSoundEvent(const char *eventName);
+ bool _rotatable;
+ float _scaleX;
+ float _scaleY;
+ float _relativeScale;
+ bool _editorSelected;
+ bool _editorAlwaysRegister;
+ bool _ready;
+ Rect32 _rect;
+ bool _rectSet;
+ int _iD;
+ char *_soundEvent;
+public:
+ TSpriteBlendMode _blendMode;
+ virtual bool afterMove();
+ float _scale;
+ uint32 _alphaColor;
+ virtual bool isReady();
+ virtual bool getExtendedFlag(const char *flagName);
+ virtual bool resetSoundPan();
+ virtual bool updateSounds();
+ bool updateOneSound(BaseSound *sound);
+ int _sFXVolume;
+
+ virtual bool handleMouseWheel(int delta);
+ virtual bool handleMouse(TMouseEvent event, TMouseButton button);
+ virtual bool handleKeypress(Common::Event *event, bool printable = false);
+ virtual int getHeight();
+ bool setCursor(const char *filename);
+ bool setActiveCursor(const char *filename);
+ bool cleanup();
+ const char *getCaption(int caseVal = 1);
+ void setCaption(const char *caption, int caseVal = 1);
+
+ bool _editorOnly;
+ bool _is3D;
+
+ DECLARE_PERSISTENT(BaseObject, BaseScriptHolder)
+ virtual bool showCursor();
+ BaseSprite *_cursor;
+ bool _sharedCursors;
+ BaseSprite *_activeCursor;
+ virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
+ virtual bool listen(BaseScriptHolder *param1, uint32 param2);
+
+ bool _movable;
+ bool _zoomable;
+ bool _shadowable;
+ int _posY;
+ int _posX;
+ bool _registrable;
+ char *_caption[7];
+ bool _saveState;
+
+ BaseObject(BaseGame *inGame);
+ virtual ~BaseObject();
+ // base
+ virtual bool update() {
+ return STATUS_FAILED;
+ };
+ virtual bool display() {
+ return STATUS_FAILED;
+ };
+ virtual bool invalidateDeviceObjects() {
+ return STATUS_OK;
+ };
+ virtual bool restoreDeviceObjects() {
+ return STATUS_OK;
+ };
+ bool _nonIntMouseEvents;
+
+
+public:
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_parser.cpp b/engines/wintermute/base/base_parser.cpp
new file mode 100644
index 0000000000..9a0e9e3ad9
--- /dev/null
+++ b/engines/wintermute/base/base_parser.cpp
@@ -0,0 +1,467 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+#include "common/util.h"
+
+#define WHITESPACE " \t\n\r"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////
+BaseParser::BaseParser() {
+ _whiteSpace = new char [strlen(WHITESPACE) + 1];
+ strcpy(_whiteSpace, WHITESPACE);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseParser::~BaseParser() {
+ if (_whiteSpace != NULL) {
+ delete[] _whiteSpace;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+char *BaseParser::getLastOffender() {
+ return _lastOffender;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int32 BaseParser::getObject(char **buf, const TokenDesc *tokens, char **name, char **data) {
+ skipCharacters(buf, _whiteSpace);
+
+ // skip comment lines.
+ while (**buf == ';') {
+ *buf = strchr(*buf, '\n');
+ _parserLine++;
+ skipCharacters(buf, _whiteSpace);
+ }
+
+ if (! **buf) { // at end of file
+ return PARSERR_EOF;
+ }
+
+ // find the token.
+ // TODO: for now just use brute force. Improve later.
+ while (tokens->id != 0) {
+ if (!scumm_strnicmp(tokens->token, *buf, strlen(tokens->token))) {
+ // here we could be matching PART of a string
+ // we could detect this here or the token list
+ // could just have the longer tokens first in the list
+ break;
+ }
+ ++tokens;
+ }
+ if (tokens->id == 0) {
+ char *p = strchr(*buf, '\n');
+ if (p && p > *buf) {
+ strncpy(_lastOffender, *buf, MIN((uint32)255, (uint32)(p - *buf))); // TODO, clean
+ } else {
+ strcpy(_lastOffender, "");
+ }
+
+ return PARSERR_TOKENNOTFOUND;
+ }
+ // skip the token
+ *buf += strlen(tokens->token);
+ skipCharacters(buf, _whiteSpace);
+
+ // get optional name
+ *name = getSubText(buf, '\'', '\''); // single quotes
+ skipCharacters(buf, _whiteSpace);
+
+ // get optional data
+ if (**buf == '=') { // An assignment rather than a command/object.
+ *data = getAssignmentText(buf);
+ } else {
+ *data = getSubText(buf, '{', '}');
+ }
+
+ return tokens->id;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int32 BaseParser::getCommand(char **buf, const TokenDesc *tokens, char **params) {
+ if (!*buf) {
+ return PARSERR_TOKENNOTFOUND;
+ }
+ BaseEngine::instance().getGameRef()->miniUpdate();
+ char *name;
+ return getObject(buf, tokens, &name, params);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseParser::skipCharacters(char **buf, const char *toSkip) {
+ char ch;
+ while ((ch = **buf) != 0) {
+ if (ch == '\n') {
+ _parserLine++;
+ }
+ if (strchr(toSkip, ch) == NULL) {
+ return;
+ }
+ ++*buf; // skip this character
+ }
+ // we must be at the end of the buffer if we get here
+}
+
+
+//////////////////////////////////////////////////////////////////////
+char *BaseParser::getSubText(char **buf, char open, char close) {
+ if (**buf == 0 || **buf != open) {
+ return 0;
+ }
+ ++*buf; // skip opening delimiter
+ char *result = *buf;
+
+ // now find the closing delimiter
+ char theChar;
+ long skip = 1;
+
+ if (open == close) { // we cant nest identical delimiters
+ open = 0;
+ }
+ while ((theChar = **buf) != 0) {
+ if (theChar == open) {
+ ++skip;
+ }
+ if (theChar == close) {
+ if (--skip == 0) {
+ **buf = 0; // null terminate the result string
+ ++*buf; // move past the closing delimiter
+ break;
+ }
+ }
+ ++*buf; // try next character
+ }
+ return result;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+char *BaseParser::getAssignmentText(char **buf) {
+ ++*buf; // skip the '='
+ skipCharacters(buf, _whiteSpace);
+ char *result = *buf;
+
+
+ if (*result == '"') {
+ result = getSubText(buf, '"', '"');
+ } else {
+ // now, we need to find the next whitespace to end the data
+ char theChar;
+
+ while ((theChar = **buf) != 0) {
+ if (theChar <= 0x20) { // space and control chars
+ break;
+ }
+ ++*buf;
+ }
+ **buf = 0; // null terminate it
+ if (theChar) { // skip the terminator
+ ++*buf;
+ }
+ }
+
+ return result;
+}
+
+//////////////////////////////////////////////////////////////////////
+Common::String BaseParser::getToken(char **buf) {
+ char token[100]; // TODO: Remove static
+ char *b = *buf, *t = token;
+ while (true) {
+ while (*b && (*b == ' ' || *b == '\n' || *b == 13 || *b == 10 || *b == '\t')) {
+ b++;
+ }
+ if (*b == ';')
+ while (*b && *b != '\n' && *b != 13 && *b != 10) {
+ b++;
+ }
+ else {
+ break;
+ }
+ }
+
+ if (*b == '\'') {
+ b++;
+ while (*b && *b != '\'') {
+ *t++ = *b++;
+ }
+ *t++ = 0;
+ if (*b == '\'') {
+ b++;
+ }
+ } else if (*b == '(' || *b == ')' || *b == '=' || *b == ',' || *b == '[' || *b == ']' ||
+ *b == '%' || *b == ':' || *b == '{' || *b == '}') {
+ *t++ = *b++;
+ *t++ = 0;
+ } else if (*b == '.' && (*(b + 1) < '0' || *(b + 1) > '9')) {
+ *t++ = *b++;
+ *t++ = 0;
+ } else if ((*b >= '0' && *b <= '9') || *b == '.' || *b == '-') {
+ while (*b && ((*b >= '0' && *b <= '9') || *b == '.' || *b == '-')) {
+ *t++ = *b++;
+ }
+ *t++ = 0;
+ } else if ((*b >= 'A' && *b <= 'Z') || (*b >= 'a' && *b <= 'z') || *b == '_') {
+ while (*b && ((*b >= 'A' && *b <= 'Z') || (*b >= 'a' && *b <= 'z') || *b == '_')) {
+ *t++ = *b++;
+ }
+ *t++ = 0;
+ } else if (*b == 0) {
+ *buf = b;
+ return NULL;
+ } else {
+ // Error.
+ return NULL;
+ }
+
+ *buf = b;
+ return token;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+float BaseParser::getTokenFloat(char **buf) {
+ Common::String token = getToken(buf);
+ const char *t = token.c_str();
+ if (!((*t >= '0' && *t <= '9') || *t == '-' || *t == '.')) {
+ // Error situation. We handle this by return 0.
+ return 0.;
+ }
+ float rc = (float)atof(t);
+ return rc;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseParser::getTokenInt(char **buf) {
+ Common::String token = getToken(buf);
+ const char *t = token.c_str();
+ if (!((*t >= '0' && *t <= '9') || *t == '-')) {
+ // Error situation. We handle this by return 0.
+ return 0;
+ }
+ int rc = atoi(t);
+ return rc;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseParser::skipToken(char **buf, char *tok, char * /*msg*/) {
+ Common::String token = getToken(buf);
+ const char *t = token.c_str();
+ if (strcmp(t, tok)) {
+ return; // Error
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseParser::scanStr(const char *in, const char *format, ...) {
+ va_list arg;
+ va_start(arg, format);
+
+ int num = 0;
+ in += strspn(in, " \t\n\f");
+
+ while (*format && *in) {
+ if (*format == '%') {
+ format++;
+ switch (*format) {
+ case 'd': {
+ int *a = va_arg(arg, int *);
+ in += strspn(in, " \t\n\f");
+ *a = atoi(in);
+ in += strspn(in, "0123456789+- \t\n\f");
+ num++;
+ break;
+ }
+ case 'D': {
+ int i;
+ int *list = va_arg(arg, int *);
+ int *nr = va_arg(arg, int *);
+ in += strspn(in, " \t\n\f");
+ i = 0;
+ while ((*in >= '0' && *in <= '9') || *in == '+' || *in == '-') {
+ list[i++] = atoi(in);
+ in += strspn(in, "0123456789+-");
+ in += strspn(in, " \t\n\f");
+ if (*in != ',') {
+ break;
+ }
+ in++;
+ in += strspn(in, " \t\n\f");
+ }
+ *nr = i;
+ num++;
+ break;
+ }
+ case 'b': {
+ bool *a = va_arg(arg, bool *);
+ in += strspn(in, " \t\n\f");
+ const char *in2 = in + strspn(in, "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ");
+ int l = (int)(in2 - in);
+
+ *a = (bool)(!scumm_strnicmp(in, "yes", l) || !scumm_strnicmp(in, "true", l) || !scumm_strnicmp(in, "on", l) ||
+ !scumm_strnicmp(in, "1", l));
+
+
+ in = in2 + strspn(in2, " \t\n\f");
+ num++;
+ break;
+ }
+ case 'f': {
+ float *a = va_arg(arg, float *);
+ in += strspn(in, " \t\n\f");
+ *a = (float)atof(in);
+ in += strspn(in, "0123456789.eE+- \t\n\f");
+ num++;
+ break;
+ }
+ case 'F': {
+ int i;
+ float *list = va_arg(arg, float *);
+ int *nr = va_arg(arg, int *);
+ in += strspn(in, " \t\n\f");
+ i = 0;
+ while ((*in >= '0' && *in <= '9') || *in == '.' || *in == '+' || *in == '-' || *in == 'e' || *in == 'E') {
+ list[i++] = (float)atof(in);
+ in += strspn(in, "0123456789.eE+-");
+ in += strspn(in, " \t\n\f");
+ if (*in != ',') {
+ break;
+ }
+ in++;
+ in += strspn(in, " \t\n\f");
+ }
+ *nr = i;
+ num++;
+ break;
+ }
+ case 's': {
+ char *a = va_arg(arg, char *);
+ in += strspn(in, " \t\n\f");
+ if (*in == '\'') {
+ in++;
+ const char *in2 = strchr(in, '\'');
+ if (in2) {
+ Common::strlcpy(a, in, (int)(in2 - in) + 1);
+ in = in2 + 1;
+ } else {
+ strcpy(a, in);
+ in = strchr(in, 0);
+ }
+ } else {
+ const char *in2 = in + strspn(in, "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ_0123456789.");
+ Common::strlcpy(a, in, (int)(in2 - in) + 1);
+ in = in2;
+ }
+ in += strspn(in, " \t\n\f");
+ num++;
+ break;
+ }
+ case 'S': {
+ char *a = va_arg(arg, char *);
+ in += strspn(in, " \t\n\f");
+ if (*in == '\"') {
+ in++;
+ while (*in != '\"') {
+ if (*in == '\\') {
+ in++;
+ switch (*in) {
+ case '\\':
+ *a++ = '\\';
+ break;
+ case 'n':
+ *a++ = '\n';
+ break;
+ case 'r':
+ *a++ = '\r';
+ break;
+ case 't':
+ *a++ = '\t';
+ break;
+ case '"':
+ *a++ = '"';
+ break;
+ default:
+ *a++ = '\\';
+ *a++ = *in;
+ break;
+ } //switch
+ in++;
+ } else {
+ *a++ = *in++;
+ }
+ } //while in string
+ in++;
+ num++;
+ } //if string started
+
+ //terminate string
+ *a = '\0';
+ break;
+ }
+ }
+ if (*format) {
+ format++;
+ }
+ } else if (*format == ' ') {
+ format++;
+ in += strspn(in, " \t\n\f");
+ } else if (*in == *format) {
+ in++;
+ format++;
+ } else {
+ num = -1;
+ break;
+ }
+ }
+
+ va_end(arg);
+
+ return num;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_parser.h b/engines/wintermute/base/base_parser.h
new file mode 100644
index 0000000000..76ca8ea856
--- /dev/null
+++ b/engines/wintermute/base/base_parser.h
@@ -0,0 +1,88 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_PARSER_H
+#define WINTERMUTE_BASE_PARSER_H
+
+
+#define TOKEN_DEF_START \
+ enum \
+ { \
+ TOKEN_NONE = 0,
+#define TOKEN_DEF(name) \
+ TOKEN_ ## name,
+#define TOKEN_DEF_END \
+ TOKEN_TOTAL_COUNT \
+ };
+#define TOKEN_TABLE_START(name) \
+ static const BaseParser::TokenDesc name [] = \
+ {
+#define TOKEN_TABLE(name) \
+ { TOKEN_ ## name, #name },
+#define TOKEN_TABLE_END \
+ { 0, 0 } \
+ };
+
+#define PARSERR_GENERIC -3
+#define PARSERR_EOF -2
+#define PARSERR_TOKENNOTFOUND -1
+
+#include "engines/wintermute/coll_templ.h"
+
+namespace Wintermute {
+
+class BaseParser {
+public:
+ struct TokenDesc {
+ int32 id;
+ const char *token;
+ };
+
+public:
+ int scanStr(const char *in, const char *format, ...);
+ int32 getCommand(char **buf, const TokenDesc *tokens, char **params);
+ BaseParser();
+ virtual ~BaseParser();
+private:
+ char *getLastOffender();
+ void skipToken(char **buf, char *tok, char *msg = NULL);
+ int getTokenInt(char **buf);
+ float getTokenFloat(char **buf);
+ Common::String getToken(char **buf);
+ char *getAssignmentText(char **buf);
+ char *getSubText(char **buf, char open, char close);
+ void skipCharacters(char **buf, const char *toSkip);
+ int32 getObject(char **buf, const TokenDesc *tokens, char **name, char **data);
+ int _parserLine;
+ char _lastOffender[255];
+ char *_whiteSpace;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_persistence_manager.cpp b/engines/wintermute/base/base_persistence_manager.cpp
new file mode 100644
index 0000000000..4cb67b87e1
--- /dev/null
+++ b/engines/wintermute/base/base_persistence_manager.cpp
@@ -0,0 +1,828 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+#include "engines/wintermute/base/base_save_thumb_helper.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/math/vector2.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/wintermute.h"
+#include "graphics/decoders/bmp.h"
+#include "common/memstream.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/savefile.h"
+
+namespace Wintermute {
+
+#define SAVE_BUFFER_INIT_SIZE 100000
+#define SAVE_BUFFER_GROW_BY 50000
+
+#define SAVE_MAGIC 0x45564153
+#define SAVE_MAGIC_2 0x32564153
+
+//////////////////////////////////////////////////////////////////////////
+BasePersistenceManager::BasePersistenceManager(const char *savePrefix, bool deleteSingleton) {
+ _saving = false;
+// _buffer = NULL;
+// _bufferSize = 0;
+ _offset = 0;
+ _saveStream = NULL;
+ _loadStream = NULL;
+ _deleteSingleton = deleteSingleton;
+ if (BaseEngine::instance().getGameRef()) {
+ _gameRef = BaseEngine::instance().getGameRef();
+ } else {
+ _gameRef = NULL;
+ }
+
+ _richBuffer = NULL;
+ _richBufferSize = 0;
+
+ _savedDescription = NULL;
+// _savedTimestamp = 0;
+ _savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
+ _savedExtMajor = _savedExtMinor = 0;
+
+ _thumbnailDataSize = 0;
+ _thumbnailData = NULL;
+ if (savePrefix) {
+ _savePrefix = savePrefix;
+ } else if (_gameRef) {
+ _savePrefix = _gameRef->getGameId();
+ } else {
+ _savePrefix = "wmesav";
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BasePersistenceManager::~BasePersistenceManager() {
+ cleanup();
+ if (_deleteSingleton && BaseEngine::instance().getGameRef() == NULL)
+ BaseEngine::destroy();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BasePersistenceManager::cleanup() {
+ /* if (_buffer) {
+ if (_saving) free(_buffer);
+ else delete[] _buffer; // allocated by file manager
+ }
+ _buffer = NULL;
+
+ _bufferSize = 0;*/
+ _offset = 0;
+
+ delete[] _richBuffer;
+ _richBuffer = NULL;
+ _richBufferSize = 0;
+
+ delete[] _savedDescription;
+ _savedDescription = NULL; // ref to buffer
+// _savedTimestamp = 0;
+ _savedVerMajor = _savedVerMinor = _savedVerBuild = 0;
+ _savedExtMajor = _savedExtMinor = 0;
+
+ _thumbnailDataSize = 0;
+ if (_thumbnailData) {
+ delete[] _thumbnailData;
+ _thumbnailData = NULL;
+ }
+
+ delete _loadStream;
+ delete _saveStream;
+ _loadStream = NULL;
+ _saveStream = NULL;
+}
+
+Common::String BasePersistenceManager::getFilenameForSlot(int slot) const {
+ // 3 Digits, to allow for one save-slot for autosave + slot 1 - 100 (which will be numbered 0-99 filename-wise)
+ return Common::String::format("%s-save%03d.wsv", _savePrefix.c_str(), slot);
+}
+
+void BasePersistenceManager::getSaveStateDesc(int slot, SaveStateDescriptor &desc) {
+ Common::String filename = getFilenameForSlot(slot);
+ debugC(kWintermuteDebugSaveGame, "Trying to list savegame %s in slot %d", filename.c_str(), slot);
+ if (DID_FAIL(readHeader(filename))) {
+ warning("getSavedDesc(%d) - Failed for %s", slot, filename.c_str());
+ return;
+ }
+ desc.setSaveSlot(slot);
+ desc.setDescription(_savedDescription);
+ desc.setDeletableFlag(true);
+ desc.setWriteProtectedFlag(false);
+
+ if (_thumbnailDataSize > 0) {
+ Common::MemoryReadStream thumbStream(_thumbnailData, _thumbnailDataSize);
+ Graphics::BitmapDecoder bmpDecoder;
+ if (bmpDecoder.loadStream(thumbStream)) {
+ Graphics::Surface *surf = new Graphics::Surface;
+ surf = bmpDecoder.getSurface()->convertTo(g_system->getOverlayFormat());
+ desc.setThumbnail(surf);
+ }
+ }
+
+ desc.setSaveDate(_savedTimestamp.tm_year, _savedTimestamp.tm_mon, _savedTimestamp.tm_mday);
+ desc.setSaveTime(_savedTimestamp.tm_hour, _savedTimestamp.tm_min);
+ desc.setPlayTime(0);
+}
+
+void BasePersistenceManager::deleteSaveSlot(int slot) {
+ Common::String filename = getFilenameForSlot(slot);
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
+uint32 BasePersistenceManager::getMaxUsedSlot() {
+ Common::String saveMask = Common::String::format("%s-save???.wsv", _savePrefix.c_str());
+ Common::StringArray saves = g_system->getSavefileManager()->listSavefiles(saveMask);
+ Common::StringArray::iterator it = saves.begin();
+ int ret = -1;
+ for (; it != saves.end(); ++it) {
+ int num = -1;
+ sscanf(it->c_str(), "save%d", &num);
+ ret = MAX(ret, num);
+ }
+ return ret;
+}
+
+bool BasePersistenceManager::getSaveExists(int slot) {
+ Common::String filename = getFilenameForSlot(slot);
+ if (DID_FAIL(readHeader(filename))) {
+ return false;
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::initSave(const char *desc) {
+ if (!desc) {
+ return STATUS_FAILED;
+ }
+
+ cleanup();
+ _saving = true;
+
+ _saveStream = new Common::MemoryWriteStreamDynamic(DisposeAfterUse::YES);
+
+ if (_saveStream) {
+ // get thumbnails
+ if (!_gameRef->_cachedThumbnail) {
+ _gameRef->_cachedThumbnail = new BaseSaveThumbHelper(_gameRef);
+ if (DID_FAIL(_gameRef->_cachedThumbnail->storeThumbnail(true))) {
+ delete _gameRef->_cachedThumbnail;
+ _gameRef->_cachedThumbnail = NULL;
+ }
+ }
+
+ uint32 magic = DCGF_MAGIC;
+ putDWORD(magic);
+
+ magic = SAVE_MAGIC_2;
+ putDWORD(magic);
+
+ byte verMajor, verMinor, extMajor, extMinor;
+ _gameRef->getVersion(&verMajor, &verMinor, &extMajor, &extMinor);
+ //uint32 version = MAKELONG(MAKEWORD(VerMajor, VerMinor), MAKEWORD(ExtMajor, ExtMinor));
+ _saveStream->writeByte(verMajor);
+ _saveStream->writeByte(verMinor);
+ _saveStream->writeByte(extMajor);
+ _saveStream->writeByte(extMinor);
+
+ // new in ver 2
+ putDWORD((uint32)DCGF_VER_BUILD);
+ putString(_gameRef->getName());
+
+ // thumbnail data size
+ bool thumbnailOK = false;
+
+ if (_gameRef->_cachedThumbnail) {
+ if (_gameRef->_cachedThumbnail->_thumbnail) {
+ Common::MemoryWriteStreamDynamic thumbStream(DisposeAfterUse::YES);
+ if (_gameRef->_cachedThumbnail->_thumbnail->writeBMPToStream(&thumbStream)) {
+ _saveStream->writeUint32LE(thumbStream.size());
+ _saveStream->write(thumbStream.getData(), thumbStream.size());
+ } else {
+ _saveStream->writeUint32LE(0);
+ }
+
+ thumbnailOK = true;
+ }
+ }
+ if (!thumbnailOK) {
+ putDWORD(0);
+ }
+
+ // in any case, destroy the cached thumbnail once used
+ delete _gameRef->_cachedThumbnail;
+ _gameRef->_cachedThumbnail = NULL;
+
+ uint32 dataOffset = _offset +
+ sizeof(uint32) + // data offset
+ sizeof(uint32) + strlen(desc) + 1 + // description
+ sizeof(uint32); // timestamp
+
+ putDWORD(dataOffset);
+ putString(desc);
+
+ g_system->getTimeAndDate(_savedTimestamp);
+ putTimeDate(_savedTimestamp);
+ _savedPlayTime = g_system->getMillis();
+ _saveStream->writeUint32LE(_savedPlayTime);
+ }
+ return STATUS_OK;
+}
+
+bool BasePersistenceManager::readHeader(const Common::String &filename) {
+ cleanup();
+
+ _saving = false;
+
+ _loadStream = g_system->getSavefileManager()->openForLoading(filename);
+ //_buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &_bufferSize);
+ if (_loadStream) {
+ uint32 magic;
+ magic = getDWORD();
+
+ if (magic != DCGF_MAGIC) {
+ cleanup();
+ return STATUS_FAILED;
+ }
+
+ magic = getDWORD();
+
+ if (magic == SAVE_MAGIC || magic == SAVE_MAGIC_2) {
+ _savedVerMajor = _loadStream->readByte();
+ _savedVerMinor = _loadStream->readByte();
+ _savedExtMajor = _loadStream->readByte();
+ _savedExtMinor = _loadStream->readByte();
+
+ if (magic == SAVE_MAGIC_2) {
+ _savedVerBuild = (byte)getDWORD();
+ _savedName = getStringObj();
+
+ // load thumbnail
+ _thumbnailDataSize = getDWORD();
+ if (_thumbnailDataSize > 0) {
+ _thumbnailData = new byte[_thumbnailDataSize];
+ if (_thumbnailData) {
+ getBytes(_thumbnailData, _thumbnailDataSize);
+ } else {
+ _thumbnailDataSize = 0;
+ }
+ }
+ } else {
+ _savedVerBuild = 35; // last build with ver1 savegames
+ }
+
+ uint32 dataOffset = getDWORD();
+
+ _savedDescription = getString();
+ _savedTimestamp = getTimeDate();
+ _savedPlayTime = _loadStream->readUint32LE();
+
+ _offset = dataOffset;
+
+ return STATUS_OK;
+ }
+ }
+
+ cleanup();
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::initLoad(const Common::String &filename) {
+ if (DID_FAIL(readHeader(filename))) {
+ cleanup();
+ return STATUS_FAILED;
+ }
+ _saving = false;
+
+ if (_savedName == "" || scumm_stricmp(_savedName.c_str(), _gameRef->getName()) != 0) {
+ debugC(kWintermuteDebugSaveGame, "ERROR: Saved game name doesn't match current game");
+ cleanup();
+ return STATUS_FAILED;
+ }
+
+ // if save is newer version than we are, fail
+ if (_savedVerMajor > DCGF_VER_MAJOR ||
+ (_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor > DCGF_VER_MINOR) ||
+ (_savedVerMajor == DCGF_VER_MAJOR && _savedVerMinor == DCGF_VER_MINOR && _savedVerBuild > DCGF_VER_BUILD)
+ ) {
+
+ debugC(kWintermuteDebugSaveGame, "ERROR: Saved game version is newer than current game");
+ debugC(kWintermuteDebugSaveGame, "ERROR: Expected %d.%d.%d got %d.%d.%d", DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, _savedVerMajor, _savedVerMinor, _savedVerBuild);
+ cleanup();
+ return STATUS_FAILED;
+ }
+
+ // if save is older than the minimal version we support
+ if (_savedVerMajor < SAVEGAME_VER_MAJOR ||
+ (_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor < SAVEGAME_VER_MINOR) ||
+ (_savedVerMajor == SAVEGAME_VER_MAJOR && _savedVerMinor == SAVEGAME_VER_MINOR && _savedVerBuild < SAVEGAME_VER_BUILD)
+ ) {
+ debugC(kWintermuteDebugSaveGame, "ERROR: Saved game is too old and cannot be used by this version of game engine");
+ debugC(kWintermuteDebugSaveGame, "ERROR: Expected %d.%d.%d got %d.%d.%d", DCGF_VER_MAJOR, DCGF_VER_MINOR, DCGF_VER_BUILD, _savedVerMajor, _savedVerMinor, _savedVerBuild);
+ cleanup();
+ return STATUS_FAILED;
+
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::saveFile(const Common::String &filename) {
+ byte *prefixBuffer = _richBuffer;
+ uint32 prefixSize = _richBufferSize;
+ byte *buffer = ((Common::MemoryWriteStreamDynamic *)_saveStream)->getData();
+ uint32 bufferSize = ((Common::MemoryWriteStreamDynamic *)_saveStream)->size();
+
+ Common::SaveFileManager *saveMan = ((WintermuteEngine *)g_engine)->getSaveFileMan();
+ Common::OutSaveFile *file = saveMan->openForSaving(filename);
+ file->write(prefixBuffer, prefixSize);
+ file->write(buffer, bufferSize);
+ bool retVal = !file->err();
+ file->finalize();
+ delete file;
+ return retVal;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::putBytes(byte *buffer, uint32 size) {
+ _saveStream->write(buffer, size);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::getBytes(byte *buffer, uint32 size) {
+ _loadStream->read(buffer, size);
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BasePersistenceManager::putDWORD(uint32 val) {
+ _saveStream->writeUint32LE(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BasePersistenceManager::getDWORD() {
+ uint32 ret = _loadStream->readUint32LE();
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BasePersistenceManager::putString(const Common::String &val) {
+ if (!val.size()) {
+ putString("(null)");
+ } else {
+ _saveStream->writeUint32LE(val.size());
+ _saveStream->writeString(val);
+ }
+}
+
+Common::String BasePersistenceManager::getStringObj() {
+ uint32 len = _loadStream->readUint32LE();
+ char *ret = new char[len + 1];
+ _loadStream->read(ret, len);
+ ret[len] = '\0';
+
+ Common::String retString = ret;
+ delete[] ret;
+
+ if (retString == "(null)") {
+ retString = "";
+ }
+
+ return retString;
+}
+
+//////////////////////////////////////////////////////////////////////////
+char *BasePersistenceManager::getString() {
+ uint32 len = _loadStream->readUint32LE();
+ char *ret = new char[len + 1];
+ _loadStream->read(ret, len);
+ ret[len] = '\0';
+
+ if (!strcmp(ret, "(null)")) {
+ delete[] ret;
+ return NULL;
+ } else {
+ return ret;
+ }
+}
+
+bool BasePersistenceManager::putTimeDate(const TimeDate &t) {
+ _saveStream->writeSint32LE(t.tm_sec);
+ _saveStream->writeSint32LE(t.tm_min);
+ _saveStream->writeSint32LE(t.tm_hour);
+ _saveStream->writeSint32LE(t.tm_mday);
+ _saveStream->writeSint32LE(t.tm_mon);
+ _saveStream->writeSint32LE(t.tm_year);
+ // _saveStream->writeSint32LE(t.tm_wday); //TODO: Add this in when merging next
+
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+}
+
+TimeDate BasePersistenceManager::getTimeDate() {
+ TimeDate t;
+ t.tm_sec = _loadStream->readSint32LE();
+ t.tm_min = _loadStream->readSint32LE();
+ t.tm_hour = _loadStream->readSint32LE();
+ t.tm_mday = _loadStream->readSint32LE();
+ t.tm_mon = _loadStream->readSint32LE();
+ t.tm_year = _loadStream->readSint32LE();
+ // t.tm_wday = _loadStream->readSint32LE(); //TODO: Add this in when merging next
+ return t;
+}
+
+void BasePersistenceManager::putFloat(float val) {
+ Common::String str = Common::String::format("F%f", val);
+ _saveStream->writeUint32LE(str.size());
+ _saveStream->writeString(str);
+}
+
+float BasePersistenceManager::getFloat() {
+ char *str = getString();
+ float value = 0.0f;
+ int ret = sscanf(str, "F%f", &value);
+ if (ret != 1) {
+ warning("%s not parsed as float", str);
+ }
+ delete[] str;
+ return value;
+}
+
+void BasePersistenceManager::putDouble(double val) {
+ Common::String str = Common::String::format("D%f", val);
+ str.format("D%f", val);
+ _saveStream->writeUint32LE(str.size());
+ _saveStream->writeString(str);
+}
+
+double BasePersistenceManager::getDouble() {
+ char *str = getString();
+ float value = 0.0f; // TODO: Do we ever really need to carry a full double-precision number?
+ int ret = sscanf(str, "D%f", &value);
+ if (ret != 1) {
+ warning("%s not parsed as double", str);
+ }
+ delete[] str;
+ return value;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// bool
+bool BasePersistenceManager::transfer(const char *name, bool *val) {
+ if (_saving) {
+ _saveStream->writeByte(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = _loadStream->readByte();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// int
+bool BasePersistenceManager::transfer(const char *name, int *val) {
+ if (_saving) {
+ _saveStream->writeSint32LE(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = _loadStream->readSint32LE();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// DWORD
+bool BasePersistenceManager::transfer(const char *name, uint32 *val) {
+ if (_saving) {
+ _saveStream->writeUint32LE(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = _loadStream->readUint32LE();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// float
+bool BasePersistenceManager::transfer(const char *name, float *val) {
+ if (_saving) {
+ putFloat(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = getFloat();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// double
+bool BasePersistenceManager::transfer(const char *name, double *val) {
+ if (_saving) {
+ putDouble(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = getDouble();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// char*
+bool BasePersistenceManager::transfer(const char *name, char **val) {
+ if (_saving) {
+ putString(*val);
+ return STATUS_OK;
+ } else {
+ char *str = getString();
+ if (_loadStream->err()) {
+ delete[] str;
+ return STATUS_FAILED;
+ }
+ *val = str;
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// const char*
+bool BasePersistenceManager::transfer(const char *name, const char **val) {
+ if (_saving) {
+ putString(*val);
+ return STATUS_OK;
+ } else {
+ char *str = getString();
+ if (_loadStream->err()) {
+ delete[] str;
+ return STATUS_FAILED;
+ }
+ *val = str;
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Common::String
+bool BasePersistenceManager::transfer(const char *name, Common::String *val) {
+ if (_saving) {
+ putString(*val);
+ return STATUS_OK;
+ } else {
+ char *str = getString();
+ if (_loadStream->err()) {
+ delete[] str;
+ return STATUS_FAILED;
+ }
+ if (str) {
+ *val = str;
+ delete[] str;
+ } else {
+ *val = "";
+ }
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::transfer(const char *name, AnsiStringArray &val) {
+ size_t size;
+
+ if (_saving) {
+ size = val.size();
+ _saveStream->writeUint32LE(size);
+
+ for (AnsiStringArray::iterator it = val.begin(); it != val.end(); ++it) {
+ putString((*it).c_str());
+ }
+ } else {
+ val.clear();
+ size = _loadStream->readUint32LE();
+
+ for (size_t i = 0; i < size; i++) {
+ char *str = getString();
+ if (_loadStream->err()) {
+ delete[] str;
+ return STATUS_FAILED;
+ }
+ if (str) {
+ val.push_back(str);
+ }
+ delete[] str;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// BYTE
+bool BasePersistenceManager::transfer(const char *name, byte *val) {
+ if (_saving) {
+ _saveStream->writeByte(*val);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ *val = _loadStream->readByte();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// RECT
+bool BasePersistenceManager::transfer(const char *name, Rect32 *val) {
+ if (_saving) {
+ _saveStream->writeSint32LE(val->left);
+ _saveStream->writeSint32LE(val->top);
+ _saveStream->writeSint32LE(val->right);
+ _saveStream->writeSint32LE(val->bottom);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ val->left = _loadStream->readSint32LE();
+ val->top = _loadStream->readSint32LE();
+ val->right = _loadStream->readSint32LE();
+ val->bottom = _loadStream->readSint32LE();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// POINT
+bool BasePersistenceManager::transfer(const char *name, Point32 *val) {
+ if (_saving) {
+ _saveStream->writeSint32LE(val->x);
+ _saveStream->writeSint32LE(val->y);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ val->x = _loadStream->readSint32LE();
+ val->y = _loadStream->readSint32LE();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// Vector2
+bool BasePersistenceManager::transfer(const char *name, Vector2 *val) {
+ if (_saving) {
+ putFloat(val->x);
+ putFloat(val->y);
+ if (_saveStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ } else {
+ val->x = getFloat();
+ val->y = getFloat();
+ if (_loadStream->err()) {
+ return STATUS_FAILED;
+ }
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// generic pointer
+bool BasePersistenceManager::transfer(const char *name, void *val) {
+ int classID = -1, instanceID = -1;
+
+ if (_saving) {
+ SystemClassRegistry::getInstance()->getPointerID(*(void **)val, &classID, &instanceID);
+ if (*(void **)val != NULL && (classID == -1 || instanceID == -1)) {
+ debugC(kWintermuteDebugSaveGame, "Warning: invalid instance '%s'", name);
+ }
+
+ _saveStream->writeUint32LE(classID);
+ _saveStream->writeUint32LE(instanceID);
+ } else {
+ classID = _loadStream->readUint32LE();
+ instanceID = _loadStream->readUint32LE();
+
+ *(void **)val = SystemClassRegistry::getInstance()->idToPointer(classID, instanceID);
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePersistenceManager::checkVersion(byte verMajor, byte verMinor, byte verBuild) {
+ if (_saving) {
+ return true;
+ }
+
+ // it's ok if we are same or newer than the saved game
+ if (verMajor > _savedVerMajor ||
+ (verMajor == _savedVerMajor && verMinor > _savedVerMinor) ||
+ (verMajor == _savedVerMajor && verMinor == _savedVerMinor && verBuild > _savedVerBuild)
+ ) {
+ return false;
+ }
+
+ return true;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_persistence_manager.h b/engines/wintermute/base/base_persistence_manager.h
new file mode 100644
index 0000000000..a262c92a0b
--- /dev/null
+++ b/engines/wintermute/base/base_persistence_manager.h
@@ -0,0 +1,118 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_PERSISTENCE_MANAGER_H
+#define WINTERMUTE_BASE_PERSISTENCE_MANAGER_H
+
+
+#include "engines/wintermute/dctypes.h"
+#include "engines/wintermute/math/rect32.h"
+#include "engines/savestate.h"
+#include "common/stream.h"
+#include "common/str.h"
+#include "common/system.h"
+#include "common/rect.h"
+
+namespace Wintermute {
+
+class Vector2;
+class BaseGame;
+class BasePersistenceManager {
+public:
+ char *_savedDescription;
+ Common::String _savePrefix;
+ Common::String _savedName;
+ bool saveFile(const Common::String &filename);
+ uint32 getDWORD();
+ void putDWORD(uint32 val);
+ char *getString();
+ Common::String getStringObj();
+ void putString(const Common::String &val);
+ float getFloat();
+ void putFloat(float val);
+ double getDouble();
+ void putDouble(double val);
+ void cleanup();
+ void getSaveStateDesc(int slot, SaveStateDescriptor &desc);
+ void deleteSaveSlot(int slot);
+ uint32 getMaxUsedSlot();
+ bool getSaveExists(int slot);
+ bool initLoad(const Common::String &filename);
+ bool initSave(const char *desc);
+ bool getBytes(byte *buffer, uint32 size);
+ bool putBytes(byte *buffer, uint32 size);
+ uint32 _offset;
+
+ bool getIsSaving() { return _saving; }
+
+ uint32 _richBufferSize;
+ byte *_richBuffer;
+
+ bool transfer(const char *name, void *val);
+ bool transfer(const char *name, int *val);
+ bool transfer(const char *name, uint32 *val);
+ bool transfer(const char *name, float *val);
+ bool transfer(const char *name, double *val);
+ bool transfer(const char *name, bool *val);
+ bool transfer(const char *name, byte *val);
+ bool transfer(const char *name, Rect32 *val);
+ bool transfer(const char *name, Point32 *val);
+ bool transfer(const char *name, const char **val);
+ bool transfer(const char *name, char **val);
+ bool transfer(const char *name, Common::String *val);
+ bool transfer(const char *name, Vector2 *val);
+ bool transfer(const char *name, AnsiStringArray &Val);
+ BasePersistenceManager(const char *savePrefix = NULL, bool deleteSingleton = false);
+ virtual ~BasePersistenceManager();
+ bool checkVersion(byte verMajor, byte verMinor, byte verBuild);
+
+ uint32 _thumbnailDataSize;
+ byte *_thumbnailData;
+ Common::String getFilenameForSlot(int slot) const;
+private:
+ bool _deleteSingleton;
+ bool readHeader(const Common::String &filename);
+ TimeDate getTimeDate();
+ bool putTimeDate(const TimeDate &t);
+ Common::WriteStream *_saveStream;
+ Common::SeekableReadStream *_loadStream;
+ TimeDate _savedTimestamp;
+ uint32 _savedPlayTime;
+ byte _savedVerMajor;
+ byte _savedVerMinor;
+ byte _savedVerBuild;
+ byte _savedExtMajor;
+ byte _savedExtMinor;
+ bool _saving;
+ // Separate from Base, as this class can do SOME operations without a _gameRef.
+ BaseGame *_gameRef;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_point.cpp b/engines/wintermute/base/base_point.cpp
new file mode 100644
index 0000000000..fbd8960894
--- /dev/null
+++ b/engines/wintermute/base/base_point.cpp
@@ -0,0 +1,63 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_point.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BasePoint, false)
+
+//////////////////////////////////////////////////////////////////////////
+BasePoint::BasePoint() {
+ x = y = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BasePoint::~BasePoint() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BasePoint::BasePoint(int initX, int initY) {
+ x = initX;
+ y = initY;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BasePoint::persist(BasePersistenceManager *persistMgr) {
+
+ persistMgr->transfer(TMEMBER(x));
+ persistMgr->transfer(TMEMBER(y));
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_point.h b/engines/wintermute/base/base_point.h
new file mode 100644
index 0000000000..c0bbd3102e
--- /dev/null
+++ b/engines/wintermute/base/base_point.h
@@ -0,0 +1,50 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_POINT_H
+#define WINTERMUTE_BASE_POINT_H
+
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BasePoint: public BaseClass {
+public:
+ DECLARE_PERSISTENT(BasePoint, BaseClass)
+ BasePoint();
+ BasePoint(int initX, int initY);
+ int y;
+ int x;
+ virtual ~BasePoint();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_quick_msg.cpp b/engines/wintermute/base/base_quick_msg.cpp
new file mode 100644
index 0000000000..0a9907ac6b
--- /dev/null
+++ b/engines/wintermute/base/base_quick_msg.cpp
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_quick_msg.h"
+#include "engines/wintermute/base/base_game.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseQuickMsg::BaseQuickMsg(BaseGame *inGame, const char *text) : BaseClass(inGame) {
+ _text = new char [strlen(text) + 1];
+ if (_text) {
+ strcpy(_text, text);
+ }
+ _startTime = _gameRef->_currentTime;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseQuickMsg::~BaseQuickMsg() {
+ if (_text) {
+ delete[] _text;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *BaseQuickMsg::getText() {
+ return _text;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_quick_msg.h b/engines/wintermute/base/base_quick_msg.h
new file mode 100644
index 0000000000..4fed5ffc2e
--- /dev/null
+++ b/engines/wintermute/base/base_quick_msg.h
@@ -0,0 +1,48 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_QUICKMSG_H
+#define WINTERMUTE_BASE_QUICKMSG_H
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseQuickMsg : public BaseClass {
+public:
+ char *getText();
+ uint32 _startTime;
+ char *_text;
+ BaseQuickMsg(BaseGame *inGame, const char *Text);
+ virtual ~BaseQuickMsg();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_region.cpp b/engines/wintermute/base/base_region.cpp
new file mode 100644
index 0000000000..e332ffe9ff
--- /dev/null
+++ b/engines/wintermute/base/base_region.cpp
@@ -0,0 +1,535 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/platform_osystem.h"
+#include <limits.h>
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseRegion, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseRegion::BaseRegion(BaseGame *inGame) : BaseObject(inGame) {
+ _active = true;
+ _editorSelectedPoint = -1;
+ _lastMimicScale = -1;
+ _lastMimicX = _lastMimicY = INT_MIN;
+
+ BasePlatform::setRectEmpty(&_rect);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseRegion::~BaseRegion() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRegion::cleanup() {
+ for (uint32 i = 0; i < _points.size(); i++) {
+ delete _points[i];
+ }
+ _points.clear();
+
+ BasePlatform::setRectEmpty(&_rect);
+ _editorSelectedPoint = -1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::createRegion() {
+ return DID_SUCCEED(getBoundingRect(&_rect));
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::pointInRegion(int x, int y) {
+ if (_points.size() < 3) {
+ return false;
+ }
+
+ Point32 pt;
+ pt.x = x;
+ pt.y = y;
+
+ Rect32 rect;
+ rect.left = x - 1;
+ rect.right = x + 2;
+ rect.top = y - 1;
+ rect.bottom = y + 2;
+
+ if (BasePlatform::ptInRect(&_rect, pt)) {
+ return ptInPolygon(x, y);
+ } else {
+ return false;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::loadFile(const char *filename) {
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer == NULL) {
+ _gameRef->LOG(0, "BaseRegion::LoadFile failed for file '%s'", filename);
+ return STATUS_FAILED;
+ }
+
+ bool ret;
+
+ setFilename(filename);
+
+ if (DID_FAIL(ret = loadBuffer(buffer, true))) {
+ _gameRef->LOG(0, "Error parsing REGION file '%s'", filename);
+ }
+
+
+ delete[] buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(REGION)
+TOKEN_DEF(TEMPLATE)
+TOKEN_DEF(NAME)
+TOKEN_DEF(ACTIVE)
+TOKEN_DEF(POINT)
+TOKEN_DEF(CAPTION)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(EDITOR_SELECTED_POINT)
+TOKEN_DEF(PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::loadBuffer(byte *buffer, bool complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(REGION)
+ TOKEN_TABLE(TEMPLATE)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(ACTIVE)
+ TOKEN_TABLE(POINT)
+ TOKEN_TABLE(CAPTION)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(EDITOR_SELECTED_POINT)
+ TOKEN_TABLE(PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ if (complete) {
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_REGION) {
+ _gameRef->LOG(0, "'REGION' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ }
+
+ for (uint32 i = 0; i < _points.size(); i++) {
+ delete _points[i];
+ }
+ _points.clear();
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_TEMPLATE:
+ if (DID_FAIL(loadFile((char *)params))) {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_NAME:
+ setName((char *)params);
+ break;
+
+ case TOKEN_CAPTION:
+ setCaption((char *)params);
+ break;
+
+ case TOKEN_ACTIVE:
+ parser.scanStr((char *)params, "%b", &_active);
+ break;
+
+ case TOKEN_POINT: {
+ int x, y;
+ parser.scanStr((char *)params, "%d,%d", &x, &y);
+ _points.add(new BasePoint(x, y));
+ }
+ break;
+
+ case TOKEN_SCRIPT:
+ addScript((char *)params);
+ break;
+
+ case TOKEN_EDITOR_SELECTED_POINT:
+ parser.scanStr((char *)params, "%d", &_editorSelectedPoint);
+ break;
+
+ case TOKEN_PROPERTY:
+ parseProperty(params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in REGION definition");
+ return STATUS_FAILED;
+ }
+
+ createRegion();
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddPoint
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "AddPoint") == 0) {
+ stack->correctParams(2);
+ int x = stack->pop()->getInt();
+ int y = stack->pop()->getInt();
+
+ _points.add(new BasePoint(x, y));
+ createRegion();
+
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InsertPoint
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "InsertPoint") == 0) {
+ stack->correctParams(3);
+ int index = stack->pop()->getInt();
+ int x = stack->pop()->getInt();
+ int y = stack->pop()->getInt();
+
+ if (index >= 0 && index < (int32)_points.size()) {
+ _points.insert_at(index, new BasePoint(x, y));
+ createRegion();
+
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPoint
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetPoint") == 0) {
+ stack->correctParams(3);
+ int index = stack->pop()->getInt();
+ int x = stack->pop()->getInt();
+ int y = stack->pop()->getInt();
+
+ if (index >= 0 && index < (int32)_points.size()) {
+ _points[index]->x = x;
+ _points[index]->y = y;
+ createRegion();
+
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemovePoint
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemovePoint") == 0) {
+ stack->correctParams(1);
+ int index = stack->pop()->getInt();
+
+ if (index >= 0 && index < (int32)_points.size()) {
+ delete _points[index];
+ _points[index] = NULL;
+
+ _points.remove_at(index);
+ createRegion();
+
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPoint
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetPoint") == 0) {
+ stack->correctParams(1);
+ int index = stack->pop()->getInt();
+
+ if (index >= 0 && index < (int32)_points.size()) {
+ ScValue *val = stack->getPushValue();
+ if (val) {
+ val->setProperty("X", _points[index]->x);
+ val->setProperty("Y", _points[index]->y);
+ }
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ } else {
+ return BaseObject::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseRegion::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("region");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Name") == 0) {
+ _scValue->setString(getName());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Active
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Active") == 0) {
+ _scValue->setBool(_active);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumPoints
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumPoints") == 0) {
+ _scValue->setInt(_points.size());
+ return _scValue;
+ } else {
+ return BaseObject::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Name") == 0) {
+ setName(value->getString());
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Active
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Active") == 0) {
+ _active = value->getBool();
+ return STATUS_OK;
+ } else {
+ return BaseObject::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseRegion::scToString() {
+ return "[region]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::saveAsText(BaseDynamicBuffer *buffer, int indent, const char *nameOverride) {
+ if (!nameOverride) {
+ buffer->putTextIndent(indent, "REGION {\n");
+ } else {
+ buffer->putTextIndent(indent, "%s {\n", nameOverride);
+ }
+
+ buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName());
+ buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption());
+ buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE");
+ buffer->putTextIndent(indent + 2, "EDITOR_SELECTED_POINT=%d\n", _editorSelectedPoint);
+
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ for (uint32 i = 0; i < _points.size(); i++) {
+ buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y);
+ }
+
+ if (_scProp) {
+ _scProp->saveAsText(buffer, indent + 2);
+ }
+
+ buffer->putTextIndent(indent, "}\n\n");
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::persist(BasePersistenceManager *persistMgr) {
+
+ BaseObject::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_active));
+ persistMgr->transfer(TMEMBER(_editorSelectedPoint));
+ persistMgr->transfer(TMEMBER(_lastMimicScale));
+ persistMgr->transfer(TMEMBER(_lastMimicX));
+ persistMgr->transfer(TMEMBER(_lastMimicY));
+ _points.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+
+typedef struct {
+ double x, y;
+} dPoint;
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::ptInPolygon(int x, int y) {
+ if (_points.size() < 3) {
+ return false;
+ }
+
+ int counter = 0;
+ double xinters;
+ dPoint p, p1, p2;
+
+ p.x = (double)x;
+ p.y = (double)y;
+
+ p1.x = (double)_points[0]->x;
+ p1.y = (double)_points[0]->y;
+
+ for (uint32 i = 1; i <= _points.size(); i++) {
+ p2.x = (double)_points[i % _points.size()]->x;
+ p2.y = (double)_points[i % _points.size()]->y;
+
+ if (p.y > MIN(p1.y, p2.y)) {
+ if (p.y <= MAX(p1.y, p2.y)) {
+ if (p.x <= MAX(p1.x, p2.x)) {
+ if (p1.y != p2.y) {
+ xinters = (p.y - p1.y) * (p2.x - p1.x) / (p2.y - p1.y) + p1.x;
+ if (p1.x == p2.x || p.x <= xinters) {
+ counter++;
+ }
+ }
+ }
+ }
+ }
+ p1 = p2;
+ }
+
+ if (counter % 2 == 0) {
+ return false;
+ } else {
+ return true;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::getBoundingRect(Rect32 *rect) {
+ if (_points.size() == 0) {
+ BasePlatform::setRectEmpty(rect);
+ } else {
+ int minX = INT_MAX, minY = INT_MAX, maxX = INT_MIN, maxY = INT_MIN;
+
+ for (uint32 i = 0; i < _points.size(); i++) {
+ minX = MIN(minX, _points[i]->x);
+ minY = MIN(minY, _points[i]->y);
+
+ maxX = MAX(maxX, _points[i]->x);
+ maxY = MAX(maxY, _points[i]->y);
+ }
+ BasePlatform::setRect(rect, minX, minY, maxX, maxY);
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRegion::mimic(BaseRegion *region, float scale, int x, int y) {
+ if (scale == _lastMimicScale && x == _lastMimicX && y == _lastMimicY) {
+ return STATUS_OK;
+ }
+
+ cleanup();
+
+ for (uint32 i = 0; i < region->_points.size(); i++) {
+ int xVal, yVal;
+
+ xVal = (int)((float)region->_points[i]->x * scale / 100.0f);
+ yVal = (int)((float)region->_points[i]->y * scale / 100.0f);
+
+ _points.add(new BasePoint(xVal + x, yVal + y));
+ }
+
+ _lastMimicScale = scale;
+ _lastMimicX = x;
+ _lastMimicY = y;
+
+ return createRegion() ? STATUS_OK : STATUS_FAILED;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_region.h b/engines/wintermute/base/base_region.h
new file mode 100644
index 0000000000..8dd02fe928
--- /dev/null
+++ b/engines/wintermute/base/base_region.h
@@ -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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_REGION_H
+#define WINTERMUTE_BASE_REGION_H
+
+#include "engines/wintermute/base/base_point.h"
+#include "engines/wintermute/base/base_object.h"
+
+namespace Wintermute {
+
+class BaseRegion : public BaseObject {
+public:
+ float _lastMimicScale;
+ int _lastMimicX;
+ int _lastMimicY;
+ void cleanup();
+ bool mimic(BaseRegion *region, float scale = 100.0f, int x = 0, int y = 0);
+ bool getBoundingRect(Rect32 *rect);
+ bool ptInPolygon(int x, int y);
+ DECLARE_PERSISTENT(BaseRegion, BaseObject)
+ bool _active;
+ int _editorSelectedPoint;
+ BaseRegion(BaseGame *inGame);
+ virtual ~BaseRegion();
+ bool pointInRegion(int x, int y);
+ bool createRegion();
+ bool loadFile(const char *filename);
+ bool loadBuffer(byte *buffer, bool complete = true);
+ Rect32 _rect;
+ BaseArray<BasePoint *> _points;
+ virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent) { return saveAsText(buffer, indent, NULL); }
+ virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent, const char *nameOverride);
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_save_thumb_helper.cpp b/engines/wintermute/base/base_save_thumb_helper.cpp
new file mode 100644
index 0000000000..186e1234a8
--- /dev/null
+++ b/engines/wintermute/base/base_save_thumb_helper.cpp
@@ -0,0 +1,80 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_save_thumb_helper.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/base_game.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseSaveThumbHelper::BaseSaveThumbHelper(BaseGame *inGame) : BaseClass(inGame) {
+ _thumbnail = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseSaveThumbHelper::~BaseSaveThumbHelper(void) {
+ delete _thumbnail;
+ _thumbnail = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSaveThumbHelper::storeThumbnail(bool doFlip) {
+ delete _thumbnail;
+ _thumbnail = NULL;
+
+ if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) {
+ if (doFlip) {
+ // when using opengl on windows it seems to be necessary to do this twice
+ // works normally for direct3d
+ _gameRef->displayContent(false);
+ _gameRef->_renderer->flip();
+
+ _gameRef->displayContent(false);
+ _gameRef->_renderer->flip();
+ }
+
+ BaseImage *screenshot = _gameRef->_renderer->takeScreenshot();
+ if (!screenshot) {
+ return STATUS_FAILED;
+ }
+
+ // normal thumbnail
+ if (_gameRef->_thumbnailWidth > 0 && _gameRef->_thumbnailHeight > 0) {
+ _thumbnail = new BaseImage();
+ _thumbnail->copyFrom(screenshot, _gameRef->_thumbnailWidth, _gameRef->_thumbnailHeight);
+ }
+
+
+ delete screenshot;
+ screenshot = NULL;
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_save_thumb_helper.h b/engines/wintermute/base/base_save_thumb_helper.h
new file mode 100644
index 0000000000..8863508ac9
--- /dev/null
+++ b/engines/wintermute/base/base_save_thumb_helper.h
@@ -0,0 +1,51 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+#ifndef WINTERMUTE_BASE_SAVE_THUMB_HELPER_H
+#define WINTERMUTE_BASE_SAVE_THUMB_HELPER_H
+
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseImage;
+
+class BaseSaveThumbHelper : public BaseClass {
+public:
+ BaseSaveThumbHelper(BaseGame *inGame);
+ virtual ~BaseSaveThumbHelper(void);
+ bool storeThumbnail(bool doFlip = false);
+
+ BaseImage *_thumbnail;
+private:
+ BaseImage *_richThumbnail;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_script_holder.cpp b/engines/wintermute/base/base_script_holder.cpp
new file mode 100644
index 0000000000..d3e6078d43
--- /dev/null
+++ b/engines/wintermute/base/base_script_holder.cpp
@@ -0,0 +1,502 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/ad/ad_game.h"
+#include "engines/wintermute/base/base_script_holder.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_engine.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseScriptHolder, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseScriptHolder::BaseScriptHolder(BaseGame *inGame) : BaseScriptable(inGame) {
+ setName("<unnamed>");
+
+ _freezable = true;
+ _filename = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseScriptHolder::~BaseScriptHolder() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::cleanup() {
+ delete[] _filename;
+ _filename = NULL;
+
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ _scripts[i]->finish(true);
+ _scripts[i]->_owner = NULL;
+ }
+ _scripts.clear();
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////
+void BaseScriptHolder::setFilename(const char *filename) {
+ if (_filename != NULL) {
+ delete[] _filename;
+ _filename = NULL;
+ }
+ if (filename == NULL) {
+ return;
+ }
+ _filename = new char [strlen(filename) + 1];
+ if (_filename != NULL) {
+ strcpy(_filename, filename);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::applyEvent(const char *eventName, bool unbreakable) {
+ int numHandlers = 0;
+
+ bool ret = STATUS_FAILED;
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (!_scripts[i]->_thread) {
+ ScScript *handler = _scripts[i]->invokeEventHandler(eventName, unbreakable);
+ if (handler) {
+ //_scripts.add(handler);
+ numHandlers++;
+ ret = STATUS_OK;
+ }
+ }
+ }
+ if (numHandlers > 0 && unbreakable) {
+ _gameRef->_scEngine->tickUnbreakable();
+ }
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::listen(BaseScriptHolder *param1, uint32 param2) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // DEBUG_CrashMe
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "DEBUG_CrashMe") == 0) {
+ stack->correctParams(0);
+ byte *p = 0;
+ *p = 10;
+ stack->pushNULL();
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ApplyEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ApplyEvent") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ bool ret;
+ ret = applyEvent(val->getString());
+
+ if (DID_SUCCEED(ret)) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CanHandleEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CanHandleEvent") == 0) {
+ stack->correctParams(1);
+ stack->pushBool(canHandleEvent(stack->pop()->getString()));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CanHandleMethod
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CanHandleMethod") == 0) {
+ stack->correctParams(1);
+ stack->pushBool(canHandleMethod(stack->pop()->getString()));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AttachScript
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AttachScript") == 0) {
+ stack->correctParams(1);
+ stack->pushBool(DID_SUCCEED(addScript(stack->pop()->getString())));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DetachScript
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DetachScript") == 0) {
+ stack->correctParams(2);
+ const char *filename = stack->pop()->getString();
+ bool killThreads = stack->pop()->getBool(false);
+ bool ret = false;
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (scumm_stricmp(_scripts[i]->_filename, filename) == 0) {
+ _scripts[i]->finish(killThreads);
+ ret = true;
+ break;
+ }
+ }
+ stack->pushBool(ret);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IsScriptRunning
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IsScriptRunning") == 0) {
+ stack->correctParams(1);
+ const char *filename = stack->pop()->getString();
+ bool ret = false;
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (scumm_stricmp(_scripts[i]->_filename, filename) == 0 && _scripts[i]->_state != SCRIPT_FINISHED && _scripts[i]->_state != SCRIPT_ERROR) {
+ ret = true;
+ break;
+ }
+ }
+ stack->pushBool(ret);
+
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseScriptHolder::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("script_holder");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Name") == 0) {
+ _scValue->setString(getName());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Filename (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Filename") == 0) {
+ _scValue->setString(_filename);
+ return _scValue;
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Name") == 0) {
+ setName(value->getString());
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseScriptHolder::scToString() {
+ return "[script_holder]";
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ return BaseClass::saveAsText(buffer, indent);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::persist(BasePersistenceManager *persistMgr) {
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_filename));
+ persistMgr->transfer(TMEMBER(_freezable));
+ if (persistMgr->getIsSaving()) {
+ const char *name = getName();
+ persistMgr->transfer(TMEMBER(name));
+ } else {
+ char *name;
+ persistMgr->transfer(TMEMBER(name));
+ setName(name);
+ delete[] name;
+ }
+ _scripts.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::addScript(const char *filename) {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (scumm_stricmp(_scripts[i]->_filename, filename) == 0) {
+ if (_scripts[i]->_state != SCRIPT_FINISHED) {
+ _gameRef->LOG(0, "BaseScriptHolder::AddScript - trying to add script '%s' mutiple times (obj: '%s')", filename, getName());
+ return STATUS_OK;
+ }
+ }
+ }
+
+ ScScript *scr = _gameRef->_scEngine->runScript(filename, this);
+ if (!scr) {
+ if (_gameRef->_editorForceScripts) {
+ // editor hack
+ scr = new ScScript(_gameRef, _gameRef->_scEngine);
+ scr->_filename = new char[strlen(filename) + 1];
+ strcpy(scr->_filename, filename);
+ scr->_state = SCRIPT_ERROR;
+ scr->_owner = this;
+ _scripts.add(scr);
+ _gameRef->_scEngine->_scripts.add(scr);
+
+ return STATUS_OK;
+ }
+ return STATUS_FAILED;
+ } else {
+ scr->_freezable = _freezable;
+ _scripts.add(scr);
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::removeScript(ScScript *script) {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i] == script) {
+ _scripts.remove_at(i);
+ break;
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::canHandleEvent(const char *EventName) {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (!_scripts[i]->_thread && _scripts[i]->canHandleEvent(EventName)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::canHandleMethod(const char *MethodName) {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (!_scripts[i]->_thread && _scripts[i]->canHandleMethod(MethodName)) {
+ return true;
+ }
+ }
+ return false;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(PROPERTY)
+TOKEN_DEF(NAME)
+TOKEN_DEF(VALUE)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::parseProperty(byte *buffer, bool complete) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(PROPERTY)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(VALUE)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ if (complete) {
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_PROPERTY) {
+ _gameRef->LOG(0, "'PROPERTY' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ }
+
+ char *propName = NULL;
+ char *propValue = NULL;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_NAME:
+ delete[] propName;
+ propName = new char[strlen((char *)params) + 1];
+ if (propName) {
+ strcpy(propName, (char *)params);
+ } else {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+
+ case TOKEN_VALUE:
+ delete[] propValue;
+ propValue = new char[strlen((char *)params) + 1];
+ if (propValue) {
+ strcpy(propValue, (char *)params);
+ } else {
+ cmd = PARSERR_GENERIC;
+ }
+ break;
+ }
+
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+ _gameRef->LOG(0, "Syntax error in PROPERTY definition");
+ return STATUS_FAILED;
+ }
+ if (cmd == PARSERR_GENERIC || propName == NULL || propValue == NULL) {
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+ _gameRef->LOG(0, "Error loading PROPERTY definition");
+ return STATUS_FAILED;
+ }
+
+
+ ScValue *val = new ScValue(_gameRef);
+ val->setString(propValue);
+ scSetProperty(propName, val);
+
+ delete val;
+ delete[] propName;
+ delete[] propValue;
+ propName = NULL;
+ propValue = NULL;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptHolder::makeFreezable(bool freezable) {
+ _freezable = freezable;
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ _scripts[i]->_freezable = freezable;
+ }
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript *BaseScriptHolder::invokeMethodThread(const char *methodName) {
+ for (int i = _scripts.size() - 1; i >= 0; i--) {
+ if (_scripts[i]->canHandleMethod(methodName)) {
+
+ ScScript *thread = new ScScript(_gameRef, _scripts[i]->_engine);
+ if (thread) {
+ bool ret = thread->createMethodThread(_scripts[i], methodName);
+ if (DID_SUCCEED(ret)) {
+ _scripts[i]->_engine->_scripts.add(thread);
+ return thread;
+ } else {
+ delete thread;
+ }
+ }
+ }
+ }
+ return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptHolder::scDebuggerDesc(char *buf, int bufSize) {
+ strcpy(buf, scToString());
+ if (getName() && strcmp(getName(), "<unnamed>") != 0) {
+ strcat(buf, " Name: ");
+ strcat(buf, getName());
+ }
+ if (_filename) {
+ strcat(buf, " File: ");
+ strcat(buf, _filename);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// IWmeObject
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptHolder::sendEvent(const char *eventName) {
+ return DID_SUCCEED(applyEvent(eventName));
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_script_holder.h b/engines/wintermute/base/base_script_holder.h
new file mode 100644
index 0000000000..0c3d7a1a70
--- /dev/null
+++ b/engines/wintermute/base/base_script_holder.h
@@ -0,0 +1,76 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SCRIPTHOLDER_H
+#define WINTERMUTE_BASE_SCRIPTHOLDER_H
+
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class BaseScriptHolder : public BaseScriptable {
+public:
+ DECLARE_PERSISTENT(BaseScriptHolder, BaseScriptable)
+
+ BaseScriptHolder(BaseGame *inGame);
+ virtual ~BaseScriptHolder();
+ virtual ScScript *invokeMethodThread(const char *methodName);
+ virtual void makeFreezable(bool freezable);
+ bool canHandleEvent(const char *eventName);
+ virtual bool canHandleMethod(const char *eventMethod);
+ bool cleanup();
+ bool removeScript(ScScript *script);
+ bool addScript(const char *filename);
+ virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent);
+ virtual bool listen(BaseScriptHolder *param1, uint32 param2);
+ bool applyEvent(const char *eventName, bool unbreakable = false);
+ void setFilename(const char *filename);
+ const char *getFilename() { return _filename; }
+ bool parseProperty(byte *buffer, bool complete = true);
+ bool _freezable;
+ bool _ready;
+
+ BaseArray<ScScript *> _scripts;
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+ virtual void scDebuggerDesc(char *buf, int bufSize);
+ // IWmeObject
+private:
+ char *_filename;
+public:
+ virtual bool sendEvent(const char *eventName);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_scriptable.cpp b/engines/wintermute/base/base_scriptable.cpp
new file mode 100644
index 0000000000..143934402b
--- /dev/null
+++ b/engines/wintermute/base/base_scriptable.cpp
@@ -0,0 +1,191 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_scriptable.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseScriptable, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseScriptable::BaseScriptable(BaseGame *inGame, bool noValue, bool persistable) : BaseNamedObject(inGame) {
+ _refCount = 0;
+
+ if (noValue) {
+ _scValue = NULL;
+ } else {
+ _scValue = new ScValue(_gameRef);
+ }
+
+ _persistable = persistable;
+
+ _scProp = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseScriptable::~BaseScriptable() {
+ //if (_refCount>0) _gameRef->LOG(0, "Warning: Destroying object, _refCount=%d", _refCount);
+ delete _scValue;
+ delete _scProp;
+ _scValue = NULL;
+ _scProp = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptable::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ /*
+ stack->correctParams(0);
+ stack->pushNULL();
+ script->runtimeError("Call to undefined method '%s'.", name);
+
+ return STATUS_OK;
+ */
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseScriptable::scGetProperty(const char *name) {
+ if (!_scProp) {
+ _scProp = new ScValue(_gameRef);
+ }
+ if (_scProp) {
+ return _scProp->getProp(name);
+ } else {
+ return NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptable::scSetProperty(const char *name, ScValue *value) {
+ if (!_scProp) {
+ _scProp = new ScValue(_gameRef);
+ }
+ if (_scProp) {
+ return _scProp->setProp(name, value);
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseScriptable::scToString() {
+ return "[native object]";
+}
+
+//////////////////////////////////////////////////////////////////////////
+void *BaseScriptable::scToMemBuffer() {
+ return (void *)NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseScriptable::scToInt() {
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+double BaseScriptable::scToFloat() {
+ return 0.0f;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptable::scToBool() {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptable::scSetString(const char *val) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptable::scSetInt(int val) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptable::scSetFloat(double val) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptable::scSetBool(bool val) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptable::persist(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_gameRef));
+ persistMgr->transfer(TMEMBER(_refCount));
+ persistMgr->transfer(TMEMBER(_scProp));
+ persistMgr->transfer(TMEMBER(_scValue));
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseScriptable::scCompare(BaseScriptable *val) {
+ if (this < val) {
+ return -1;
+ } else if (this > val) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseScriptable::scDebuggerDesc(char *buf, int bufSize) {
+ strcpy(buf, scToString());
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseScriptable::canHandleMethod(const char *eventMethod) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript *BaseScriptable::invokeMethodThread(const char *methodName) {
+ return NULL;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_scriptable.h b/engines/wintermute/base/base_scriptable.h
new file mode 100644
index 0000000000..b006e6e07c
--- /dev/null
+++ b/engines/wintermute/base/base_scriptable.h
@@ -0,0 +1,83 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SCRIPTABLE_H
+#define WINTERMUTE_BASE_SCRIPTABLE_H
+
+
+#include "engines/wintermute/base/base_named_object.h"
+#include "engines/wintermute/persistent.h"
+
+namespace Wintermute {
+
+class ScValue;
+class ScStack;
+class ScScript;
+
+class BaseScriptable : public BaseNamedObject {
+public:
+ virtual ScScript *invokeMethodThread(const char *methodName);
+ DECLARE_PERSISTENT(BaseScriptable, BaseNamedObject)
+
+ BaseScriptable(BaseGame *inGame, bool noValue = false, bool persistable = true);
+ virtual ~BaseScriptable();
+
+ // high level scripting interface
+ virtual bool canHandleMethod(const char *eventMethod);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+ virtual void *scToMemBuffer();
+ virtual int scToInt();
+ virtual double scToFloat();
+ virtual bool scToBool();
+ virtual void scSetString(const char *val);
+ virtual void scSetInt(int val);
+ virtual void scSetFloat(double val);
+ virtual void scSetBool(bool val);
+ virtual int scCompare(BaseScriptable *val);
+ virtual void scDebuggerDesc(char *buf, int bufSize);
+ int _refCount;
+ ScValue *_scValue;
+ ScValue *_scProp;
+};
+
+// Implemented in their respective .cpp-files
+BaseScriptable *makeSXArray(BaseGame *inGame, ScStack *stack);
+BaseScriptable *makeSXDate(BaseGame *inGame, ScStack *stack);
+BaseScriptable *makeSXFile(BaseGame *inGame, ScStack *stack);
+BaseScriptable *makeSXMath(BaseGame *inGame);
+BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack);
+BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack);
+BaseScriptable *makeSXStore(BaseGame *inGame);
+BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack);
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_sprite.cpp b/engines/wintermute/base/base_sprite.cpp
new file mode 100644
index 0000000000..e2dd8bbd39
--- /dev/null
+++ b/engines/wintermute/base/base_sprite.cpp
@@ -0,0 +1,814 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/utils/path_util.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_frame.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseSprite, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseSprite::BaseSprite(BaseGame *inGame, BaseObject *Owner) : BaseScriptHolder(inGame) {
+ _editorAllFrames = false;
+ _owner = Owner;
+ setDefaults();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseSprite::~BaseSprite() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSprite::setDefaults() {
+ _currentFrame = -1;
+ _looping = false;
+ _lastFrameTime = 0;
+ setFilename(NULL);
+ _finished = false;
+ _changed = false;
+ _paused = false;
+ _continuous = false;
+ _moveX = _moveY = 0;
+
+ _editorMuted = false;
+ _editorBgFile = NULL;
+ _editorBgOffsetX = _editorBgOffsetY = 0;
+ _editorBgAlpha = 0xFF;
+ _streamed = false;
+ _streamedKeepLoaded = false;
+
+ setName("");
+
+ _precise = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSprite::cleanup() {
+ BaseScriptHolder::cleanup();
+
+ for (uint32 i = 0; i < _frames.size(); i++) {
+ delete _frames[i];
+ }
+ _frames.clear();
+
+ delete[] _editorBgFile;
+ _editorBgFile = NULL;
+
+ setDefaults();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, uint32 alpha) {
+ getCurrentFrame(zoomX, zoomY);
+ if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) {
+ return STATUS_OK;
+ }
+
+ // move owner if allowed to
+ if (_changed && _owner && _owner->_movable) {
+ _owner->_posX += _moveX;
+ _owner->_posY += _moveY;
+ _owner->afterMove();
+
+ x = _owner->_posX;
+ y = _owner->_posY;
+ }
+
+ // draw frame
+ return display(x, y, registerOwner, zoomX, zoomY, alpha);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSprite::loadFile(const Common::String &filename, int lifeTime, TSpriteCacheType cacheType) {
+ Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(filename);
+ if (!file) {
+ _gameRef->LOG(0, "BaseSprite::LoadFile failed for file '%s'", filename.c_str());
+ if (_gameRef->_debugDebugMode) {
+ return loadFile("invalid_debug.bmp", lifeTime, cacheType);
+ } else {
+ return loadFile("invalid.bmp", lifeTime, cacheType);
+ }
+ } else {
+ BaseFileManager::getEngineInstance()->closeFile(file);
+ file = NULL;
+ }
+
+ bool ret = STATUS_FAILED;
+
+ AnsiString filePrefix = filename;
+ AnsiString ext = PathUtil::getExtension(filename);
+ ext.toLowercase();
+ filePrefix.toLowercase();
+ if (filePrefix.hasPrefix("savegame:") || (ext == "bmp") || (ext == "tga") || (ext == "png") || (ext == "jpg")) {
+ BaseFrame *frame = new BaseFrame(_gameRef);
+ BaseSubFrame *subframe = new BaseSubFrame(_gameRef);
+ subframe->setSurface(filename, true, 0, 0, 0, lifeTime, true);
+ if (subframe->_surface == NULL) {
+ _gameRef->LOG(0, "Error loading simple sprite '%s'", filename.c_str());
+ ret = STATUS_FAILED;
+ delete frame;
+ delete subframe;
+ } else {
+ subframe->setDefaultRect();
+ frame->_subframes.add(subframe);
+ _frames.add(frame);
+ _currentFrame = 0;
+ ret = STATUS_OK;
+ }
+ } else {
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer) {
+ if (DID_FAIL(ret = loadBuffer(buffer, true, lifeTime, cacheType))) {
+ _gameRef->LOG(0, "Error parsing SPRITE file '%s'", filename.c_str());
+ } else {
+ ret = STATUS_OK;
+ }
+ delete[] buffer;
+ }
+ }
+
+ setFilename(filename.c_str());
+
+ return ret;
+}
+
+
+
+TOKEN_DEF_START
+TOKEN_DEF(CONTINUOUS)
+TOKEN_DEF(SPRITE)
+TOKEN_DEF(LOOPING)
+TOKEN_DEF(FRAME)
+TOKEN_DEF(NAME)
+TOKEN_DEF(PRECISE)
+TOKEN_DEF(EDITOR_MUTED)
+TOKEN_DEF(STREAMED_KEEP_LOADED)
+TOKEN_DEF(STREAMED)
+TOKEN_DEF(SCRIPT)
+TOKEN_DEF(EDITOR_BG_FILE)
+TOKEN_DEF(EDITOR_BG_OFFSET_X)
+TOKEN_DEF(EDITOR_BG_OFFSET_Y)
+TOKEN_DEF(EDITOR_BG_ALPHA)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////
+bool BaseSprite::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(CONTINUOUS)
+ TOKEN_TABLE(SPRITE)
+ TOKEN_TABLE(LOOPING)
+ TOKEN_TABLE(FRAME)
+ TOKEN_TABLE(NAME)
+ TOKEN_TABLE(PRECISE)
+ TOKEN_TABLE(EDITOR_MUTED)
+ TOKEN_TABLE(STREAMED_KEEP_LOADED)
+ TOKEN_TABLE(STREAMED)
+ TOKEN_TABLE(SCRIPT)
+ TOKEN_TABLE(EDITOR_BG_FILE)
+ TOKEN_TABLE(EDITOR_BG_OFFSET_X)
+ TOKEN_TABLE(EDITOR_BG_OFFSET_Y)
+ TOKEN_TABLE(EDITOR_BG_ALPHA)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ byte *params;
+ int cmd;
+ BaseParser parser;
+
+ cleanup();
+
+
+ if (complete) {
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_SPRITE) {
+ _gameRef->LOG(0, "'SPRITE' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = params;
+ }
+
+ int frameCount = 1;
+ BaseFrame *frame;
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_CONTINUOUS:
+ parser.scanStr((char *)params, "%b", &_continuous);
+ break;
+
+ case TOKEN_EDITOR_MUTED:
+ parser.scanStr((char *)params, "%b", &_editorMuted);
+ break;
+
+ case TOKEN_SCRIPT:
+ addScript((char *)params);
+ break;
+
+ case TOKEN_LOOPING:
+ parser.scanStr((char *)params, "%b", &_looping);
+ break;
+
+ case TOKEN_PRECISE:
+ parser.scanStr((char *)params, "%b", &_precise);
+ break;
+
+ case TOKEN_STREAMED:
+ parser.scanStr((char *)params, "%b", &_streamed);
+ if (_streamed && lifeTime == -1) {
+ lifeTime = 500;
+ cacheType = CACHE_ALL;
+ }
+ break;
+
+ case TOKEN_STREAMED_KEEP_LOADED:
+ parser.scanStr((char *)params, "%b", &_streamedKeepLoaded);
+ break;
+
+ case TOKEN_NAME:
+ setName((char *)params);
+ break;
+
+ case TOKEN_EDITOR_BG_FILE:
+ if (_gameRef->_editorMode) {
+ delete[] _editorBgFile;
+ _editorBgFile = new char[strlen((char *)params) + 1];
+ if (_editorBgFile) {
+ strcpy(_editorBgFile, (char *)params);
+ }
+ }
+ break;
+
+ case TOKEN_EDITOR_BG_OFFSET_X:
+ parser.scanStr((char *)params, "%d", &_editorBgOffsetX);
+ break;
+
+ case TOKEN_EDITOR_BG_OFFSET_Y:
+ parser.scanStr((char *)params, "%d", &_editorBgOffsetY);
+ break;
+
+ case TOKEN_EDITOR_BG_ALPHA:
+ parser.scanStr((char *)params, "%d", &_editorBgAlpha);
+ _editorBgAlpha = MIN(_editorBgAlpha, 255);
+ _editorBgAlpha = MAX(_editorBgAlpha, 0);
+ break;
+
+ case TOKEN_FRAME: {
+ int frameLifeTime = lifeTime;
+ if (cacheType == CACHE_HALF && frameCount % 2 != 1) {
+ frameLifeTime = -1;
+ }
+
+ frame = new BaseFrame(_gameRef);
+
+ if (DID_FAIL(frame->loadBuffer(params, frameLifeTime, _streamedKeepLoaded))) {
+ delete frame;
+ _gameRef->LOG(0, "Error parsing frame %d", frameCount);
+ return STATUS_FAILED;
+ }
+
+ _frames.add(frame);
+ frameCount++;
+ if (_currentFrame == -1) {
+ _currentFrame = 0;
+ }
+ }
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ parseEditorProperty(params, false);
+ break;
+ }
+ }
+
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in SPRITE definition");
+ return STATUS_FAILED;
+ }
+ _canBreak = !_continuous;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseSprite::reset() {
+ if (_frames.size() > 0) {
+ _currentFrame = 0;
+ } else {
+ _currentFrame = -1;
+ }
+
+ killAllSounds();
+
+ _lastFrameTime = 0;
+ _finished = false;
+ _moveX = _moveY = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSprite::getCurrentFrame(float zoomX, float zoomY) {
+ //if (_owner && _owner->_freezable && _gameRef->_state == GAME_FROZEN) return true;
+
+ if (_currentFrame == -1) {
+ return false;
+ }
+
+ uint32 timer;
+ if (_owner && _owner->_freezable) {
+ timer = _gameRef->_timer;
+ } else {
+ timer = _gameRef->_liveTimer;
+ }
+
+ int lastFrame = _currentFrame;
+
+ // get current frame
+ if (!_paused && !_finished && timer >= _lastFrameTime + _frames[_currentFrame]->_delay && _lastFrameTime != 0) {
+ if (_currentFrame < (int32)_frames.size() - 1) {
+ _currentFrame++;
+ if (_continuous) {
+ _canBreak = (_currentFrame == (int32)_frames.size() - 1);
+ }
+ } else {
+ if (_looping) {
+ _currentFrame = 0;
+ _canBreak = true;
+ } else {
+ _finished = true;
+ _canBreak = true;
+ }
+ }
+
+ _lastFrameTime = timer;
+ }
+
+ _changed = (lastFrame != _currentFrame || (_looping && (int32)_frames.size() == 1));
+
+ if (_lastFrameTime == 0) {
+ _lastFrameTime = timer;
+ _changed = true;
+ if (_continuous) {
+ _canBreak = (_currentFrame == (int32)_frames.size() - 1);
+ }
+ }
+
+ if (_changed) {
+ _moveX = _frames[_currentFrame]->_moveX;
+ _moveY = _frames[_currentFrame]->_moveY;
+
+ if (zoomX != 100 || zoomY != 100) {
+ _moveX = (int)((float)_moveX * (float)(zoomX / 100.0f));
+ _moveY = (int)((float)_moveY * (float)(zoomY / 100.0f));
+ }
+ }
+
+ return _changed;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSprite::display(int x, int y, BaseObject *registerVal, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
+ if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) {
+ return STATUS_OK;
+ }
+
+ // on change...
+ if (_changed) {
+ if (_frames[_currentFrame]->_killSound) {
+ killAllSounds();
+ }
+ applyEvent("FrameChanged");
+ _frames[_currentFrame]->oneTimeDisplay(_owner, _gameRef->_editorMode && _editorMuted);
+ }
+
+ // draw frame
+ return _frames[_currentFrame]->draw(x - _gameRef->_offsetX, y - _gameRef->_offsetY, registerVal, zoomX, zoomY, _precise, alpha, _editorAllFrames, rotate, blendMode);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSurface *BaseSprite::getSurface() {
+ // only used for animated textures for 3D models
+ if (_currentFrame < 0 || _currentFrame >= (int32)_frames.size()) {
+ return NULL;
+ }
+ BaseFrame *frame = _frames[_currentFrame];
+ if (frame && frame->_subframes.size() > 0) {
+ BaseSubFrame *subframe = frame->_subframes[0];
+ if (subframe) {
+ return subframe->_surface;
+ } else {
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) {
+ if (!rect) {
+ return false;
+ }
+
+ BasePlatform::setRectEmpty(rect);
+ for (uint32 i = 0; i < _frames.size(); i++) {
+ Rect32 frame;
+ Rect32 temp;
+ BasePlatform::copyRect(&temp, rect);
+ _frames[i]->getBoundingRect(&frame, x, y, scaleX, scaleY);
+ BasePlatform::unionRect(rect, &temp, &frame);
+ }
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ buffer->putTextIndent(indent, "SPRITE {\n");
+ buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName());
+ buffer->putTextIndent(indent + 2, "LOOPING=%s\n", _looping ? "TRUE" : "FALSE");
+ buffer->putTextIndent(indent + 2, "CONTINUOUS=%s\n", _continuous ? "TRUE" : "FALSE");
+ buffer->putTextIndent(indent + 2, "PRECISE=%s\n", _precise ? "TRUE" : "FALSE");
+ if (_streamed) {
+ buffer->putTextIndent(indent + 2, "STREAMED=%s\n", _streamed ? "TRUE" : "FALSE");
+
+ if (_streamedKeepLoaded) {
+ buffer->putTextIndent(indent + 2, "STREAMED_KEEP_LOADED=%s\n", _streamedKeepLoaded ? "TRUE" : "FALSE");
+ }
+ }
+
+ if (_editorMuted) {
+ buffer->putTextIndent(indent + 2, "EDITOR_MUTED=%s\n", _editorMuted ? "TRUE" : "FALSE");
+ }
+
+ if (_editorBgFile) {
+ buffer->putTextIndent(indent + 2, "EDITOR_BG_FILE=\"%s\"\n", _editorBgFile);
+ buffer->putTextIndent(indent + 2, "EDITOR_BG_OFFSET_X=%d\n", _editorBgOffsetX);
+ buffer->putTextIndent(indent + 2, "EDITOR_BG_OFFSET_Y=%d\n", _editorBgOffsetY);
+ buffer->putTextIndent(indent + 2, "EDITOR_BG_ALPHA=%d\n", _editorBgAlpha);
+ }
+
+ BaseScriptHolder::saveAsText(buffer, indent + 2);
+
+ // scripts
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename);
+ }
+
+ for (uint32 i = 0; i < _frames.size(); i++) {
+ _frames[i]->saveAsText(buffer, indent + 2);
+ }
+
+ buffer->putTextIndent(indent, "}\n\n");
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::persist(BasePersistenceManager *persistMgr) {
+ BaseScriptHolder::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_canBreak));
+ persistMgr->transfer(TMEMBER(_changed));
+ persistMgr->transfer(TMEMBER(_paused));
+ persistMgr->transfer(TMEMBER(_continuous));
+ persistMgr->transfer(TMEMBER(_currentFrame));
+ persistMgr->transfer(TMEMBER(_editorAllFrames));
+ persistMgr->transfer(TMEMBER(_editorBgAlpha));
+ persistMgr->transfer(TMEMBER(_editorBgFile));
+ persistMgr->transfer(TMEMBER(_editorBgOffsetX));
+ persistMgr->transfer(TMEMBER(_editorBgOffsetY));
+ persistMgr->transfer(TMEMBER(_editorMuted));
+ persistMgr->transfer(TMEMBER(_finished));
+
+ _frames.persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_lastFrameTime));
+ persistMgr->transfer(TMEMBER(_looping));
+ persistMgr->transfer(TMEMBER(_moveX));
+ persistMgr->transfer(TMEMBER(_moveY));
+ persistMgr->transfer(TMEMBER(_owner));
+ persistMgr->transfer(TMEMBER(_precise));
+ persistMgr->transfer(TMEMBER(_streamed));
+ persistMgr->transfer(TMEMBER(_streamedKeepLoaded));
+
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetFrame
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "GetFrame") == 0) {
+ stack->correctParams(1);
+ int index = stack->pop()->getInt(-1);
+ if (index < 0 || index >= (int32)_frames.size()) {
+ script->runtimeError("Sprite.GetFrame: Frame index %d is out of range.", index);
+ stack->pushNULL();
+ } else {
+ stack->pushNative(_frames[index], true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DeleteFrame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DeleteFrame") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ if (val->isInt()) {
+ int index = val->getInt(-1);
+ if (index < 0 || index >= (int32)_frames.size()) {
+ script->runtimeError("Sprite.DeleteFrame: Frame index %d is out of range.", index);
+ }
+ } else {
+ BaseFrame *frame = (BaseFrame *)val->getNative();
+ for (uint32 i = 0; i < _frames.size(); i++) {
+ if (_frames[i] == frame) {
+ if (i == (uint32)_currentFrame) {
+ _lastFrameTime = 0;
+ }
+ delete _frames[i];
+ _frames.remove_at(i);
+ break;
+ }
+ }
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Reset
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Reset") == 0) {
+ stack->correctParams(0);
+ reset();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddFrame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddFrame") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ const char *filename = NULL;
+ if (!val->isNULL()) {
+ filename = val->getString();
+ }
+
+ BaseFrame *frame = new BaseFrame(_gameRef);
+ if (filename != NULL) {
+ BaseSubFrame *sub = new BaseSubFrame(_gameRef);
+ if (DID_SUCCEED(sub->setSurface(filename))) {
+ sub->setDefaultRect();
+ frame->_subframes.add(sub);
+ } else {
+ delete sub;
+ }
+ }
+ _frames.add(frame);
+
+ stack->pushNative(frame, true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // InsertFrame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "InsertFrame") == 0) {
+ stack->correctParams(2);
+ int index = stack->pop()->getInt();
+ if (index < 0) {
+ index = 0;
+ }
+
+ ScValue *val = stack->pop();
+ const char *filename = NULL;
+ if (!val->isNULL()) {
+ filename = val->getString();
+ }
+
+ BaseFrame *frame = new BaseFrame(_gameRef);
+ if (filename != NULL) {
+ BaseSubFrame *sub = new BaseSubFrame(_gameRef);
+ if (DID_SUCCEED(sub->setSurface(filename))) {
+ frame->_subframes.add(sub);
+ } else {
+ delete sub;
+ }
+ }
+
+ if (index >= (int32)_frames.size()) {
+ _frames.add(frame);
+ } else {
+ _frames.insert_at(index, frame);
+ }
+
+ stack->pushNative(frame, true);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Pause
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Pause") == 0) {
+ stack->correctParams(0);
+ _paused = true;
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Play
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Play") == 0) {
+ stack->correctParams(0);
+ _paused = false;
+ stack->pushNULL();
+ return STATUS_OK;
+ } else {
+ return BaseScriptHolder::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseSprite::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("sprite");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // NumFrames (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumFrames") == 0) {
+ _scValue->setInt(_frames.size());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // CurrentFrame
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "CurrentFrame") == 0) {
+ _scValue->setInt(_currentFrame);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PixelPerfect") == 0) {
+ _scValue->setBool(_precise);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Looping
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Looping") == 0) {
+ _scValue->setBool(_looping);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Owner (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Owner") == 0) {
+ if (_owner == NULL) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setNative(_owner, true);
+ }
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Finished (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Finished") == 0) {
+ _scValue->setBool(_finished);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Paused (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Paused") == 0) {
+ _scValue->setBool(_paused);
+ return _scValue;
+ } else {
+ return BaseScriptHolder::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // CurrentFrame
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "CurrentFrame") == 0) {
+ _currentFrame = value->getInt(0);
+ if (_currentFrame >= (int32)_frames.size() || _currentFrame < 0) {
+ _currentFrame = -1;
+ }
+ _lastFrameTime = 0;
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PixelPerfect
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PixelPerfect") == 0) {
+ _precise = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Looping
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Looping") == 0) {
+ _looping = value->getBool();
+ return STATUS_OK;
+ } else {
+ return BaseScriptHolder::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseSprite::scToString() {
+ return "[sprite]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSprite::killAllSounds() {
+ for (uint32 i = 0; i < _frames.size(); i++) {
+ if (_frames[i]->_sound) {
+ _frames[i]->_sound->stop();
+ }
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_sprite.h b/engines/wintermute/base/base_sprite.h
new file mode 100644
index 0000000000..c861ca9930
--- /dev/null
+++ b/engines/wintermute/base/base_sprite.h
@@ -0,0 +1,90 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SPRITE_H
+#define WINTERMUTE_BASE_SPRITE_H
+
+
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/base/base_script_holder.h"
+
+namespace Wintermute {
+class BaseFrame;
+class BaseSurface;
+class BaseObject;
+class BaseSprite: public BaseScriptHolder {
+public:
+ bool killAllSounds();
+ BaseSurface *getSurface();
+ char *_editorBgFile;
+ int _editorBgOffsetX;
+ int _editorBgOffsetY;
+ int _editorBgAlpha;
+ bool _streamed;
+ bool _streamedKeepLoaded;
+ void cleanup();
+ void setDefaults();
+ bool _precise;
+ DECLARE_PERSISTENT(BaseSprite, BaseScriptHolder)
+
+ bool _editorAllFrames;
+ bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
+ int _moveY;
+ int _moveX;
+ bool display(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool getCurrentFrame(float zoomX = 100, float zoomY = 100);
+ bool _canBreak;
+ bool _editorMuted;
+ bool _continuous;
+ void reset();
+ BaseObject *_owner;
+ bool _changed;
+ bool _paused;
+ bool _finished;
+ bool loadBuffer(byte *buffer, bool compete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
+ bool loadFile(const Common::String &filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL);
+ uint32 _lastFrameTime;
+ bool draw(int x, int y, BaseObject *Register = NULL, float zoomX = 100, float zoomY = 100, uint32 alpha = 0xFFFFFFFF);
+ bool _looping;
+ int _currentFrame;
+ bool addFrame(const char *filename, uint32 delay = 0, int hotspotX = 0, int hotspotY = 0, Rect32 *rect = NULL);
+ BaseSprite(BaseGame *inGame, BaseObject *owner = NULL);
+ virtual ~BaseSprite();
+ BaseArray<BaseFrame *> _frames;
+ bool saveAsText(BaseDynamicBuffer *buffer, int indent);
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_string_table.cpp b/engines/wintermute/base/base_string_table.cpp
new file mode 100644
index 0000000000..2f890beea1
--- /dev/null
+++ b/engines/wintermute/base/base_string_table.cpp
@@ -0,0 +1,255 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_string_table.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseStringTable::BaseStringTable(BaseGame *inGame) : BaseClass(inGame) {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseStringTable::~BaseStringTable() {
+ // delete strings
+ _strings.clear();
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseStringTable::addString(const char *key, const char *val, bool reportDuplicities) {
+ if (key == NULL || val == NULL) {
+ return STATUS_FAILED;
+ }
+
+ if (scumm_stricmp(key, "@right-to-left") == 0) {
+ _gameRef->_textRTL = true;
+ return STATUS_OK;
+ }
+
+ Common::String finalKey = key;
+ finalKey.toLowercase();
+
+ StringsIter it = _strings.find(finalKey);
+ if (it != _strings.end() && reportDuplicities) {
+ _gameRef->LOG(0, " Warning: Duplicate definition of string '%s'.", finalKey.c_str());
+ }
+
+ _strings[finalKey] = val;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+char *BaseStringTable::getKey(const char *str) const {
+ if (str == NULL || str[0] != '/') {
+ return NULL;
+ }
+
+ const char *value = strchr(str + 1, '/');
+ if (value == NULL) {
+ return NULL;
+ }
+
+ char *key = new char[value - str];
+ Common::strlcpy(key, str + 1, (size_t)(value - str));
+
+ BasePlatform::strlwr(key);
+
+ char *newStr;
+
+ StringsIter it = _strings.find(key);
+ if (it != _strings.end()) {
+ newStr = new char[it->_value.size() + 1];
+ strcpy(newStr, it->_value.c_str());
+ if (strlen(newStr) > 0 && newStr[0] == '/' && strchr(newStr + 1, '/')) {
+ delete[] key;
+ char *ret = getKey(newStr);
+ delete[] newStr;
+ return ret;
+ } else {
+ delete[] newStr;
+ return key;
+ }
+ } else {
+ return key;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseStringTable::expand(char **str) const {
+ if (str == NULL || *str == NULL || *str[0] != '/') {
+ return;
+ }
+
+ char *value = strchr(*str + 1, '/');
+ if (value == NULL) {
+ return;
+ }
+
+ char *key = new char[value - *str];
+ Common::strlcpy(key, *str + 1, (size_t)(value - *str));
+
+ BasePlatform::strlwr(key);
+
+ value++;
+
+ char *newStr;
+
+ StringsIter it = _strings.find(key);
+ if (it != _strings.end()) {
+ newStr = new char[it->_value.size() + 1];
+ strcpy(newStr, it->_value.c_str());
+ } else {
+ newStr = new char[strlen(value) + 1];
+ strcpy(newStr, value);
+ }
+
+ delete[] key;
+ delete[] *str;
+ *str = newStr;
+
+ if (strlen(*str) > 0 && *str[0] == '/') {
+ expand(str);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseStringTable::expandStatic(const char *string) const {
+ if (string == NULL || string[0] == '\0' || string[0] != '/') {
+ return string;
+ }
+
+ const char *value = strchr(string + 1, '/');
+ if (value == NULL) {
+ return string;
+ }
+
+ char *key = new char[value - string];
+ Common::strlcpy(key, string + 1, (size_t)(value - string - 1));
+ BasePlatform::strlwr(key);
+
+ value++;
+
+ const char *newStr;
+
+ StringsIter it = _strings.find(key);
+ if (it != _strings.end()) {
+ newStr = it->_value.c_str();
+ } else {
+ newStr = value;
+ }
+
+ delete[] key;
+
+ if (strlen(newStr) > 0 && newStr[0] == '/') {
+ return expandStatic(newStr);
+ } else {
+ return newStr;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseStringTable::loadFile(const char *filename, bool clearOld) {
+ _gameRef->LOG(0, "Loading string table...");
+
+ if (clearOld) {
+ _strings.clear();
+ }
+
+ uint32 size;
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename, &size);
+ if (buffer == NULL) {
+ _gameRef->LOG(0, "BaseStringTable::LoadFile failed for file '%s'", filename);
+ return STATUS_FAILED;
+ }
+
+ uint32 pos = 0;
+
+ if (size > 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) {
+ pos += 3;
+ if (_gameRef->_textEncoding != TEXT_UTF8) {
+ _gameRef->_textEncoding = TEXT_UTF8;
+ //_gameRef->_textEncoding = TEXT_ANSI;
+ _gameRef->LOG(0, " UTF8 file detected, switching to UTF8 text encoding");
+ }
+ } else {
+ _gameRef->_textEncoding = TEXT_ANSI;
+ }
+
+ uint32 lineLength = 0;
+ while (pos < size) {
+ lineLength = 0;
+ while (pos + lineLength < size && buffer[pos + lineLength] != '\n' && buffer[pos + lineLength] != '\0') {
+ lineLength++;
+ }
+
+ uint32 realLength = lineLength - (pos + lineLength >= size ? 0 : 1);
+ char *line = new char[realLength + 1];
+ Common::strlcpy(line, (char *)&buffer[pos], realLength + 1);
+ char *value = strchr(line, '\t');
+ if (value == NULL) {
+ value = strchr(line, ' ');
+ }
+
+ if (line[0] != ';') {
+ if (value != NULL) {
+ value[0] = '\0';
+ value++;
+ for (uint32 i = 0; i < strlen(value); i++) {
+ if (value[i] == '|') {
+ value[i] = '\n';
+ }
+ }
+ addString(line, value, clearOld);
+ } else if (line[0] != '\0') {
+ addString(line, "", clearOld);
+ }
+ }
+
+ delete[] line;
+ pos += lineLength + 1;
+ }
+
+ delete[] buffer;
+
+ _gameRef->LOG(0, " %d strings loaded", _strings.size());
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_string_table.h b/engines/wintermute/base/base_string_table.h
new file mode 100644
index 0000000000..128807bd1a
--- /dev/null
+++ b/engines/wintermute/base/base_string_table.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_STRING_TABLE_H
+#define WINTERMUTE_BASE_STRING_TABLE_H
+
+
+#include "common/hashmap.h"
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseStringTable : public BaseClass {
+public:
+ bool loadFile(const char *filename, bool deleteAll = true);
+ void expand(char **str) const;
+ const char *expandStatic(const char *string) const;
+ bool addString(const char *key, const char *val, bool reportDuplicities = true);
+ BaseStringTable(BaseGame *inGame);
+ virtual ~BaseStringTable();
+ char *getKey(const char *str) const;
+private:
+ Common::HashMap<Common::String, Common::String> _strings;
+ typedef Common::HashMap<Common::String, Common::String>::const_iterator StringsIter;
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_sub_frame.cpp b/engines/wintermute/base/base_sub_frame.cpp
new file mode 100644
index 0000000000..6a9246efd4
--- /dev/null
+++ b/engines/wintermute/base/base_sub_frame.cpp
@@ -0,0 +1,655 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_active_rect.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseSubFrame, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseSubFrame::BaseSubFrame(BaseGame *inGame) : BaseScriptable(inGame, true) {
+ _surface = NULL;
+ _hotspotX = _hotspotY = 0;
+ _alpha = 0xFFFFFFFF;
+ _transparent = 0xFFFF00FF;
+
+ _wantsDefaultRect = false;
+ BasePlatform::setRectEmpty(&_rect);
+
+ _editorSelected = false;
+
+ _surfaceFilename = NULL;
+ _cKDefault = true;
+ _cKRed = _cKBlue = _cKGreen = 0;
+ _lifeTime = -1;
+ _keepLoaded = false;
+
+ _2DOnly = _3DOnly = false;
+ _decoration = false;
+
+ _mirrorX = _mirrorY = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSubFrame::~BaseSubFrame() {
+ if (_surface) {
+ _gameRef->_surfaceStorage->removeSurface(_surface);
+ }
+ delete[] _surfaceFilename;
+ _surfaceFilename = NULL;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(TRANSPARENT)
+TOKEN_DEF(RECT)
+TOKEN_DEF(HOTSPOT)
+TOKEN_DEF(2D_ONLY)
+TOKEN_DEF(3D_ONLY)
+TOKEN_DEF(DECORATION)
+TOKEN_DEF(ALPHA_COLOR)
+TOKEN_DEF(ALPHA)
+TOKEN_DEF(MIRROR_X)
+TOKEN_DEF(MIRROR_Y)
+TOKEN_DEF(EDITOR_SELECTED)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::loadBuffer(byte *buffer, int lifeTime, bool keepLoaded) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(TRANSPARENT)
+ TOKEN_TABLE(RECT)
+ TOKEN_TABLE(HOTSPOT)
+ TOKEN_TABLE(2D_ONLY)
+ TOKEN_TABLE(3D_ONLY)
+ TOKEN_TABLE(DECORATION)
+ TOKEN_TABLE(ALPHA_COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE(MIRROR_X)
+ TOKEN_TABLE(MIRROR_Y)
+ TOKEN_TABLE(EDITOR_SELECTED)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE_END
+
+ char *params;
+ int cmd;
+ BaseParser parser;
+ Rect32 rect;
+ int r = 255, g = 255, b = 255;
+ int ar = 255, ag = 255, ab = 255, alpha = 255;
+ bool custoTrans = false;
+ BasePlatform::setRectEmpty(&rect);
+ char *surfaceFile = NULL;
+
+ delete _surface;
+ _surface = NULL;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, &params)) > 0) {
+ switch (cmd) {
+ case TOKEN_IMAGE:
+ surfaceFile = params;
+ break;
+
+ case TOKEN_TRANSPARENT:
+ parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
+ custoTrans = true;
+ break;
+
+ case TOKEN_RECT:
+ parser.scanStr(params, "%d,%d,%d,%d", &rect.left, &rect.top, &rect.right, &rect.bottom);
+ break;
+
+ case TOKEN_HOTSPOT:
+ parser.scanStr(params, "%d,%d", &_hotspotX, &_hotspotY);
+ break;
+
+ case TOKEN_2D_ONLY:
+ parser.scanStr(params, "%b", &_2DOnly);
+ break;
+
+ case TOKEN_3D_ONLY:
+ parser.scanStr(params, "%b", &_3DOnly);
+ break;
+
+ case TOKEN_MIRROR_X:
+ parser.scanStr(params, "%b", &_mirrorX);
+ break;
+
+ case TOKEN_MIRROR_Y:
+ parser.scanStr(params, "%b", &_mirrorY);
+ break;
+
+ case TOKEN_DECORATION:
+ parser.scanStr(params, "%b", &_decoration);
+ break;
+
+ case TOKEN_ALPHA_COLOR:
+ parser.scanStr(params, "%d,%d,%d", &ar, &ag, &ab);
+ break;
+
+ case TOKEN_ALPHA:
+ parser.scanStr(params, "%d", &alpha);
+ break;
+
+ case TOKEN_EDITOR_SELECTED:
+ parser.scanStr(params, "%b", &_editorSelected);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ parseEditorProperty((byte *)params, false);
+ break;
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in SUBFRAME definition");
+ return STATUS_FAILED;
+ }
+
+ if (surfaceFile != NULL) {
+ if (custoTrans) {
+ setSurface(surfaceFile, false, r, g, b, lifeTime, keepLoaded);
+ } else {
+ setSurface(surfaceFile, true, 0, 0, 0, lifeTime, keepLoaded);
+ }
+ }
+
+ _alpha = BYTETORGBA(ar, ag, ab, alpha);
+ if (custoTrans) {
+ _transparent = BYTETORGBA(r, g, b, 0xFF);
+ }
+
+ /*
+ if (_surface == NULL)
+ {
+ _gameRef->LOG(0, "Error parsing sub-frame. Image not set.");
+ return STATUS_FAILED;
+ }
+ */
+ if (BasePlatform::isRectEmpty(&rect)) {
+ setDefaultRect();
+ } else {
+ setRect(rect);
+ }
+
+ return STATUS_OK;
+}
+
+Rect32 BaseSubFrame::getRect() {
+ if (_wantsDefaultRect && _surface) {
+ BasePlatform::setRect(&_rect, 0, 0, _surface->getWidth(), _surface->getHeight());
+ _wantsDefaultRect = false;
+ }
+ return _rect;
+}
+
+void BaseSubFrame::setRect(Rect32 rect) {
+ _wantsDefaultRect = false;
+ _rect = rect;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::draw(int x, int y, BaseObject *registerOwner, float zoomX, float zoomY, bool precise, uint32 alpha, float rotate, TSpriteBlendMode blendMode) {
+ if (!_surface) {
+ return STATUS_OK;
+ }
+
+ if (registerOwner != NULL && !_decoration) {
+ if (zoomX == 100 && zoomY == 100) {
+ _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, x - _hotspotX + getRect().left, y - _hotspotY + getRect().top, getRect().right - getRect().left, getRect().bottom - getRect().top, zoomX, zoomY, precise));
+ } else {
+ _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, registerOwner, this, (int)(x - (_hotspotX + getRect().left) * (zoomX / 100)), (int)(y - (_hotspotY + getRect().top) * (zoomY / 100)), (int)((getRect().right - getRect().left) * (zoomX / 100)), (int)((getRect().bottom - getRect().top) * (zoomY / 100)), zoomX, zoomY, precise));
+ }
+ }
+ if (_gameRef->_suspendedRendering) {
+ return STATUS_OK;
+ }
+
+ bool res;
+
+ //if (Alpha==0xFFFFFFFF) Alpha = _alpha; // TODO: better (combine owner's and self alpha)
+ if (_alpha != 0xFFFFFFFF) {
+ alpha = _alpha;
+ }
+
+ if (rotate != 0.0f) {
+ res = _surface->displayTransform((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), _hotspotX, _hotspotY, getRect(), zoomX, zoomY, alpha, rotate, blendMode, _mirrorX, _mirrorY);
+ } else {
+ if (zoomX == 100 && zoomY == 100) {
+ res = _surface->displayTrans(x - _hotspotX, y - _hotspotY, getRect(), alpha, blendMode, _mirrorX, _mirrorY);
+ } else {
+ res = _surface->displayTransZoom((int)(x - _hotspotX * (zoomX / 100)), (int)(y - _hotspotY * (zoomY / 100)), getRect(), zoomX, zoomY, alpha, blendMode, _mirrorX, _mirrorY);
+ }
+ }
+
+ return res;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::getBoundingRect(Rect32 *rect, int x, int y, float scaleX, float scaleY) {
+ if (!rect) {
+ return false;
+ }
+
+ float ratioX = scaleX / 100.0f;
+ float ratioY = scaleY / 100.0f;
+
+ BasePlatform::setRect(rect,
+ (int)(x - _hotspotX * ratioX),
+ (int)(y - _hotspotY * ratioY),
+ (int)(x - _hotspotX * ratioX + (getRect().right - getRect().left) * ratioX),
+ (int)(y - _hotspotY * ratioY + (getRect().bottom - getRect().top) * ratioY));
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::saveAsText(BaseDynamicBuffer *buffer, int indent, bool complete) {
+ if (complete) {
+ buffer->putTextIndent(indent, "SUBFRAME {\n");
+ }
+
+ if (_surface && _surface->getFileNameStr() != "") {
+ buffer->putTextIndent(indent + 2, "IMAGE = \"%s\"\n", _surface->getFileName());
+ }
+
+ if (_transparent != 0xFFFF00FF) {
+ buffer->putTextIndent(indent + 2, "TRANSPARENT { %d,%d,%d }\n", RGBCOLGetR(_transparent), RGBCOLGetG(_transparent), RGBCOLGetB(_transparent));
+ }
+
+ Rect32 rect;
+ BasePlatform::setRectEmpty(&rect);
+ if (_surface) {
+ BasePlatform::setRect(&rect, 0, 0, _surface->getWidth(), _surface->getHeight());
+ }
+ if (!(rect == getRect())) {
+ buffer->putTextIndent(indent + 2, "RECT { %d,%d,%d,%d }\n", getRect().left, getRect().top, getRect().right, getRect().bottom);
+ }
+
+ if (_hotspotX != 0 || _hotspotY != 0) {
+ buffer->putTextIndent(indent + 2, "HOTSPOT {%d, %d}\n", _hotspotX, _hotspotY);
+ }
+
+ if (_alpha != 0xFFFFFFFF) {
+ buffer->putTextIndent(indent + 2, "ALPHA_COLOR { %d,%d,%d }\n", RGBCOLGetR(_alpha), RGBCOLGetG(_alpha), RGBCOLGetB(_alpha));
+ buffer->putTextIndent(indent + 2, "ALPHA = %d\n", RGBCOLGetA(_alpha));
+ }
+
+ if (_mirrorX) {
+ buffer->putTextIndent(indent + 2, "MIRROR_X=%s\n", _mirrorX ? "TRUE" : "FALSE");
+ }
+
+ if (_mirrorY) {
+ buffer->putTextIndent(indent + 2, "MIRROR_Y=%s\n", _mirrorY ? "TRUE" : "FALSE");
+ }
+
+ if (_2DOnly) {
+ buffer->putTextIndent(indent + 2, "2D_ONLY=%s\n", _2DOnly ? "TRUE" : "FALSE");
+ }
+
+ if (_3DOnly) {
+ buffer->putTextIndent(indent + 2, "3D_ONLY=%s\n", _3DOnly ? "TRUE" : "FALSE");
+ }
+
+ if (_decoration) {
+ buffer->putTextIndent(indent + 2, "DECORATION=%s\n", _decoration ? "TRUE" : "FALSE");
+ }
+
+ if (_editorSelected) {
+ buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE");
+ }
+
+ BaseClass::saveAsText(buffer, indent + 2);
+
+
+ if (complete) {
+ buffer->putTextIndent(indent, "}\n\n");
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSubFrame::setDefaultRect() {
+ if (_surface) {
+ _wantsDefaultRect = true;
+ } else {
+ _wantsDefaultRect = false;
+ BasePlatform::setRectEmpty(&_rect);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_2DOnly));
+ persistMgr->transfer(TMEMBER(_3DOnly));
+ persistMgr->transfer(TMEMBER(_alpha));
+ persistMgr->transfer(TMEMBER(_decoration));
+ persistMgr->transfer(TMEMBER(_editorSelected));
+ persistMgr->transfer(TMEMBER(_hotspotX));
+ persistMgr->transfer(TMEMBER(_hotspotY));
+ persistMgr->transfer(TMEMBER(_rect));
+ persistMgr->transfer(TMEMBER(_wantsDefaultRect));
+
+ persistMgr->transfer(TMEMBER(_surfaceFilename));
+ persistMgr->transfer(TMEMBER(_cKDefault));
+ persistMgr->transfer(TMEMBER(_cKRed));
+ persistMgr->transfer(TMEMBER(_cKGreen));
+ persistMgr->transfer(TMEMBER(_cKBlue));
+ persistMgr->transfer(TMEMBER(_lifeTime));
+
+ persistMgr->transfer(TMEMBER(_keepLoaded));
+ persistMgr->transfer(TMEMBER(_mirrorX));
+ persistMgr->transfer(TMEMBER(_mirrorY));
+ persistMgr->transfer(TMEMBER(_transparent));
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetImage
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "GetImage") == 0) {
+ stack->correctParams(0);
+
+ if (!_surfaceFilename) {
+ stack->pushNULL();
+ } else {
+ stack->pushString(_surfaceFilename);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetImage
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetImage") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+
+ if (val->isNULL()) {
+ if (_surface) {
+ _gameRef->_surfaceStorage->removeSurface(_surface);
+ }
+ delete[] _surfaceFilename;
+ _surfaceFilename = NULL;
+ stack->pushBool(true);
+ } else {
+ const char *filename = val->getString();
+ if (DID_SUCCEED(setSurface(filename))) {
+ setDefaultRect();
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+ }
+
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *BaseSubFrame::scGetProperty(const char *name) {
+ if (!_scValue) {
+ _scValue = new ScValue(_gameRef);
+ }
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("subframe");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaColor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaColor") == 0) {
+
+ _scValue->setInt((int)_alpha);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TransparentColor (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TransparentColor") == 0) {
+ _scValue->setInt((int)_transparent);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Is2DOnly
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Is2DOnly") == 0) {
+ _scValue->setBool(_2DOnly);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Is3DOnly
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Is3DOnly") == 0) {
+ _scValue->setBool(_3DOnly);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MirrorX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MirrorX") == 0) {
+ _scValue->setBool(_mirrorX);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MirrorY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MirrorY") == 0) {
+ _scValue->setBool(_mirrorY);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Decoration
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Decoration") == 0) {
+ _scValue->setBool(_decoration);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HotspotX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HotspotX") == 0) {
+ _scValue->setInt(_hotspotX);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HotspotY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HotspotY") == 0) {
+ _scValue->setInt(_hotspotY);
+ return _scValue;
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaColor
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "AlphaColor") == 0) {
+ _alpha = (uint32)value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Is2DOnly
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Is2DOnly") == 0) {
+ _2DOnly = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Is3DOnly
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Is3DOnly") == 0) {
+ _3DOnly = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MirrorX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MirrorX") == 0) {
+ _mirrorX = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MirrorY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MirrorY") == 0) {
+ _mirrorY = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Decoration
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Decoration") == 0) {
+ _decoration = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HotspotX
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HotspotX") == 0) {
+ _hotspotX = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // HotspotY
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "HotspotY") == 0) {
+ _hotspotY = value->getInt();
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *BaseSubFrame::scToString() {
+ return "[subframe]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::setSurface(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
+ if (_surface) {
+ _gameRef->_surfaceStorage->removeSurface(_surface);
+ _surface = NULL;
+ }
+
+ delete[] _surfaceFilename;
+ _surfaceFilename = NULL;
+
+ _surface = _gameRef->_surfaceStorage->addSurface(filename, defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded);
+ if (_surface) {
+ _surfaceFilename = new char[filename.size() + 1];
+ strcpy(_surfaceFilename, filename.c_str());
+
+ _cKDefault = defaultCK;
+ _cKRed = ckRed;
+ _cKGreen = ckGreen;
+ _cKBlue = ckBlue;
+ _lifeTime = lifeTime;
+ _keepLoaded = keepLoaded;
+
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSubFrame::setSurfaceSimple() {
+ if (!_surfaceFilename) {
+ _surface = NULL;
+ return STATUS_OK;
+ }
+ _surface = _gameRef->_surfaceStorage->addSurface(_surfaceFilename, _cKDefault, _cKRed, _cKGreen, _cKBlue, _lifeTime, _keepLoaded);
+ if (_surface) {
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_sub_frame.h b/engines/wintermute/base/base_sub_frame.h
new file mode 100644
index 0000000000..b174c6e5f0
--- /dev/null
+++ b/engines/wintermute/base/base_sub_frame.h
@@ -0,0 +1,92 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SUBFRAME_H
+#define WINTERMUTE_BASE_SUBFRAME_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+class BaseObject;
+class BaseSurface;
+class BaseSubFrame : public BaseScriptable {
+public:
+ bool _mirrorX;
+ bool _mirrorY;
+ bool _decoration;
+ bool setSurface(const Common::String &filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false);
+ bool setSurfaceSimple();
+ DECLARE_PERSISTENT(BaseSubFrame, BaseScriptable)
+ void setDefaultRect();
+ uint32 _transparent;
+ bool saveAsText(BaseDynamicBuffer *buffer, int indent) { return saveAsText(buffer, indent, true); }
+ bool saveAsText(BaseDynamicBuffer *buffer, int indent, bool complete);
+ bool _editorSelected;
+ BaseSubFrame(BaseGame *inGame);
+ virtual ~BaseSubFrame();
+ bool loadBuffer(byte *buffer, int lifeTime, bool keepLoaded);
+ bool draw(int x, int y, BaseObject *registerOwner = NULL, float zoomX = 100, float zoomY = 100, bool precise = true, uint32 alpha = 0xFFFFFFFF, float rotate = 0.0f, TSpriteBlendMode blendMode = BLEND_NORMAL);
+ bool getBoundingRect(Rect32 *rect, int x, int y, float scaleX = 100, float scaleY = 100);
+
+ int _hotspotX;
+ int _hotspotY;
+ uint32 _alpha;
+ // These two setters and getters are rather usefull, as they allow _rect to be lazily defined
+ // Thus we don't need to load the actual graphics before the rect is actually needed.
+ Rect32 getRect();
+ void setRect(Rect32 rect);
+private:
+ bool _wantsDefaultRect;
+ Rect32 _rect;
+public:
+ bool _cKDefault;
+ byte _cKRed;
+ byte _cKGreen;
+ byte _cKBlue;
+ int _lifeTime;
+ bool _keepLoaded;
+ char *_surfaceFilename;
+
+ bool _2DOnly;
+ bool _3DOnly;
+
+ BaseSurface *_surface;
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_surface_storage.cpp b/engines/wintermute/base/base_surface_storage.cpp
new file mode 100644
index 0000000000..1dcebb0595
--- /dev/null
+++ b/engines/wintermute/base/base_surface_storage.cpp
@@ -0,0 +1,207 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+//IMPLEMENT_PERSISTENT(BaseSurfaceStorage, true);
+
+//////////////////////////////////////////////////////////////////////
+BaseSurfaceStorage::BaseSurfaceStorage(BaseGame *inGame) : BaseClass(inGame) {
+ _lastCleanupTime = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseSurfaceStorage::~BaseSurfaceStorage() {
+ cleanup(true);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::cleanup(bool warn) {
+ for (uint32 i = 0; i < _surfaces.size(); i++) {
+ if (warn) {
+ _gameRef->LOG(0, "BaseSurfaceStorage warning: purging surface '%s', usage:%d", _surfaces[i]->getFileName(), _surfaces[i]->_referenceCount);
+ }
+ delete _surfaces[i];
+ }
+ _surfaces.clear();
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::initLoop() {
+ if (_gameRef->_smartCache && _gameRef->_liveTimer - _lastCleanupTime >= _gameRef->_surfaceGCCycleTime) {
+ _lastCleanupTime = _gameRef->_liveTimer;
+ sortSurfaces();
+ for (uint32 i = 0; i < _surfaces.size(); i++) {
+ if (_surfaces[i]->_lifeTime <= 0) {
+ break;
+ }
+
+ if (_surfaces[i]->_lifeTime > 0 && _surfaces[i]->_valid && (int)(_gameRef->_liveTimer - _surfaces[i]->_lastUsedTime) >= _surfaces[i]->_lifeTime) {
+ //_gameRef->QuickMessageForm("Invalidating: %s", _surfaces[i]->_filename);
+ _surfaces[i]->invalidate();
+ }
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::removeSurface(BaseSurface *surface) {
+ for (uint32 i = 0; i < _surfaces.size(); i++) {
+ if (_surfaces[i] == surface) {
+ _surfaces[i]->_referenceCount--;
+ if (_surfaces[i]->_referenceCount <= 0) {
+ delete _surfaces[i];
+ _surfaces.remove_at(i);
+ }
+ break;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseSurface *BaseSurfaceStorage::addSurface(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
+ for (uint32 i = 0; i < _surfaces.size(); i++) {
+ if (scumm_stricmp(_surfaces[i]->getFileName(), filename.c_str()) == 0) {
+ _surfaces[i]->_referenceCount++;
+ return _surfaces[i];
+ }
+ }
+
+ if (!BaseFileManager::getEngineInstance()->hasFile(filename)) {
+ if (filename.size()) {
+ _gameRef->LOG(0, "Missing image: '%s'", filename.c_str());
+ }
+ if (_gameRef->_debugDebugMode) {
+ return addSurface("invalid_debug.bmp", defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded);
+ } else {
+ return addSurface("invalid.bmp", defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded);
+ }
+ }
+
+ BaseSurface *surface;
+ surface = _gameRef->_renderer->createSurface();
+
+ if (!surface) {
+ return NULL;
+ }
+
+ if (DID_FAIL(surface->create(filename, defaultCK, ckRed, ckGreen, ckBlue, lifeTime, keepLoaded))) {
+ delete surface;
+ return NULL;
+ } else {
+ surface->_referenceCount = 1;
+ _surfaces.push_back(surface);
+ return surface;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::restoreAll() {
+ bool ret;
+ for (uint32 i = 0; i < _surfaces.size(); i++) {
+ ret = _surfaces[i]->restore();
+ if (ret != STATUS_OK) {
+ _gameRef->LOG(0, "BaseSurfaceStorage::RestoreAll failed");
+ return ret;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+/*
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::persist(BasePersistenceManager *persistMgr)
+{
+
+ if (!persistMgr->getIsSaving()) cleanup(false);
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ //_surfaces.persist(persistMgr);
+
+ return STATUS_OK;
+}
+*/
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceStorage::sortSurfaces() {
+ Common::sort(_surfaces.begin(), _surfaces.end(), surfaceSortCB);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseSurfaceStorage::surfaceSortCB(const void *arg1, const void *arg2) {
+ const BaseSurface *s1 = *((const BaseSurface *const *)arg1);
+ const BaseSurface *s2 = *((const BaseSurface *const *)arg2);
+
+ // sort by life time
+ if (s1->_lifeTime <= 0 && s2->_lifeTime > 0) {
+ return 1;
+ } else if (s1->_lifeTime > 0 && s2->_lifeTime <= 0) {
+ return -1;
+ }
+
+
+ // sort by validity
+ if (s1->_valid && !s2->_valid) {
+ return -1;
+ } else if (!s1->_valid && s2->_valid) {
+ return 1;
+ }
+
+ // sort by time
+ else if (s1->_lastUsedTime > s2->_lastUsedTime) {
+ return 1;
+ } else if (s1->_lastUsedTime < s2->_lastUsedTime) {
+ return -1;
+ } else {
+ return 0;
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_surface_storage.h b/engines/wintermute/base/base_surface_storage.h
new file mode 100644
index 0000000000..aef8ad23f9
--- /dev/null
+++ b/engines/wintermute/base/base_surface_storage.h
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SURFACE_STORAGE_H
+#define WINTERMUTE_BASE_SURFACE_STORAGE_H
+
+#include "engines/wintermute/base/base.h"
+#include "common/array.h"
+
+namespace Wintermute {
+class BaseSurface;
+class BaseSurfaceStorage : public BaseClass {
+public:
+ uint32 _lastCleanupTime;
+ bool initLoop();
+ bool sortSurfaces();
+ static int surfaceSortCB(const void *arg1, const void *arg2);
+ bool cleanup(bool warn = false);
+ //DECLARE_PERSISTENT(BaseSurfaceStorage, BaseClass);
+
+ bool restoreAll();
+ BaseSurface *addSurface(const Common::String &filename, bool defaultCK = true, byte ckRed = 0, byte ckGreen = 0, byte ckBlue = 0, int lifeTime = -1, bool keepLoaded = false);
+ bool removeSurface(BaseSurface *surface);
+ BaseSurfaceStorage(BaseGame *inGame);
+ virtual ~BaseSurfaceStorage();
+
+ Common::Array<BaseSurface *> _surfaces;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp
new file mode 100644
index 0000000000..5c28f36d30
--- /dev/null
+++ b/engines/wintermute/base/base_transition_manager.cpp
@@ -0,0 +1,136 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_transition_manager.h"
+#include "engines/wintermute/base/base_game.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseTransitionMgr::BaseTransitionMgr(BaseGame *inGame) : BaseClass(inGame) {
+ _state = TRANS_MGR_READY;
+ _type = TRANSITION_NONE;
+ _origInteractive = false;
+ _preserveInteractive = false;
+ _lastTime = 0;
+ _started = false;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseTransitionMgr::~BaseTransitionMgr() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseTransitionMgr::isReady() {
+ return (_state == TRANS_MGR_READY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseTransitionMgr::start(TTransitionType type, bool nonInteractive) {
+ if (_state != TRANS_MGR_READY) {
+ return STATUS_OK;
+ }
+
+ if (type == TRANSITION_NONE || type >= NUM_TRANSITION_TYPES) {
+ _state = TRANS_MGR_READY;
+ return STATUS_OK;
+ }
+
+ if (nonInteractive) {
+ _preserveInteractive = true;
+ _origInteractive = _gameRef->_interactive;
+ _gameRef->_interactive = false;
+ } /*else _preserveInteractive */;
+
+
+ _type = type;
+ _state = TRANS_MGR_RUNNING;
+ _started = false;
+
+ return STATUS_OK;
+}
+
+#define FADE_DURATION 200
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseTransitionMgr::update() {
+ if (isReady()) {
+ return STATUS_OK;
+ }
+
+ if (!_started) {
+ _started = true;
+ _lastTime = g_system->getMillis();
+ }
+
+ switch (_type) {
+ case TRANSITION_NONE:
+ _state = TRANS_MGR_READY;
+ break;
+
+ case TRANSITION_FADE_OUT: {
+ uint32 time = g_system->getMillis() - _lastTime;
+ int alpha = (int)(255 - (float)time / (float)FADE_DURATION * 255);
+ alpha = MIN(255, MAX(alpha, 0));
+ _gameRef->_renderer->fade((uint16)alpha);
+
+ if (time > FADE_DURATION) {
+ _state = TRANS_MGR_READY;
+ }
+ }
+ break;
+
+ case TRANSITION_FADE_IN: {
+ uint32 time = g_system->getMillis() - _lastTime;
+ int alpha = (int)((float)time / (float)FADE_DURATION * 255);
+ alpha = MIN(255, MAX(alpha, 0));
+ _gameRef->_renderer->fade((uint16)alpha);
+
+ if (time > FADE_DURATION) {
+ _state = TRANS_MGR_READY;
+ }
+ }
+ break;
+ default:
+ error("BaseTransitionMgr::Update - unhandled enum NUM_TRANSITION_TYPES");
+ }
+
+ if (isReady()) {
+ if (_preserveInteractive) {
+ _gameRef->_interactive = _origInteractive;
+ }
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_transition_manager.h b/engines/wintermute/base/base_transition_manager.h
new file mode 100644
index 0000000000..d16a44c88e
--- /dev/null
+++ b/engines/wintermute/base/base_transition_manager.h
@@ -0,0 +1,54 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_TRANSITION_MANAGER_H
+#define WINTERMUTE_BASE_TRANSITION_MANAGER_H
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+class BaseTransitionMgr : public BaseClass {
+public:
+ bool _started;
+ uint32 _lastTime;
+ bool _origInteractive;
+ bool _preserveInteractive;
+ bool update();
+ bool start(TTransitionType type, bool nonInteractive = false);
+ bool isReady();
+ TTransMgrState _state;
+ BaseTransitionMgr(BaseGame *inGame);
+ virtual ~BaseTransitionMgr();
+ TTransitionType _type;
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/base_viewport.cpp b/engines/wintermute/base/base_viewport.cpp
new file mode 100644
index 0000000000..3b003e1c49
--- /dev/null
+++ b/engines/wintermute/base/base_viewport.cpp
@@ -0,0 +1,98 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/base_viewport.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseViewport, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseViewport::BaseViewport(BaseGame *inGame) : BaseClass(inGame) {
+ BasePlatform::setRectEmpty(&_rect);
+ _mainObject = NULL;
+ _offsetX = _offsetY = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseViewport::~BaseViewport() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseViewport::persist(BasePersistenceManager *persistMgr) {
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ persistMgr->transfer(TMEMBER(_mainObject));
+ persistMgr->transfer(TMEMBER(_offsetX));
+ persistMgr->transfer(TMEMBER(_offsetY));
+ persistMgr->transfer(TMEMBER(_rect));
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseViewport::setRect(int left, int top, int right, int bottom, bool noCheck) {
+ if (!noCheck) {
+ left = MAX(left, 0);
+ top = MAX(top, 0);
+ right = MIN(right, _gameRef->_renderer->_width);
+ bottom = MIN(bottom, _gameRef->_renderer->_height);
+ }
+
+ BasePlatform::setRect(&_rect, left, top, right, bottom);
+ _offsetX = left;
+ _offsetY = top;
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+Rect32 *BaseViewport::getRect() {
+ return &_rect;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseViewport::getWidth() {
+ return _rect.right - _rect.left;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseViewport::getHeight() {
+ return _rect.bottom - _rect.top;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/base_viewport.h b/engines/wintermute/base/base_viewport.h
new file mode 100644
index 0000000000..98ad1c1e14
--- /dev/null
+++ b/engines/wintermute/base/base_viewport.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_VIEWPORT_H
+#define WINTERMUTE_BASE_VIEWPORT_H
+
+
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+class BaseObject;
+class BaseViewport : public BaseClass {
+public:
+ int getHeight();
+ int getWidth();
+ Rect32 *getRect();
+ bool setRect(int left, int top, int right, int bottom, bool noCheck = false);
+ DECLARE_PERSISTENT(BaseViewport, BaseClass)
+ int _offsetY;
+ int _offsetX;
+ BaseObject *_mainObject;
+ BaseViewport(BaseGame *inGame = NULL);
+ virtual ~BaseViewport();
+private:
+ Rect32 _rect;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_disk_file.cpp b/engines/wintermute/base/file/base_disk_file.cpp
new file mode 100644
index 0000000000..2d3951b026
--- /dev/null
+++ b/engines/wintermute/base/file/base_disk_file.cpp
@@ -0,0 +1,196 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/dcgf.h"
+#include "engines/wintermute/base/file/base_disk_file.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "common/stream.h"
+#include "common/memstream.h"
+#include "common/file.h"
+#include "common/zlib.h"
+#include "common/archive.h"
+#include "common/tokenizer.h"
+#include "common/config-manager.h"
+
+namespace Wintermute {
+
+void correctSlashes(char *fileName) {
+ for (size_t i = 0; i < strlen(fileName); i++) {
+ if (fileName[i] == '\\') {
+ fileName[i] = '/';
+ }
+ }
+}
+
+// Parse a relative path in the game-folder, and if it exists, return a FSNode to it.
+static Common::FSNode getNodeForRelativePath(const Common::String &filename) {
+ // The filename can be an explicit path, thus we need to chop it up, expecting the path the game
+ // specifies to follow the Windows-convention of folder\subfolder\file (absolute paths should not happen)
+
+ // Absolute path: These should have been handled in openDiskFile.
+ if (filename.contains(':')) {
+ // So just return an invalid node.
+ return Common::FSNode();
+ }
+
+ // Relative path:
+ if (filename.contains('\\')) {
+ Common::StringTokenizer path(filename, "\\");
+
+ // Start traversing relative to the game-data-dir
+ const Common::FSNode gameDataDir(ConfMan.get("path"));
+ Common::FSNode curNode = gameDataDir;
+
+ // Parse all path-elements
+ while (!path.empty()) {
+ // Get the next path-component by slicing on '\\'
+ Common::String pathPart = path.nextToken();
+ // Get the next FSNode in the chain, if it exists as a child from the previous.
+ curNode = curNode.getChild(pathPart);
+ if (!curNode.isReadable()) {
+ // Return an invalid FSNode.
+ return Common::FSNode();
+ }
+ // Following the comments in common/fs.h, anything not a directory is a file.
+ if (!curNode.isDirectory()) {
+ if (!path.empty()) {
+ error("Relative path %s reached a file before the end of the path", filename.c_str());
+ }
+ return curNode;
+ }
+ }
+ }
+ // Return an invalid FSNode to mark that we didn't find the requested file.
+ return Common::FSNode();
+}
+
+bool diskFileExists(const Common::String &filename) {
+ // Try directly from SearchMan first
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, filename);
+
+ for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
+ if ((*it)->getName() == filename) {
+ return true;
+ }
+ }
+ // File wasn't found in SearchMan, try to parse the path as a relative path.
+ Common::FSNode searchNode = getNodeForRelativePath(filename);
+ if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
+ return true;
+ }
+ return false;
+}
+
+Common::SeekableReadStream *openDiskFile(const Common::String &filename) {
+ uint32 prefixSize = 0;
+ Common::SeekableReadStream *file = NULL;
+ Common::String fixedFilename = filename;
+
+ // Absolute path: TODO: Add specific fallbacks here.
+ if (filename.contains(':')) {
+ if (filename.hasPrefix("c:\\windows\\fonts\\")) { // East Side Story refers to "c:\windows\fonts\framd.ttf"
+ fixedFilename = filename.c_str() + 17;
+ } else {
+ error("openDiskFile::Absolute path or invalid filename used in %s", filename.c_str());
+ }
+ }
+ // Try directly from SearchMan first
+ Common::ArchiveMemberList files;
+ SearchMan.listMatchingMembers(files, fixedFilename);
+
+ for (Common::ArchiveMemberList::iterator it = files.begin(); it != files.end(); ++it) {
+ if ((*it)->getName() == filename) {
+ file = (*it)->createReadStream();
+ break;
+ }
+ }
+ // File wasn't found in SearchMan, try to parse the path as a relative path.
+ if (!file) {
+ Common::FSNode searchNode = getNodeForRelativePath(filename);
+ if (searchNode.exists() && !searchNode.isDirectory() && searchNode.isReadable()) {
+ file = searchNode.createReadStream();
+ }
+ }
+ if (file) {
+ uint32 magic1, magic2;
+ magic1 = file->readUint32LE();
+ magic2 = file->readUint32LE();
+
+ bool compressed = false;
+ if (magic1 == DCGF_MAGIC && magic2 == COMPRESSED_FILE_MAGIC) {
+ compressed = true;
+ }
+
+ if (compressed) {
+ uint32 dataOffset, compSize, uncompSize;
+ dataOffset = file->readUint32LE();
+ compSize = file->readUint32LE();
+ uncompSize = file->readUint32LE();
+
+ byte *compBuffer = new byte[compSize];
+ if (!compBuffer) {
+ error("Error allocating memory for compressed file '%s'", filename.c_str());
+ delete file;
+ return NULL;
+ }
+
+ byte *data = new byte[uncompSize];
+ if (!data) {
+ error("Error allocating buffer for file '%s'", filename.c_str());
+ delete[] compBuffer;
+ delete file;
+ return NULL;
+ }
+ file->seek(dataOffset + prefixSize, SEEK_SET);
+ file->read(compBuffer, compSize);
+
+ if (Common::uncompress(data, (unsigned long *)&uncompSize, compBuffer, compSize) != true) {
+ error("Error uncompressing file '%s'", filename.c_str());
+ delete[] compBuffer;
+ delete file;
+ return NULL;
+ }
+
+ delete[] compBuffer;
+
+ return new Common::MemoryReadStream(data, uncompSize, DisposeAfterUse::YES);
+ delete file;
+ file = NULL;
+ } else {
+ file->seek(0, SEEK_SET);
+ return file;
+ }
+
+ return file;
+
+ }
+ return NULL;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_disk_file.h b/engines/wintermute/base/file/base_disk_file.h
new file mode 100644
index 0000000000..c9f93b80d9
--- /dev/null
+++ b/engines/wintermute/base/file/base_disk_file.h
@@ -0,0 +1,41 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_DISKFILE_H
+#define WINTERMUTE_BASE_DISKFILE_H
+
+#include "common/stream.h"
+
+namespace Wintermute {
+
+Common::SeekableReadStream *openDiskFile(const Common::String &filename);
+bool diskFileExists(const Common::String &filename);
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_file.cpp b/engines/wintermute/base/file/base_file.cpp
new file mode 100644
index 0000000000..f52a13211e
--- /dev/null
+++ b/engines/wintermute/base/file/base_file.cpp
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_file.h"
+#include "common/memstream.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseFile::BaseFile() {
+ _pos = 0;
+ _size = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseFile::~BaseFile() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFile::isEOF() {
+ return _pos == _size;
+}
+
+Common::SeekableReadStream *BaseFile::getMemStream() {
+ uint32 oldPos = getPos();
+ seek(0);
+ byte *data = new byte[getSize()];
+ read(data, getSize());
+ seek(oldPos);
+ Common::MemoryReadStream *memStream = new Common::MemoryReadStream(data, getSize(), DisposeAfterUse::YES);
+ return memStream;
+}
+
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_file.h b/engines/wintermute/base/file/base_file.h
new file mode 100644
index 0000000000..82f6ce3554
--- /dev/null
+++ b/engines/wintermute/base/file/base_file.h
@@ -0,0 +1,67 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FILE_H
+#define WINTERMUTE_BASE_FILE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace Common {
+class SeekableReadStream;
+}
+
+namespace Wintermute {
+
+class BaseFile {
+protected:
+ uint32 _pos;
+ uint32 _size;
+public:
+ virtual uint32 getSize() {
+ return _size;
+ };
+ virtual uint32 getPos() {
+ return _pos;
+ };
+ virtual bool seek(uint32 pos, int whence = SEEK_SET) = 0;
+ virtual bool read(void *buffer, uint32 size) = 0;
+ virtual bool close() = 0;
+ virtual bool open(const Common::String &filename) = 0;
+ virtual bool isEOF();
+ BaseFile();
+ virtual ~BaseFile();
+ // Temporary solution to allow usage in ScummVM-code:
+ virtual Common::SeekableReadStream *getMemStream();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_file_entry.cpp b/engines/wintermute/base/file/base_file_entry.cpp
new file mode 100644
index 0000000000..b9805d78dd
--- /dev/null
+++ b/engines/wintermute/base/file/base_file_entry.cpp
@@ -0,0 +1,73 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_file_entry.h"
+#include "engines/wintermute/base/file/base_package.h"
+#include "common/stream.h"
+#include "common/substream.h"
+#include "common/zlib.h"
+
+namespace Wintermute {
+
+Common::SeekableReadStream *BaseFileEntry::createReadStream() const {
+ Common::SeekableReadStream *file = _package->getFilePointer();
+ if (!file) {
+ return NULL;
+ }
+
+ bool compressed = (_compressedLength != 0);
+
+ if (compressed) {
+ file = Common::wrapCompressedReadStream(new Common::SeekableSubReadStream(file, _offset, _offset + _length, DisposeAfterUse::YES), _length); //
+ } else {
+ file = new Common::SeekableSubReadStream(file, _offset, _offset + _length, DisposeAfterUse::YES);
+ }
+
+ file->seek(0);
+
+ return file;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseFileEntry::BaseFileEntry() {
+ _package = NULL;
+ _length = _compressedLength = _offset = _flags = 0;
+ _filename = "";
+
+ _timeDate1 = _timeDate2 = 0;
+
+ _journalTime = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseFileEntry::~BaseFileEntry() {
+ _package = NULL; // ref only
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_file_entry.h b/engines/wintermute/base/file/base_file_entry.h
new file mode 100644
index 0000000000..6e4823d994
--- /dev/null
+++ b/engines/wintermute/base/file/base_file_entry.h
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FILEENTRY_H
+#define WINTERMUTE_BASE_FILEENTRY_H
+
+#include "common/archive.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace Wintermute {
+
+class BasePackage;
+
+class BaseFileEntry : public Common::ArchiveMember {
+public:
+ virtual Common::SeekableReadStream *createReadStream() const;
+ virtual Common::String getName() const { return _filename; }
+ uint32 _timeDate2;
+ uint32 _timeDate1;
+ uint32 _flags;
+ uint32 _journalTime;
+ Common::String _filename;
+ uint32 _compressedLength;
+ uint32 _length;
+ uint32 _offset;
+ BasePackage *_package;
+ BaseFileEntry();
+ virtual ~BaseFileEntry();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_package.cpp b/engines/wintermute/base/file/base_package.cpp
new file mode 100644
index 0000000000..9780992652
--- /dev/null
+++ b/engines/wintermute/base/file/base_package.cpp
@@ -0,0 +1,276 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_package.h"
+#include "engines/wintermute/base/file/base_file_entry.h"
+#include "engines/wintermute/base/file/dcpackage.h"
+#include "engines/wintermute/wintermute.h"
+#include "common/file.h"
+#include "common/stream.h"
+#include "common/debug.h"
+
+namespace Wintermute {
+
+BasePackage::BasePackage() {
+ _name = "";
+ _cd = 0;
+ _priority = 0;
+ _boundToExe = false;
+}
+
+Common::SeekableReadStream *BasePackage::getFilePointer() {
+ Common::SeekableReadStream *stream = _fsnode.createReadStream();
+
+ return stream;
+}
+
+static bool findPackageSignature(Common::SeekableReadStream *f, uint32 *offset) {
+ byte buf[32768];
+
+ byte signature[8];
+ ((uint32 *)signature)[0] = PACKAGE_MAGIC_1;
+ ((uint32 *)signature)[1] = PACKAGE_MAGIC_2;
+
+ uint32 fileSize = (uint32)f->size();
+ uint32 startPos = 1024 * 1024;
+ uint32 bytesRead = startPos;
+
+ while (bytesRead < fileSize - 16) {
+ uint32 toRead = MIN((unsigned int)32768, fileSize - bytesRead);
+ f->seek((int32)startPos, SEEK_SET);
+ uint32 actuallyRead = f->read(buf, toRead);
+ if (actuallyRead != toRead) {
+ return false;
+ }
+
+ for (uint32 i = 0; i < toRead - 8; i++)
+ if (!memcmp(buf + i, signature, 8)) {
+ *offset = startPos + i;
+ return true;
+ }
+
+ bytesRead = bytesRead + toRead - 16;
+ startPos = startPos + toRead - 16;
+
+ }
+ return false;
+
+}
+
+void TPackageHeader::readFromStream(Common::ReadStream *stream) {
+ _magic1 = stream->readUint32LE();
+ _magic2 = stream->readUint32LE();
+ _packageVersion = stream->readUint32LE();
+
+ _gameVersion = stream->readUint32LE();
+
+ _priority = stream->readByte();
+ _cd = stream->readByte();
+ _masterIndex = stream->readByte();
+ stream->readByte(); // To align the next byte...
+
+ _creationTime = stream->readUint32LE();
+
+ stream->read(_desc, 100);
+ _numDirs = stream->readUint32LE();
+}
+
+PackageSet::PackageSet(Common::FSNode file, const Common::String &filename, bool searchSignature) {
+ uint32 absoluteOffset = 0;
+ _priority = 0;
+ bool boundToExe = false;
+ Common::SeekableReadStream *stream = file.createReadStream();
+ if (!stream) {
+ return;
+ }
+ if (searchSignature) {
+ uint32 offset;
+ if (!findPackageSignature(stream, &offset)) {
+ delete stream;
+ return;
+ } else {
+ stream->seek(offset, SEEK_SET);
+ absoluteOffset = offset;
+ boundToExe = true;
+ }
+ }
+
+ TPackageHeader hdr;
+ hdr.readFromStream(stream);
+ if (hdr._magic1 != PACKAGE_MAGIC_1 || hdr._magic2 != PACKAGE_MAGIC_2 || hdr._packageVersion > PACKAGE_VERSION) {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Invalid header in package file '%s'. Ignoring.", filename.c_str());
+ delete stream;
+ return;
+ }
+
+ if (hdr._packageVersion != PACKAGE_VERSION) {
+ debugC(kWintermuteDebugFileAccess | kWintermuteDebugLog, " Warning: package file '%s' is outdated.", filename.c_str());
+ }
+ _priority = hdr._priority;
+ // new in v2
+ if (hdr._packageVersion == PACKAGE_VERSION) {
+ uint32 dirOffset;
+ dirOffset = stream->readUint32LE();
+ dirOffset += absoluteOffset;
+ stream->seek(dirOffset, SEEK_SET);
+ }
+ assert(hdr._numDirs == 1);
+ for (uint32 i = 0; i < hdr._numDirs; i++) {
+ BasePackage *pkg = new BasePackage();
+ if (!pkg) {
+ return;
+ }
+ pkg->_fsnode = file;
+
+ pkg->_boundToExe = boundToExe;
+
+ // read package info
+ byte nameLength = stream->readByte();
+ char *pkgName = new char[nameLength];
+ stream->read(pkgName, nameLength);
+ pkg->_name = pkgName;
+ pkg->_cd = stream->readByte();
+ pkg->_priority = hdr._priority;
+ delete[] pkgName;
+ pkgName = NULL;
+
+ if (!hdr._masterIndex) {
+ pkg->_cd = 0; // override CD to fixed disk
+ }
+ _packages.push_back(pkg);
+
+ // read file entries
+ uint32 numFiles = stream->readUint32LE();
+
+ for (uint32 j = 0; j < numFiles; j++) {
+ char *name;
+ uint32 offset, length, compLength, flags;/*, timeDate1, timeDate2;*/
+
+ nameLength = stream->readByte();
+ name = new char[nameLength];
+ stream->read(name, nameLength);
+
+ // v2 - xor name
+ if (hdr._packageVersion == PACKAGE_VERSION) {
+ for (int k = 0; k < nameLength; k++) {
+ ((byte *)name)[k] ^= 'D';
+ }
+ }
+ debugC(kWintermuteDebugFileAccess, "Package contains %s", name);
+
+ Common::String upcName = name;
+ upcName.toUppercase();
+ delete[] name;
+ name = NULL;
+
+ offset = stream->readUint32LE();
+ offset += absoluteOffset;
+ length = stream->readUint32LE();
+ compLength = stream->readUint32LE();
+ flags = stream->readUint32LE();
+
+ if (hdr._packageVersion == PACKAGE_VERSION) {
+ /* timeDate1 = */ stream->readUint32LE();
+ /* timeDate2 = */ stream->readUint32LE();
+ }
+ _filesIter = _files.find(upcName);
+ if (_filesIter == _files.end()) {
+ BaseFileEntry *fileEntry = new BaseFileEntry();
+ fileEntry->_package = pkg;
+ fileEntry->_offset = offset;
+ fileEntry->_length = length;
+ fileEntry->_compressedLength = compLength;
+ fileEntry->_flags = flags;
+
+ _files[upcName] = Common::ArchiveMemberPtr(fileEntry);
+ } else {
+ // current package has higher priority than the registered
+ // TODO: This cast might be a bit ugly.
+ BaseFileEntry *filePtr = (BaseFileEntry *) &*(_filesIter->_value);
+ if (pkg->_priority > filePtr->_package->_priority) {
+ filePtr->_package = pkg;
+ filePtr->_offset = offset;
+ filePtr->_length = length;
+ filePtr->_compressedLength = compLength;
+ filePtr->_flags = flags;
+ }
+ }
+ }
+ }
+ debugC(kWintermuteDebugFileAccess, " Registered %d files in %d package(s)", _files.size(), _packages.size());
+
+ delete stream;
+}
+
+PackageSet::~PackageSet() {
+ for (Common::Array<BasePackage *>::iterator it = _packages.begin(); it != _packages.end(); ++it) {
+ delete *it;
+ }
+ _packages.clear();
+}
+
+bool PackageSet::hasFile(const Common::String &name) const {
+ Common::String upcName = name;
+ upcName.toUppercase();
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::const_iterator it;
+ it = _files.find(upcName.c_str());
+ return (it != _files.end());
+}
+
+int PackageSet::listMembers(Common::ArchiveMemberList &list) const {
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::const_iterator it = _files.begin();
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::const_iterator end = _files.end();
+ int count = 0;
+ for (; it != end; ++it) {
+ const Common::ArchiveMemberPtr ptr(it->_value);
+ list.push_back(ptr);
+ count++;
+ }
+ return count;
+}
+
+const Common::ArchiveMemberPtr PackageSet::getMember(const Common::String &name) const {
+ Common::String upcName = name;
+ upcName.toUppercase();
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::const_iterator it;
+ it = _files.find(upcName.c_str());
+ return Common::ArchiveMemberPtr(it->_value);
+}
+
+Common::SeekableReadStream *PackageSet::createReadStreamForMember(const Common::String &name) const {
+ Common::String upcName = name;
+ upcName.toUppercase();
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::const_iterator it;
+ it = _files.find(upcName.c_str());
+ if (it != _files.end()) {
+ return it->_value->createReadStream();
+ }
+ return NULL;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_package.h b/engines/wintermute/base/file/base_package.h
new file mode 100644
index 0000000000..2882eb03b7
--- /dev/null
+++ b/engines/wintermute/base/file/base_package.h
@@ -0,0 +1,90 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_PACKAGE_H
+#define WINTERMUTE_BASE_PACKAGE_H
+
+#include "common/archive.h"
+#include "common/stream.h"
+#include "common/fs.h"
+
+namespace Wintermute {
+class BasePackage {
+public:
+ Common::SeekableReadStream *getFilePointer();
+ Common::FSNode _fsnode;
+ bool _boundToExe;
+ byte _priority;
+ Common::String _name;
+ int _cd;
+ BasePackage();
+};
+
+class PackageSet : public Common::Archive {
+public:
+ virtual ~PackageSet();
+
+ PackageSet(Common::FSNode package, const Common::String &filename = "", bool searchSignature = false);
+ /**
+ * Check if a member with the given name is present in the Archive.
+ * Patterns are not allowed, as this is meant to be a quick File::exists()
+ * replacement.
+ */
+ virtual bool hasFile(const Common::String &name) const;
+
+ /**
+ * Add all members of the Archive to list.
+ * Must only append to list, and not remove elements from it.
+ *
+ * @return the number of names added to list
+ */
+ virtual int listMembers(Common::ArchiveMemberList &list) const;
+
+ /**
+ * Returns a ArchiveMember representation of the given file.
+ */
+ virtual const Common::ArchiveMemberPtr getMember(const Common::String &name) const;
+
+ /**
+ * Create a stream bound to a member with the specified name in the
+ * archive. If no member with this name exists, 0 is returned.
+ * @return the newly created input stream
+ */
+ virtual Common::SeekableReadStream *createReadStreamForMember(const Common::String &name) const;
+
+ int getPriority() const { return _priority; }
+private:
+ byte _priority;
+ Common::Array<BasePackage *> _packages;
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr> _files;
+ Common::HashMap<Common::String, Common::ArchiveMemberPtr>::iterator _filesIter;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_resources.cpp b/engines/wintermute/base/file/base_resources.cpp
new file mode 100644
index 0000000000..0b32cb0c4f
--- /dev/null
+++ b/engines/wintermute/base/file/base_resources.cpp
@@ -0,0 +1,2830 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_resources.h"
+#include "common/str.h"
+#include "common/memstream.h"
+
+namespace Wintermute {
+
+unsigned char invalid[] = {
+ 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x20, 0x4e, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
+} ;
+
+unsigned char invaliddebug[] = {
+ 0x42, 0x4d, 0x36, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x80,
+ 0x00, 0x00, 0x00, 0x80, 0x80, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x80,
+ 0x00, 0x00, 0xc0, 0xc0, 0xc0, 0x00, 0xc0, 0xdc, 0xc0, 0x00, 0xf0, 0xca, 0xa6, 0x00, 0x00, 0x20,
+ 0x40, 0x00, 0x00, 0x20, 0x60, 0x00, 0x00, 0x20, 0x80, 0x00, 0x00, 0x20, 0xa0, 0x00, 0x00, 0x20,
+ 0xc0, 0x00, 0x00, 0x20, 0xe0, 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40,
+ 0x40, 0x00, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40,
+ 0xc0, 0x00, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x60, 0x00, 0x00, 0x00, 0x60, 0x20, 0x00, 0x00, 0x60,
+ 0x40, 0x00, 0x00, 0x60, 0x60, 0x00, 0x00, 0x60, 0x80, 0x00, 0x00, 0x60, 0xa0, 0x00, 0x00, 0x60,
+ 0xc0, 0x00, 0x00, 0x60, 0xe0, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80,
+ 0x40, 0x00, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80,
+ 0xc0, 0x00, 0x00, 0x80, 0xe0, 0x00, 0x00, 0xa0, 0x00, 0x00, 0x00, 0xa0, 0x20, 0x00, 0x00, 0xa0,
+ 0x40, 0x00, 0x00, 0xa0, 0x60, 0x00, 0x00, 0xa0, 0x80, 0x00, 0x00, 0xa0, 0xa0, 0x00, 0x00, 0xa0,
+ 0xc0, 0x00, 0x00, 0xa0, 0xe0, 0x00, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0,
+ 0x40, 0x00, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0,
+ 0xc0, 0x00, 0x00, 0xc0, 0xe0, 0x00, 0x00, 0xe0, 0x00, 0x00, 0x00, 0xe0, 0x20, 0x00, 0x00, 0xe0,
+ 0x40, 0x00, 0x00, 0xe0, 0x60, 0x00, 0x00, 0xe0, 0x80, 0x00, 0x00, 0xe0, 0xa0, 0x00, 0x00, 0xe0,
+ 0xc0, 0x00, 0x00, 0xe0, 0xe0, 0x00, 0x40, 0x00, 0x00, 0x00, 0x40, 0x00, 0x20, 0x00, 0x40, 0x00,
+ 0x40, 0x00, 0x40, 0x00, 0x60, 0x00, 0x40, 0x00, 0x80, 0x00, 0x40, 0x00, 0xa0, 0x00, 0x40, 0x00,
+ 0xc0, 0x00, 0x40, 0x00, 0xe0, 0x00, 0x40, 0x20, 0x00, 0x00, 0x40, 0x20, 0x20, 0x00, 0x40, 0x20,
+ 0x40, 0x00, 0x40, 0x20, 0x60, 0x00, 0x40, 0x20, 0x80, 0x00, 0x40, 0x20, 0xa0, 0x00, 0x40, 0x20,
+ 0xc0, 0x00, 0x40, 0x20, 0xe0, 0x00, 0x40, 0x40, 0x00, 0x00, 0x40, 0x40, 0x20, 0x00, 0x40, 0x40,
+ 0x40, 0x00, 0x40, 0x40, 0x60, 0x00, 0x40, 0x40, 0x80, 0x00, 0x40, 0x40, 0xa0, 0x00, 0x40, 0x40,
+ 0xc0, 0x00, 0x40, 0x40, 0xe0, 0x00, 0x40, 0x60, 0x00, 0x00, 0x40, 0x60, 0x20, 0x00, 0x40, 0x60,
+ 0x40, 0x00, 0x40, 0x60, 0x60, 0x00, 0x40, 0x60, 0x80, 0x00, 0x40, 0x60, 0xa0, 0x00, 0x40, 0x60,
+ 0xc0, 0x00, 0x40, 0x60, 0xe0, 0x00, 0x40, 0x80, 0x00, 0x00, 0x40, 0x80, 0x20, 0x00, 0x40, 0x80,
+ 0x40, 0x00, 0x40, 0x80, 0x60, 0x00, 0x40, 0x80, 0x80, 0x00, 0x40, 0x80, 0xa0, 0x00, 0x40, 0x80,
+ 0xc0, 0x00, 0x40, 0x80, 0xe0, 0x00, 0x40, 0xa0, 0x00, 0x00, 0x40, 0xa0, 0x20, 0x00, 0x40, 0xa0,
+ 0x40, 0x00, 0x40, 0xa0, 0x60, 0x00, 0x40, 0xa0, 0x80, 0x00, 0x40, 0xa0, 0xa0, 0x00, 0x40, 0xa0,
+ 0xc0, 0x00, 0x40, 0xa0, 0xe0, 0x00, 0x40, 0xc0, 0x00, 0x00, 0x40, 0xc0, 0x20, 0x00, 0x40, 0xc0,
+ 0x40, 0x00, 0x40, 0xc0, 0x60, 0x00, 0x40, 0xc0, 0x80, 0x00, 0x40, 0xc0, 0xa0, 0x00, 0x40, 0xc0,
+ 0xc0, 0x00, 0x40, 0xc0, 0xe0, 0x00, 0x40, 0xe0, 0x00, 0x00, 0x40, 0xe0, 0x20, 0x00, 0x40, 0xe0,
+ 0x40, 0x00, 0x40, 0xe0, 0x60, 0x00, 0x40, 0xe0, 0x80, 0x00, 0x40, 0xe0, 0xa0, 0x00, 0x40, 0xe0,
+ 0xc0, 0x00, 0x40, 0xe0, 0xe0, 0x00, 0x80, 0x00, 0x00, 0x00, 0x80, 0x00, 0x20, 0x00, 0x80, 0x00,
+ 0x40, 0x00, 0x80, 0x00, 0x60, 0x00, 0x80, 0x00, 0x80, 0x00, 0x80, 0x00, 0xa0, 0x00, 0x80, 0x00,
+ 0xc0, 0x00, 0x80, 0x00, 0xe0, 0x00, 0x80, 0x20, 0x00, 0x00, 0x80, 0x20, 0x20, 0x00, 0x80, 0x20,
+ 0x40, 0x00, 0x80, 0x20, 0x60, 0x00, 0x80, 0x20, 0x80, 0x00, 0x80, 0x20, 0xa0, 0x00, 0x80, 0x20,
+ 0xc0, 0x00, 0x80, 0x20, 0xe0, 0x00, 0x80, 0x40, 0x00, 0x00, 0x80, 0x40, 0x20, 0x00, 0x80, 0x40,
+ 0x40, 0x00, 0x80, 0x40, 0x60, 0x00, 0x80, 0x40, 0x80, 0x00, 0x80, 0x40, 0xa0, 0x00, 0x80, 0x40,
+ 0xc0, 0x00, 0x80, 0x40, 0xe0, 0x00, 0x80, 0x60, 0x00, 0x00, 0x80, 0x60, 0x20, 0x00, 0x80, 0x60,
+ 0x40, 0x00, 0x80, 0x60, 0x60, 0x00, 0x80, 0x60, 0x80, 0x00, 0x80, 0x60, 0xa0, 0x00, 0x80, 0x60,
+ 0xc0, 0x00, 0x80, 0x60, 0xe0, 0x00, 0x80, 0x80, 0x00, 0x00, 0x80, 0x80, 0x20, 0x00, 0x80, 0x80,
+ 0x40, 0x00, 0x80, 0x80, 0x60, 0x00, 0x80, 0x80, 0x80, 0x00, 0x80, 0x80, 0xa0, 0x00, 0x80, 0x80,
+ 0xc0, 0x00, 0x80, 0x80, 0xe0, 0x00, 0x80, 0xa0, 0x00, 0x00, 0x80, 0xa0, 0x20, 0x00, 0x80, 0xa0,
+ 0x40, 0x00, 0x80, 0xa0, 0x60, 0x00, 0x80, 0xa0, 0x80, 0x00, 0x80, 0xa0, 0xa0, 0x00, 0x80, 0xa0,
+ 0xc0, 0x00, 0x80, 0xa0, 0xe0, 0x00, 0x80, 0xc0, 0x00, 0x00, 0x80, 0xc0, 0x20, 0x00, 0x80, 0xc0,
+ 0x40, 0x00, 0x80, 0xc0, 0x60, 0x00, 0x80, 0xc0, 0x80, 0x00, 0x80, 0xc0, 0xa0, 0x00, 0x80, 0xc0,
+ 0xc0, 0x00, 0x80, 0xc0, 0xe0, 0x00, 0x80, 0xe0, 0x00, 0x00, 0x80, 0xe0, 0x20, 0x00, 0x80, 0xe0,
+ 0x40, 0x00, 0x80, 0xe0, 0x60, 0x00, 0x80, 0xe0, 0x80, 0x00, 0x80, 0xe0, 0xa0, 0x00, 0x80, 0xe0,
+ 0xc0, 0x00, 0x80, 0xe0, 0xe0, 0x00, 0xc0, 0x00, 0x00, 0x00, 0xc0, 0x00, 0x20, 0x00, 0xc0, 0x00,
+ 0x40, 0x00, 0xc0, 0x00, 0x60, 0x00, 0xc0, 0x00, 0x80, 0x00, 0xc0, 0x00, 0xa0, 0x00, 0xc0, 0x00,
+ 0xc0, 0x00, 0xc0, 0x00, 0xe0, 0x00, 0xc0, 0x20, 0x00, 0x00, 0xc0, 0x20, 0x20, 0x00, 0xc0, 0x20,
+ 0x40, 0x00, 0xc0, 0x20, 0x60, 0x00, 0xc0, 0x20, 0x80, 0x00, 0xc0, 0x20, 0xa0, 0x00, 0xc0, 0x20,
+ 0xc0, 0x00, 0xc0, 0x20, 0xe0, 0x00, 0xc0, 0x40, 0x00, 0x00, 0xc0, 0x40, 0x20, 0x00, 0xc0, 0x40,
+ 0x40, 0x00, 0xc0, 0x40, 0x60, 0x00, 0xc0, 0x40, 0x80, 0x00, 0xc0, 0x40, 0xa0, 0x00, 0xc0, 0x40,
+ 0xc0, 0x00, 0xc0, 0x40, 0xe0, 0x00, 0xc0, 0x60, 0x00, 0x00, 0xc0, 0x60, 0x20, 0x00, 0xc0, 0x60,
+ 0x40, 0x00, 0xc0, 0x60, 0x60, 0x00, 0xc0, 0x60, 0x80, 0x00, 0xc0, 0x60, 0xa0, 0x00, 0xc0, 0x60,
+ 0xc0, 0x00, 0xc0, 0x60, 0xe0, 0x00, 0xc0, 0x80, 0x00, 0x00, 0xc0, 0x80, 0x20, 0x00, 0xc0, 0x80,
+ 0x40, 0x00, 0xc0, 0x80, 0x60, 0x00, 0xc0, 0x80, 0x80, 0x00, 0xc0, 0x80, 0xa0, 0x00, 0xc0, 0x80,
+ 0xc0, 0x00, 0xc0, 0x80, 0xe0, 0x00, 0xc0, 0xa0, 0x00, 0x00, 0xc0, 0xa0, 0x20, 0x00, 0xc0, 0xa0,
+ 0x40, 0x00, 0xc0, 0xa0, 0x60, 0x00, 0xc0, 0xa0, 0x80, 0x00, 0xc0, 0xa0, 0xa0, 0x00, 0xc0, 0xa0,
+ 0xc0, 0x00, 0xc0, 0xa0, 0xe0, 0x00, 0xc0, 0xc0, 0x00, 0x00, 0xc0, 0xc0, 0x20, 0x00, 0xc0, 0xc0,
+ 0x40, 0x00, 0xc0, 0xc0, 0x60, 0x00, 0xc0, 0xc0, 0x80, 0x00, 0xc0, 0xc0, 0xa0, 0x00, 0xf0, 0xfb,
+ 0xff, 0x00, 0xa4, 0xa0, 0xa0, 0x00, 0x80, 0x80, 0x80, 0x00, 0x00, 0x00, 0xff, 0x00, 0x00, 0xff,
+ 0x00, 0x00, 0x00, 0xff, 0xff, 0x00, 0xff, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0xff, 0xff,
+ 0x00, 0x00, 0xff, 0xff, 0xff, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9,
+ 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0xf9, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00,
+ 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0xf9,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9,
+ 0xf9, 0xf9, 0xf9, 0xf9, 0xf9, 0xf9
+} ;
+
+unsigned char systemfont[] = {
+ 0x42, 0x4d, 0x36, 0x84, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x04, 0x00, 0x00, 0x28, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x80, 0x00, 0x00, 0x00, 0x01, 0x00, 0x08, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x80, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x70, 0x0b, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x00, 0xff, 0x00, 0x80, 0x80,
+ 0xff, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x01, 0x00, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x01, 0x02, 0x02, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x02, 0x00, 0x01, 0x02, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x00, 0x02, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x02, 0x00, 0x02, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x02, 0x01, 0x00, 0x02, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x00, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02,
+ 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x00,
+ 0x00, 0x01, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x01, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x00,
+ 0x00, 0x01, 0x02, 0x01, 0x02, 0x01, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x01, 0x01, 0x00, 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x01, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x00, 0x01, 0x02, 0x00, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x02, 0x01,
+ 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x01, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x01, 0x00, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x00, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x01, 0x01, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x02, 0x01, 0x02, 0x01, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00,
+ 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x00, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x02, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01,
+ 0x00, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x00, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x00, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x02, 0x00, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x02, 0x00, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x00, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x00, 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02,
+ 0x00, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x00, 0x01, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x01,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x00, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02, 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x02,
+ 0x02, 0x02, 0x02, 0x02, 0x02, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
+ 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
+} ;
+
+Common::SeekableReadStream *BaseResources::getFile(const Common::String &filename) {
+ if (scumm_stricmp(filename.c_str(), "invalid.bmp") == 0) {
+ return new Common::MemoryReadStream(invalid, sizeof(invalid), DisposeAfterUse::NO);
+ } else if (scumm_stricmp(filename.c_str(), "invalid_debug.bmp") == 0) {
+ return new Common::MemoryReadStream(invaliddebug, sizeof(invalid), DisposeAfterUse::NO);
+ } else if (scumm_stricmp(filename.c_str(), "syste_font.bmp") == 0) {
+ return new Common::MemoryReadStream(systemfont, sizeof(invalid), DisposeAfterUse::NO);
+ }
+ return NULL;
+}
+
+bool BaseResources::hasFile(const Common::String &filename) {
+ if (scumm_stricmp(filename.c_str(), "invalid.bmp") == 0) {
+ return true;
+ } else if (scumm_stricmp(filename.c_str(), "invalid_debug.bmp") == 0) {
+ return true;
+ } else if (scumm_stricmp(filename.c_str(), "syste_font.bmp") == 0) {
+ return true;
+ }
+ return false;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_resources.h b/engines/wintermute/base/file/base_resources.h
new file mode 100644
index 0000000000..91c30bcfa7
--- /dev/null
+++ b/engines/wintermute/base/file/base_resources.h
@@ -0,0 +1,45 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_RESOURCES_H
+#define WINTERMUTE_BASE_RESOURCES_H
+
+#include "common/stream.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+class BaseResources {
+public:
+ static Common::SeekableReadStream *getFile(const Common::String &filename);
+ static bool hasFile(const Common::String &filename);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/base_save_thumb_file.cpp b/engines/wintermute/base/file/base_save_thumb_file.cpp
new file mode 100644
index 0000000000..5bdab0853e
--- /dev/null
+++ b/engines/wintermute/base/file/base_save_thumb_file.cpp
@@ -0,0 +1,154 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_persistence_manager.h"
+#include "engines/wintermute/base/file/base_save_thumb_file.h"
+#include "engines/wintermute/platform_osystem.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSaveThumbFile::BaseSaveThumbFile() {
+ _data = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSaveThumbFile::~BaseSaveThumbFile() {
+ close();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSaveThumbFile::open(const Common::String &filename) {
+ close();
+
+ if (scumm_strnicmp(filename.c_str(), "savegame:", 9) != 0) {
+ return STATUS_FAILED;
+ }
+
+ char *tempFilename = new char[strlen(filename.c_str()) - 8];
+ strcpy(tempFilename, filename.c_str() + 9);
+ for (uint32 i = 0; i < strlen(tempFilename); i++) {
+ if (tempFilename[i] < '0' || tempFilename[i] > '9') {
+ tempFilename[i] = '\0';
+ break;
+ }
+ }
+
+ // get slot number from name
+ int slot = atoi(tempFilename);
+ delete[] tempFilename;
+
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ Common::String slotFilename = pm->getFilenameForSlot(slot);
+ if (!pm) {
+ return STATUS_FAILED;
+ }
+
+ if (DID_FAIL(pm->initLoad(slotFilename))) {
+ delete pm;
+ return STATUS_FAILED;
+ }
+
+ bool res;
+
+ if (pm->_thumbnailDataSize != 0) {
+ _data = new byte[pm->_thumbnailDataSize];
+ memcpy(_data, pm->_thumbnailData, pm->_thumbnailDataSize);
+ _size = pm->_thumbnailDataSize;
+ res = STATUS_OK;
+ } else {
+ res = STATUS_FAILED;
+ }
+ delete pm;
+
+ return res;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSaveThumbFile::close() {
+ delete[] _data;
+ _data = NULL;
+
+ _pos = 0;
+ _size = 0;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSaveThumbFile::read(void *buffer, uint32 size) {
+ if (!_data || _pos + size > _size) {
+ return STATUS_FAILED;
+ }
+
+ memcpy(buffer, (byte *)_data + _pos, size);
+ _pos += size;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSaveThumbFile::seek(uint32 pos, int whence) {
+ if (!_data) {
+ return STATUS_FAILED;
+ }
+
+ uint32 newPos = 0;
+
+ switch (whence) {
+ case SEEK_SET:
+ newPos = pos;
+ break;
+ case SEEK_END:
+ newPos = _size + pos;
+ break;
+ case SEEK_CUR:
+ newPos = _pos + pos;
+ break;
+ }
+
+ if (newPos > _size) {
+ return STATUS_FAILED;
+ } else {
+ _pos = newPos;
+ }
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/file/base_save_thumb_file.h b/engines/wintermute/base/file/base_save_thumb_file.h
new file mode 100644
index 0000000000..3b217525fd
--- /dev/null
+++ b/engines/wintermute/base/file/base_save_thumb_file.h
@@ -0,0 +1,52 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SAVETHUMBFILE_H
+#define WINTERMUTE_BASE_SAVETHUMBFILE_H
+
+
+#include "engines/wintermute/base/file/base_file.h"
+
+namespace Wintermute {
+
+//TODO: Get rid of this
+class BaseSaveThumbFile : public BaseFile {
+public:
+ BaseSaveThumbFile();
+ virtual ~BaseSaveThumbFile();
+ virtual bool seek(uint32 pos, int whence = SEEK_SET);
+ virtual bool read(void *buffer, uint32 size);
+ virtual bool close();
+ virtual bool open(const Common::String &filename);
+private:
+ byte *_data;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/file/dcpackage.h b/engines/wintermute/base/file/dcpackage.h
new file mode 100644
index 0000000000..2234139408
--- /dev/null
+++ b/engines/wintermute/base/file/dcpackage.h
@@ -0,0 +1,80 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef _DCPACKAGE_H_
+#define _DCPACKAGE_H_
+
+
+#define PACKAGE_MAGIC_1 0xDEC0ADDE
+#define PACKAGE_MAGIC_2 0x4B4E554A // "JUNK"
+#define PACKAGE_VERSION 0x00000200
+#define PACKAGE_EXTENSION "dcp"
+
+#include "common/stream.h"
+
+namespace Wintermute {
+
+struct TPackageHeader {
+ uint32 _magic1;
+ uint32 _magic2;
+ uint32 _packageVersion;
+ uint32 _gameVersion;
+ byte _priority;
+ byte _cd;
+ bool _masterIndex;
+ uint32 _creationTime;
+ char _desc[100];
+ uint32 _numDirs;
+ // base_package.cpp:
+ void readFromStream(Common::ReadStream *stream);
+};
+
+/*
+v2: uint32 DirOffset
+
+
+Dir: byte NameLength
+ char Name [NameLength]
+ byte CD;
+ uint32 NumEntries
+
+
+Entry: byte NameLength
+ char Name [NameLength]
+ uint32 Offset
+ uint32 Length
+ uint32 CompLength
+ uint32 Flags
+v2: uint32 TimeDate1
+ uint32 TimeDate2 // not used
+
+*/
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/font/base_font.cpp b/engines/wintermute/base/font/base_font.cpp
new file mode 100644
index 0000000000..87dd3da5a3
--- /dev/null
+++ b/engines/wintermute/base/font/base_font.cpp
@@ -0,0 +1,140 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/font/base_font_bitmap.h"
+#include "engines/wintermute/base/font/base_font_truetype.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_file_manager.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(BaseFont, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseFont::BaseFont(BaseGame *inGame) : BaseObject(inGame) {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseFont::~BaseFont() {
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseFont::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseFont::getTextHeight(byte *text, int width) {
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseFont::getTextWidth(byte *text, int maxLength) {
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFont::getLetterHeight() {
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFont::persist(BasePersistenceManager *persistMgr) {
+
+ BaseObject::persist(persistMgr);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseFont *BaseFont::createFromFile(BaseGame *gameRef, const Common::String &filename) {
+ if (isTrueType(gameRef, filename)) {
+ BaseFontTT *font = new BaseFontTT(gameRef);
+ if (font) {
+ if (DID_FAIL(font->loadFile(filename))) {
+ delete font;
+ return NULL;
+ }
+ }
+ return font;
+ } else {
+ BaseFontBitmap *font = new BaseFontBitmap(gameRef);
+ if (font) {
+ if (DID_FAIL(font->loadFile(filename))) {
+ delete font;
+ return NULL;
+ }
+ }
+ return font;
+ }
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(FONT)
+TOKEN_DEF(TTFONT)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////////
+bool BaseFont::isTrueType(BaseGame *gameRef, const Common::String &filename) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(TTFONT)
+ TOKEN_TABLE_END
+
+
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer == NULL) {
+ return false;
+ }
+
+ byte *workBuffer = buffer;
+
+ char *params;
+ BaseParser parser;
+
+ bool ret = false;
+ if (parser.getCommand((char **)&workBuffer, commands, (char **)&params) == TOKEN_TTFONT) {
+ ret = true;
+ }
+
+ delete[] buffer;
+ return ret;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font.h b/engines/wintermute/base/font/base_font.h
new file mode 100644
index 0000000000..0abe62ab98
--- /dev/null
+++ b/engines/wintermute/base/font/base_font.h
@@ -0,0 +1,61 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FONT_H
+#define WINTERMUTE_BASE_FONT_H
+
+#include "engines/wintermute/base/base_object.h"
+
+#define NUM_CHARACTERS 256
+
+namespace Wintermute {
+
+class BaseFont: public BaseObject {
+public:
+ DECLARE_PERSISTENT(BaseFont, BaseObject)
+ virtual int getTextWidth(byte *text, int maxLength = -1);
+ virtual int getTextHeight(byte *text, int width);
+ virtual void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1);
+ virtual int getLetterHeight();
+
+ virtual void initLoop() {}
+ virtual void afterLoad() {}
+ BaseFont(BaseGame *inGame);
+ virtual ~BaseFont();
+
+ static BaseFont *createFromFile(BaseGame *game, const Common::String &filename);
+
+private:
+ //bool loadBuffer(byte * Buffer);
+ //bool loadFile(const char* Filename);
+ static bool isTrueType(BaseGame *game, const Common::String &filename);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/font/base_font_bitmap.cpp b/engines/wintermute/base/font/base_font_bitmap.cpp
new file mode 100644
index 0000000000..fced08c7e2
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_bitmap.cpp
@@ -0,0 +1,589 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/font/base_font_bitmap.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_frame.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_frame.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/platform_osystem.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(BaseFontBitmap, false)
+
+//////////////////////////////////////////////////////////////////////
+BaseFontBitmap::BaseFontBitmap(BaseGame *inGame) : BaseFont(inGame) {
+ _subframe = NULL;
+ _sprite = NULL;
+ _widthsFrame = 0;
+ memset(_widths, 0, NUM_CHARACTERS);
+ _tileWidth = _tileHeight = _numColumns = 0;
+ _fontextFix = false;
+ _freezable = false;
+ _wholeCell = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseFontBitmap::~BaseFontBitmap() {
+ delete _subframe;
+ delete _sprite;
+ _subframe = NULL;
+ _sprite = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseFontBitmap::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
+ textHeightDraw(text, x, y, width, align, true, maxHeight, maxLength);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseFontBitmap::getTextHeight(byte *text, int width) {
+ return textHeightDraw(text, 0, 0, width, TAL_LEFT, false);
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseFontBitmap::getTextWidth(byte *text, int maxLength) {
+ AnsiString str;
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::utf8ToWide(Utf8String((char *)text));
+ str = StringUtil::wideToAnsi(wstr);
+ } else {
+ str = AnsiString((char *)text);
+ }
+
+ if (maxLength >= 0 && str.size() > (uint32)maxLength) {
+ str = Common::String(str.c_str(), (uint32)maxLength);
+ }
+ //str.substr(0, maxLength); // TODO: Remove
+
+ int textWidth = 0;
+ for (int i = 0; (uint32)i < str.size(); i++) {
+ textWidth += getCharWidth((byte)str[i]);
+ }
+
+ return textWidth;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+int BaseFontBitmap::textHeightDraw(const byte *text, int x, int y, int width, TTextAlign align, bool draw, int maxHeight, int maxLength) {
+ if (maxLength == 0) {
+ return 0;
+ }
+
+ if (text == NULL || text[0] == '\0') {
+ return _tileHeight;
+ }
+
+ AnsiString str;
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::utf8ToWide(Utf8String((const char *)text));
+ str = StringUtil::wideToAnsi(wstr);
+ } else {
+ str = AnsiString((const char *)text);
+ }
+ if (str.empty()) {
+ return 0;
+ }
+
+ int lineLength = 0;
+ int realLength = 0;
+ int numLines = 0;
+
+ int i;
+
+ int index = -1;
+ int start = 0;
+ int end = 0;
+ int last_end = 0;
+
+ bool done = false;
+ bool newLine = false;
+ bool longLine = false;
+
+ if (draw) {
+ _gameRef->_renderer->startSpriteBatch();
+ }
+
+ while (!done) {
+ if (maxHeight > 0 && (numLines + 1)*_tileHeight > maxHeight) {
+ if (draw) {
+ _gameRef->_renderer->endSpriteBatch();
+ }
+ return numLines * _tileHeight;
+ }
+
+ index++;
+
+ if (str[index] == ' ' && (maxHeight < 0 || maxHeight / _tileHeight > 1)) {
+ end = index - 1;
+ realLength = lineLength;
+ }
+
+ if (str[index] == '\n') {
+ end = index - 1;
+ realLength = lineLength;
+ newLine = true;
+ }
+
+ if (lineLength + getCharWidth(str[index]) > width && last_end == end) {
+ end = index - 1;
+ realLength = lineLength;
+ newLine = true;
+ longLine = true;
+ }
+
+ if ((int)str.size() == (index + 1) || (maxLength >= 0 && index == maxLength - 1)) {
+ done = true;
+ if (!newLine) {
+ end = index;
+ lineLength += getCharWidth(str[index]);
+ realLength = lineLength;
+ }
+ } else {
+ lineLength += getCharWidth(str[index]);
+ }
+
+ if ((lineLength > width) || done || newLine) {
+ if (end < 0) {
+ done = true;
+ }
+ int startX;
+ switch (align) {
+ case TAL_CENTER:
+ startX = x + (width - realLength) / 2;
+ break;
+ case TAL_RIGHT:
+ startX = x + width - realLength;
+ break;
+ case TAL_LEFT:
+ startX = x;
+ break;
+ default:
+ error("BaseFontBitmap::TextHeightDraw - Unhandled enum");
+ break;
+ }
+ for (i = start; i < end + 1; i++) {
+ if (draw) {
+ drawChar(str[i], startX, y);
+ }
+ startX += getCharWidth(str[i]);
+ }
+ y += _tileHeight;
+ last_end = end;
+ if (longLine) {
+ end--;
+ }
+ start = end + 2;
+ index = end + 1;
+ lineLength = 0;
+ newLine = false;
+ longLine = false;
+ numLines++;
+ }
+ }
+
+ if (draw) {
+ _gameRef->_renderer->endSpriteBatch();
+ }
+
+ return numLines * _tileHeight;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseFontBitmap::drawChar(byte c, int x, int y) {
+ if (_fontextFix) {
+ c--;
+ }
+
+ int row, col;
+
+ row = c / _numColumns;
+ col = c % _numColumns;
+
+ Rect32 rect;
+ /* l t r b */
+ int tileWidth;
+ if (_wholeCell) {
+ tileWidth = _tileWidth;
+ } else {
+ tileWidth = _widths[c];
+ }
+
+ BasePlatform::setRect(&rect, col * _tileWidth, row * _tileHeight, col * _tileWidth + tileWidth, (row + 1)*_tileHeight);
+ bool handled = false;
+ if (_sprite) {
+ _sprite->getCurrentFrame();
+ if (_sprite->_currentFrame >= 0 && _sprite->_currentFrame < (int32)_sprite->_frames.size() && _sprite->_frames[_sprite->_currentFrame]) {
+ if (_sprite->_frames[_sprite->_currentFrame]->_subframes.size() > 0) {
+ _sprite->_frames[_sprite->_currentFrame]->_subframes[0]->_surface->displayTrans(x, y, rect);
+ }
+ handled = true;
+ }
+ }
+ if (!handled && _subframe) {
+ _subframe->_surface->displayTrans(x, y, rect);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseFontBitmap::loadFile(const Common::String &filename) {
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer == NULL) {
+ _gameRef->LOG(0, "BaseFontBitmap::LoadFile failed for file '%s'", filename.c_str());
+ return STATUS_FAILED;
+ }
+
+ bool ret;
+
+ setFilename(filename.c_str());
+
+ if (DID_FAIL(ret = loadBuffer(buffer))) {
+ _gameRef->LOG(0, "Error parsing FONT file '%s'", filename.c_str());
+ }
+
+ delete[] buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(FONTEXT_FIX)
+TOKEN_DEF(FONT)
+TOKEN_DEF(IMAGE)
+TOKEN_DEF(TRANSPARENT)
+TOKEN_DEF(COLUMNS)
+TOKEN_DEF(TILE_WIDTH)
+TOKEN_DEF(TILE_HEIGHT)
+TOKEN_DEF(DEFAULT_WIDTH)
+TOKEN_DEF(WIDTHS)
+TOKEN_DEF(AUTO_WIDTH)
+TOKEN_DEF(SPACE_WIDTH)
+TOKEN_DEF(EXPAND_WIDTH)
+TOKEN_DEF(EDITOR_PROPERTY)
+TOKEN_DEF(SPRITE)
+TOKEN_DEF(WIDTHS_FRAME)
+TOKEN_DEF(PAINT_WHOLE_CELL)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////
+bool BaseFontBitmap::loadBuffer(byte *buffer) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(FONTEXT_FIX)
+ TOKEN_TABLE(FONT)
+ TOKEN_TABLE(IMAGE)
+ TOKEN_TABLE(TRANSPARENT)
+ TOKEN_TABLE(COLUMNS)
+ TOKEN_TABLE(TILE_WIDTH)
+ TOKEN_TABLE(TILE_HEIGHT)
+ TOKEN_TABLE(DEFAULT_WIDTH)
+ TOKEN_TABLE(WIDTHS)
+ TOKEN_TABLE(AUTO_WIDTH)
+ TOKEN_TABLE(SPACE_WIDTH)
+ TOKEN_TABLE(EXPAND_WIDTH)
+ TOKEN_TABLE(EDITOR_PROPERTY)
+ TOKEN_TABLE(SPRITE)
+ TOKEN_TABLE(WIDTHS_FRAME)
+ TOKEN_TABLE(PAINT_WHOLE_CELL)
+ TOKEN_TABLE_END
+
+ char *params;
+ int cmd;
+ BaseParser parser;
+
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_FONT) {
+ _gameRef->LOG(0, "'FONT' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = (byte *)params;
+
+ int widths[300];
+ int num = 0, defaultWidth = 8;
+ int lastWidth = 0;
+ int i;
+ int r = 255, g = 255, b = 255;
+ bool custoTrans = false;
+ char *surfaceFile = NULL;
+ char *spriteFile = NULL;
+
+ bool autoWidth = false;
+ int spaceWidth = 0;
+ int expandWidth = 0;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+
+ switch (cmd) {
+ case TOKEN_IMAGE:
+ surfaceFile = (char *)params;
+ break;
+
+ case TOKEN_SPRITE:
+ spriteFile = (char *)params;
+ break;
+
+ case TOKEN_TRANSPARENT:
+ parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
+ custoTrans = true;
+ break;
+
+ case TOKEN_WIDTHS:
+ parser.scanStr(params, "%D", widths, &num);
+ for (i = 0; lastWidth < NUM_CHARACTERS && num > 0; lastWidth++, num--, i++) {
+ _widths[lastWidth] = (byte)widths[i];
+ }
+ break;
+
+ case TOKEN_DEFAULT_WIDTH:
+ parser.scanStr(params, "%d", &defaultWidth);
+ break;
+
+ case TOKEN_WIDTHS_FRAME:
+ parser.scanStr(params, "%d", &_widthsFrame);
+ break;
+
+ case TOKEN_COLUMNS:
+ parser.scanStr(params, "%d", &_numColumns);
+ break;
+
+ case TOKEN_TILE_WIDTH:
+ parser.scanStr(params, "%d", &_tileWidth);
+ break;
+
+ case TOKEN_TILE_HEIGHT:
+ parser.scanStr(params, "%d", &_tileHeight);
+ break;
+
+ case TOKEN_AUTO_WIDTH:
+ parser.scanStr(params, "%b", &autoWidth);
+ break;
+
+ case TOKEN_FONTEXT_FIX:
+ parser.scanStr(params, "%b", &_fontextFix);
+ break;
+
+ case TOKEN_PAINT_WHOLE_CELL:
+ parser.scanStr(params, "%b", &_wholeCell);
+ break;
+
+ case TOKEN_SPACE_WIDTH:
+ parser.scanStr(params, "%d", &spaceWidth);
+ break;
+
+ case TOKEN_EXPAND_WIDTH:
+ parser.scanStr(params, "%d", &expandWidth);
+ break;
+
+ case TOKEN_EDITOR_PROPERTY:
+ parseEditorProperty((byte *)params, false);
+ break;
+ }
+
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in FONT definition");
+ return STATUS_FAILED;
+ }
+
+ if (spriteFile != NULL) {
+ delete _sprite;
+ _sprite = new BaseSprite(_gameRef, this);
+ if (!_sprite || DID_FAIL(_sprite->loadFile(spriteFile))) {
+ delete _sprite;
+ _sprite = NULL;
+ }
+ }
+
+ if (surfaceFile != NULL && !_sprite) {
+ _subframe = new BaseSubFrame(_gameRef);
+ if (custoTrans) {
+ _subframe->setSurface(surfaceFile, false, r, g, b);
+ } else {
+ _subframe->setSurface(surfaceFile);
+ }
+ }
+
+
+ if (((_subframe == NULL || _subframe->_surface == NULL) && _sprite == NULL) || _numColumns == 0 || _tileWidth == 0 || _tileHeight == 0) {
+ _gameRef->LOG(0, "Incomplete font definition");
+ return STATUS_FAILED;
+ }
+
+ if (autoWidth) {
+ // calculate characters width
+ getWidths();
+
+ // do we need to modify widths?
+ if (expandWidth != 0) {
+ for (i = 0; i < NUM_CHARACTERS; i++) {
+ int newWidth = (int)_widths[i] + expandWidth;
+ if (newWidth < 0) {
+ newWidth = 0;
+ }
+
+ _widths[i] = (byte)newWidth;
+ }
+ }
+
+ // handle space character
+ uint32 spaceChar = ' ';
+ if (_fontextFix) {
+ spaceChar--;
+ }
+
+ if (spaceWidth != 0) {
+ _widths[spaceChar] = spaceWidth;
+ } else {
+ if (_widths[spaceChar] == expandWidth || _widths[spaceChar] == 0) {
+ _widths[spaceChar] = (_widths['m'] + _widths['i']) / 2;
+ }
+ }
+ } else {
+ for (i = lastWidth; i < NUM_CHARACTERS; i++) {
+ _widths[i] = defaultWidth;
+ }
+ }
+
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontBitmap::persist(BasePersistenceManager *persistMgr) {
+
+ BaseFont::persist(persistMgr);
+ persistMgr->transfer(TMEMBER(_numColumns));
+
+ persistMgr->transfer(TMEMBER(_subframe));
+ persistMgr->transfer(TMEMBER(_tileHeight));
+ persistMgr->transfer(TMEMBER(_tileWidth));
+ persistMgr->transfer(TMEMBER(_sprite));
+ persistMgr->transfer(TMEMBER(_widthsFrame));
+
+ if (persistMgr->getIsSaving()) {
+ persistMgr->putBytes(_widths, sizeof(_widths));
+ } else {
+ persistMgr->getBytes(_widths, sizeof(_widths));
+ }
+
+
+ persistMgr->transfer(TMEMBER(_fontextFix));
+ persistMgr->transfer(TMEMBER(_wholeCell));
+
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFontBitmap::getCharWidth(byte index) {
+ if (_fontextFix) {
+ index--;
+ }
+ return _widths[index];
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontBitmap::getWidths() {
+ BaseSurface *surf = NULL;
+
+ if (_sprite) {
+ if (_widthsFrame >= 0 && _widthsFrame < (int32)_sprite->_frames.size()) {
+ if (_sprite->_frames[_widthsFrame] && (int32)_sprite->_frames[_widthsFrame]->_subframes.size() > 0) {
+ surf = _sprite->_frames[_widthsFrame]->_subframes[0]->_surface;
+ }
+ }
+ }
+ if (surf == NULL && _subframe) {
+ surf = _subframe->_surface;
+ }
+ if (!surf || DID_FAIL(surf->startPixelOp())) {
+ return STATUS_FAILED;
+ }
+
+
+ for (int i = 0; i < NUM_CHARACTERS; i++) {
+ int xxx = (i % _numColumns) * _tileWidth;
+ int yyy = (i / _numColumns) * _tileHeight;
+
+
+ int minCol = -1;
+ for (int row = 0; row < _tileHeight; row++) {
+ for (int col = _tileWidth - 1; col >= minCol + 1; col--) {
+ if (xxx + col < 0 || xxx + col >= surf->getWidth() || yyy + row < 0 || yyy + row >= surf->getHeight()) {
+ continue;
+ }
+ if (!surf->isTransparentAtLite(xxx + col, yyy + row)) {
+ //min_col = col;
+ minCol = MAX(col, minCol);
+ break;
+ }
+ }
+ if (minCol == _tileWidth - 1) {
+ break;
+ }
+ }
+
+ _widths[i] = minCol + 1;
+ }
+ surf->endPixelOp();
+ /*
+ _gameRef->LOG(0, "----- %s ------", _filename);
+ for(int j=0; j<16; j++)
+ {
+ _gameRef->LOG(0, "%02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d %02d", _widths[j*16+0], _widths[j*16+1], _widths[j*16+2], _widths[j*16+3], _widths[j*16+4], _widths[j*16+5], _widths[j*16+6], _widths[j*16+7], _widths[j*16+8], _widths[j*16+9], _widths[j*16+10], _widths[j*16+11], _widths[j*16+12], _widths[j*16+13], _widths[j*16+14], _widths[j*16+15]);
+ }
+ */
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFontBitmap::getLetterHeight() {
+ return _tileHeight;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_bitmap.h b/engines/wintermute/base/font/base_font_bitmap.h
new file mode 100644
index 0000000000..2f3a69d097
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_bitmap.h
@@ -0,0 +1,71 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FONTBITMAP_H
+#define WINTERMUTE_BASE_FONTBITMAP_H
+
+
+#include "engines/wintermute/base/font/base_font.h"
+
+namespace Wintermute {
+class BaseSubFrame;
+class BaseFontBitmap : public BaseFont {
+public:
+ DECLARE_PERSISTENT(BaseFontBitmap, BaseFont)
+ bool loadBuffer(byte *Buffer);
+ bool loadFile(const Common::String &filename);
+ virtual int getTextWidth(byte *text, int maxLength = -1);
+ virtual int getTextHeight(byte *text, int width);
+ virtual void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1);
+ virtual int getLetterHeight();
+
+ BaseFontBitmap(BaseGame *inGame);
+ virtual ~BaseFontBitmap();
+
+private:
+ bool getWidths();
+ BaseSprite *_sprite;
+ int _widthsFrame;
+ bool _fontextFix;
+ int _numColumns;
+ int _tileHeight;
+ int _tileWidth;
+ byte _widths[NUM_CHARACTERS];
+ BaseSubFrame *_subframe;
+ bool _wholeCell;
+
+ int getCharWidth(byte index);
+ void drawChar(byte c, int x, int y);
+
+ int textHeightDraw(const byte *text, int x, int y, int width, TTextAlign align, bool draw, int max_height = -1, int maxLength = -1);
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/font/base_font_storage.cpp b/engines/wintermute/base/font/base_font_storage.cpp
new file mode 100644
index 0000000000..d26fa1d593
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_storage.cpp
@@ -0,0 +1,142 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/font/base_font_storage.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(BaseFontStorage, true)
+
+//////////////////////////////////////////////////////////////////////////
+BaseFontStorage::BaseFontStorage(BaseGame *inGame) : BaseClass(inGame) {
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseFontStorage::~BaseFontStorage() {
+ cleanup(true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontStorage::cleanup(bool warn) {
+ for (uint32 i = 0; i < _fonts.size(); i++) {
+ if (warn) {
+ _gameRef->LOG(0, "Removing orphan font '%s'", _fonts[i]->getFilename());
+ }
+ delete _fonts[i];
+ }
+ _fonts.clear();
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontStorage::initLoop() {
+ for (uint32 i = 0; i < _fonts.size(); i++) {
+ _fonts[i]->initLoop();
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseFont *BaseFontStorage::addFont(const Common::String &filename) {
+ if (!filename.size()) {
+ return NULL;
+ }
+
+ for (uint32 i = 0; i < _fonts.size(); i++) {
+ if (scumm_stricmp(_fonts[i]->getFilename(), filename.c_str()) == 0) {
+ _fonts[i]->_refCount++;
+ return _fonts[i];
+ }
+ }
+
+ /*
+ BaseFont* font = new BaseFont(_gameRef);
+ if (!font) return NULL;
+
+ if (DID_FAIL(font->loadFile(filename))) {
+ delete font;
+ return NULL;
+ }
+ else {
+ font->_refCount = 1;
+ _fonts.add(font);
+ return font;
+ }
+ */
+ BaseFont *font = BaseFont::createFromFile(_gameRef, filename);
+ if (font) {
+ font->_refCount = 1;
+ _fonts.add(font);
+ }
+ return font;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontStorage::removeFont(BaseFont *font) {
+ if (!font) {
+ return STATUS_FAILED;
+ }
+
+ for (uint32 i = 0; i < _fonts.size(); i++) {
+ if (_fonts[i] == font) {
+ _fonts[i]->_refCount--;
+ if (_fonts[i]->_refCount <= 0) {
+ delete _fonts[i];
+ _fonts.remove_at(i);
+ }
+ break;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontStorage::persist(BasePersistenceManager *persistMgr) {
+
+ if (!persistMgr->getIsSaving()) {
+ cleanup(false);
+ }
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+ _fonts.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_storage.h b/engines/wintermute/base/font/base_font_storage.h
new file mode 100644
index 0000000000..60874167e7
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_storage.h
@@ -0,0 +1,55 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FONTSTORAGE_H
+#define WINTERMUTE_BASE_FONTSTORAGE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/coll_templ.h"
+
+namespace Wintermute {
+
+class BaseFont;
+
+class BaseFontStorage : public BaseClass {
+public:
+ DECLARE_PERSISTENT(BaseFontStorage, BaseClass)
+ bool cleanup(bool warn = false);
+ bool removeFont(BaseFont *font);
+ BaseFont *addFont(const Common::String &filename);
+ BaseFontStorage(BaseGame *inGame);
+ virtual ~BaseFontStorage();
+ BaseArray<BaseFont *> _fonts;
+ bool initLoop();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/font/base_font_truetype.cpp b/engines/wintermute/base/font/base_font_truetype.cpp
new file mode 100644
index 0000000000..599010bbd5
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_truetype.cpp
@@ -0,0 +1,605 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_file.h"
+#include "engines/wintermute/base/font/base_font_truetype.h"
+#include "engines/wintermute/utils/path_util.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "engines/wintermute/math/math_util.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_parser.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/wintermute.h"
+#include "graphics/fonts/ttf.h"
+#include "graphics/fontman.h"
+#include <limits.h>
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseFontTT, false)
+
+//////////////////////////////////////////////////////////////////////////
+BaseFontTT::BaseFontTT(BaseGame *inGame) : BaseFont(inGame) {
+ _fontHeight = 12;
+ _isBold = _isItalic = _isUnderline = _isStriked = false;
+
+ _fontFile = NULL;
+ _font = NULL;
+ _fallbackFont = NULL;
+ _deletableFont = NULL;
+
+ for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
+ _cachedTexts[i] = NULL;
+ }
+
+ _lineHeight = 0;
+ _maxCharWidth = _maxCharHeight = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseFontTT::~BaseFontTT(void) {
+ clearCache();
+
+ for (uint32 i = 0; i < _layers.size(); i++) {
+ delete _layers[i];
+ }
+ _layers.clear();
+
+ delete[] _fontFile;
+ _fontFile = NULL;
+
+ delete _deletableFont;
+ _font = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseFontTT::clearCache() {
+ for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
+ if (_cachedTexts[i]) {
+ delete _cachedTexts[i];
+ }
+ _cachedTexts[i] = NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseFontTT::initLoop() {
+ // we need more aggressive cache management on iOS not to waste too much memory on fonts
+ if (_gameRef->_constrainedMemory) {
+ // purge all cached images not used in the last frame
+ for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
+ if (_cachedTexts[i] == NULL) {
+ continue;
+ }
+
+ if (!_cachedTexts[i]->_marked) {
+ delete _cachedTexts[i];
+ _cachedTexts[i] = NULL;
+ } else {
+ _cachedTexts[i]->_marked = false;
+ }
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFontTT::getTextWidth(byte *text, int maxLength) {
+ WideString textStr;
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ textStr = StringUtil::utf8ToWide((char *)text);
+ } else {
+ textStr = StringUtil::ansiToWide((char *)text);
+ }
+
+ if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
+ textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+ }
+ //text = text.substr(0, MaxLength); // TODO: Remove
+
+ int textWidth, textHeight;
+ measureText(textStr, -1, -1, textWidth, textHeight);
+
+ return textWidth;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFontTT::getTextHeight(byte *text, int width) {
+ WideString textStr;
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ textStr = StringUtil::utf8ToWide((char *)text);
+ } else {
+ textStr = StringUtil::ansiToWide((char *)text);
+ }
+
+
+ int textWidth, textHeight;
+ measureText(textStr, width, -1, textWidth, textHeight);
+
+ return textHeight;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseFontTT::drawText(const byte *text, int x, int y, int width, TTextAlign align, int maxHeight, int maxLength) {
+ if (text == NULL || strcmp((const char *)text, "") == 0) {
+ return;
+ }
+
+ WideString textStr = (const char *)text;
+
+ // TODO: Why do we still insist on Widestrings everywhere?
+ /* if (_gameRef->_textEncoding == TEXT_UTF8) text = StringUtil::Utf8ToWide((char *)Text);
+ else text = StringUtil::AnsiToWide((char *)Text);*/
+
+ if (maxLength >= 0 && textStr.size() > (uint32)maxLength) {
+ textStr = Common::String(textStr.c_str(), (uint32)maxLength);
+ }
+ //text = text.substr(0, MaxLength); // TODO: Remove
+
+ BaseRenderer *renderer = _gameRef->_renderer;
+
+ // find cached surface, if exists
+ int minPriority = INT_MAX;
+ int minIndex = -1;
+ BaseSurface *surface = NULL;
+ int textOffset = 0;
+
+ for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
+ if (_cachedTexts[i] == NULL) {
+ minPriority = 0;
+ minIndex = i;
+ } else {
+ if (_cachedTexts[i]->_text == textStr && _cachedTexts[i]->_align == align && _cachedTexts[i]->_width == width && _cachedTexts[i]->_maxHeight == maxHeight && _cachedTexts[i]->_maxLength == maxLength) {
+ surface = _cachedTexts[i]->_surface;
+ textOffset = _cachedTexts[i]->_textOffset;
+ _cachedTexts[i]->_priority++;
+ _cachedTexts[i]->_marked = true;
+ break;
+ } else {
+ if (_cachedTexts[i]->_priority < minPriority) {
+ minPriority = _cachedTexts[i]->_priority;
+ minIndex = i;
+ }
+ }
+ }
+ }
+
+ // not found, create one
+ if (!surface) {
+ debugC(kWintermuteDebugFont, "Draw text: %s", text);
+ surface = renderTextToTexture(textStr, width, align, maxHeight, textOffset);
+ if (surface) {
+ // write surface to cache
+ if (_cachedTexts[minIndex] != NULL) {
+ delete _cachedTexts[minIndex];
+ }
+ _cachedTexts[minIndex] = new BaseCachedTTFontText;
+
+ _cachedTexts[minIndex]->_surface = surface;
+ _cachedTexts[minIndex]->_align = align;
+ _cachedTexts[minIndex]->_width = width;
+ _cachedTexts[minIndex]->_maxHeight = maxHeight;
+ _cachedTexts[minIndex]->_maxLength = maxLength;
+ _cachedTexts[minIndex]->_priority = 1;
+ _cachedTexts[minIndex]->_text = textStr;
+ _cachedTexts[minIndex]->_textOffset = textOffset;
+ _cachedTexts[minIndex]->_marked = true;
+ }
+ }
+
+
+ // and paint it
+ if (surface) {
+ Rect32 rc;
+ BasePlatform::setRect(&rc, 0, 0, surface->getWidth(), surface->getHeight());
+ for (uint32 i = 0; i < _layers.size(); i++) {
+ uint32 color = _layers[i]->_color;
+ uint32 origForceAlpha = renderer->_forceAlphaColor;
+ if (renderer->_forceAlphaColor != 0) {
+ color = BYTETORGBA(RGBCOLGetR(color), RGBCOLGetG(color), RGBCOLGetB(color), RGBCOLGetA(renderer->_forceAlphaColor));
+ renderer->_forceAlphaColor = 0;
+ }
+ surface->displayTransOffset(x, y - textOffset, rc, color, BLEND_NORMAL, false, false, _layers[i]->_offsetX, _layers[i]->_offsetY);
+
+ renderer->_forceAlphaColor = origForceAlpha;
+ }
+ }
+
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseSurface *BaseFontTT::renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset) {
+ //TextLineList lines;
+ // TODO: Use WideString-conversion here.
+ //WrapText(text, width, maxHeight, lines);
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text, width, lines);
+
+ while (maxHeight > 0 && lines.size() * _lineHeight > maxHeight) {
+ lines.pop_back();
+ }
+ if (lines.size() == 0) {
+ return NULL;
+ }
+
+ Graphics::TextAlign alignment = Graphics::kTextAlignInvalid;
+ if (align == TAL_LEFT) {
+ alignment = Graphics::kTextAlignLeft;
+ } else if (align == TAL_CENTER) {
+ alignment = Graphics::kTextAlignCenter;
+ } else if (align == TAL_RIGHT) {
+ alignment = Graphics::kTextAlignRight;
+ }
+
+ debugC(kWintermuteDebugFont, "%s %d %d %d %d", text.c_str(), RGBCOLGetR(_layers[0]->_color), RGBCOLGetG(_layers[0]->_color), RGBCOLGetB(_layers[0]->_color), RGBCOLGetA(_layers[0]->_color));
+// void drawString(Surface *dst, const Common::String &str, int x, int y, int w, uint32 color, TextAlign align = kTextAlignLeft, int deltax = 0, bool useEllipsis = true) const;
+ Graphics::Surface *surface = new Graphics::Surface();
+ if (_deletableFont) { // We actually have a TTF
+ surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ } else { // We are using a fallback, they can't do 32bpp
+ surface->create((uint16)width, (uint16)(_lineHeight * lines.size()), Graphics::PixelFormat(2, 5, 5, 5, 1, 11, 6, 1, 0));
+ }
+ uint32 useColor = 0xffffffff;
+ Common::Array<Common::String>::iterator it;
+ int heightOffset = 0;
+ for (it = lines.begin(); it != lines.end(); ++it) {
+ _font->drawString(surface, *it, 0, heightOffset, width, useColor, alignment);
+ heightOffset += (int)_lineHeight;
+ }
+
+ BaseSurface *retSurface = _gameRef->_renderer->createSurface();
+ Graphics::Surface *convertedSurface = surface->convertTo(Graphics::PixelFormat(4, 8, 8, 8, 8, 16, 8, 0, 24));
+ retSurface->putSurface(*convertedSurface, true);
+ convertedSurface->free();
+ surface->free();
+ delete surface;
+ delete convertedSurface;
+ return retSurface;
+ // TODO: _isUnderline, _isBold, _isItalic, _isStriked
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int BaseFontTT::getLetterHeight() {
+ return (int)getLineHeight();
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseFontTT::loadFile(const Common::String &filename) {
+ byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename);
+ if (buffer == NULL) {
+ _gameRef->LOG(0, "BaseFontTT::LoadFile failed for file '%s'", filename.c_str());
+ return STATUS_FAILED;
+ }
+
+ bool ret;
+
+ setFilename(filename.c_str());
+
+ if (DID_FAIL(ret = loadBuffer(buffer))) {
+ _gameRef->LOG(0, "Error parsing TTFONT file '%s'", filename.c_str());
+ }
+
+ delete[] buffer;
+
+ return ret;
+}
+
+
+TOKEN_DEF_START
+TOKEN_DEF(TTFONT)
+TOKEN_DEF(SIZE)
+TOKEN_DEF(FACE)
+TOKEN_DEF(FILENAME)
+TOKEN_DEF(BOLD)
+TOKEN_DEF(ITALIC)
+TOKEN_DEF(UNDERLINE)
+TOKEN_DEF(STRIKE)
+TOKEN_DEF(CHARSET)
+TOKEN_DEF(COLOR)
+TOKEN_DEF(ALPHA)
+TOKEN_DEF(LAYER)
+TOKEN_DEF(OFFSET_X)
+TOKEN_DEF(OFFSET_Y)
+TOKEN_DEF_END
+//////////////////////////////////////////////////////////////////////
+bool BaseFontTT::loadBuffer(byte *buffer) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(TTFONT)
+ TOKEN_TABLE(SIZE)
+ TOKEN_TABLE(FACE)
+ TOKEN_TABLE(FILENAME)
+ TOKEN_TABLE(BOLD)
+ TOKEN_TABLE(ITALIC)
+ TOKEN_TABLE(UNDERLINE)
+ TOKEN_TABLE(STRIKE)
+ TOKEN_TABLE(CHARSET)
+ TOKEN_TABLE(COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE(LAYER)
+ TOKEN_TABLE_END
+
+ char *params;
+ int cmd;
+ BaseParser parser;
+
+ if (parser.getCommand((char **)&buffer, commands, (char **)&params) != TOKEN_TTFONT) {
+ _gameRef->LOG(0, "'TTFONT' keyword expected.");
+ return STATUS_FAILED;
+ }
+ buffer = (byte *)params;
+
+ uint32 baseColor = 0x00000000;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_SIZE:
+ parser.scanStr(params, "%d", &_fontHeight);
+ break;
+
+ case TOKEN_FACE:
+ // we don't need this anymore
+ break;
+
+ case TOKEN_FILENAME:
+ BaseUtils::setString(&_fontFile, params);
+ break;
+
+ case TOKEN_BOLD:
+ parser.scanStr(params, "%b", &_isBold);
+ break;
+
+ case TOKEN_ITALIC:
+ parser.scanStr(params, "%b", &_isItalic);
+ break;
+
+ case TOKEN_UNDERLINE:
+ parser.scanStr(params, "%b", &_isUnderline);
+ break;
+
+ case TOKEN_STRIKE:
+ parser.scanStr(params, "%b", &_isStriked);
+ break;
+
+ case TOKEN_CHARSET:
+ // we don't need this anymore
+ break;
+
+ case TOKEN_COLOR: {
+ int r, g, b;
+ parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
+ baseColor = BYTETORGBA(r, g, b, RGBCOLGetA(baseColor));
+ }
+ break;
+
+ case TOKEN_ALPHA: {
+ int a;
+ parser.scanStr(params, "%d", &a);
+ baseColor = BYTETORGBA(RGBCOLGetR(baseColor), RGBCOLGetG(baseColor), RGBCOLGetB(baseColor), a);
+ }
+ break;
+
+ case TOKEN_LAYER: {
+ BaseTTFontLayer *layer = new BaseTTFontLayer;
+ if (layer && DID_SUCCEED(parseLayer(layer, (byte *)params))) {
+ _layers.add(layer);
+ } else {
+ delete layer;
+ layer = NULL;
+ cmd = PARSERR_TOKENNOTFOUND;
+ }
+ }
+ break;
+
+ }
+ }
+ if (cmd == PARSERR_TOKENNOTFOUND) {
+ _gameRef->LOG(0, "Syntax error in TTFONT definition");
+ return STATUS_FAILED;
+ }
+
+ // create at least one layer
+ if (_layers.size() == 0) {
+ BaseTTFontLayer *layer = new BaseTTFontLayer;
+ layer->_color = baseColor;
+ _layers.add(layer);
+ }
+
+ if (!_fontFile) {
+ BaseUtils::setString(&_fontFile, "arial.ttf");
+ }
+
+ return initFont();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontTT::parseLayer(BaseTTFontLayer *layer, byte *buffer) {
+ TOKEN_TABLE_START(commands)
+ TOKEN_TABLE(OFFSET_X)
+ TOKEN_TABLE(OFFSET_Y)
+ TOKEN_TABLE(COLOR)
+ TOKEN_TABLE(ALPHA)
+ TOKEN_TABLE_END
+
+ char *params;
+ int cmd;
+ BaseParser parser;
+
+ while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)&params)) > 0) {
+ switch (cmd) {
+ case TOKEN_OFFSET_X:
+ parser.scanStr(params, "%d", &layer->_offsetX);
+ break;
+
+ case TOKEN_OFFSET_Y:
+ parser.scanStr(params, "%d", &layer->_offsetY);
+ break;
+
+ case TOKEN_COLOR: {
+ int r, g, b;
+ parser.scanStr(params, "%d,%d,%d", &r, &g, &b);
+ layer->_color = BYTETORGBA(r, g, b, RGBCOLGetA(layer->_color));
+ }
+ break;
+
+ case TOKEN_ALPHA: {
+ int a;
+ parser.scanStr(params, "%d", &a);
+ layer->_color = BYTETORGBA(RGBCOLGetR(layer->_color), RGBCOLGetG(layer->_color), RGBCOLGetB(layer->_color), a);
+ }
+ break;
+ }
+ }
+ if (cmd != PARSERR_EOF) {
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontTT::persist(BasePersistenceManager *persistMgr) {
+ BaseFont::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_isBold));
+ persistMgr->transfer(TMEMBER(_isItalic));
+ persistMgr->transfer(TMEMBER(_isUnderline));
+ persistMgr->transfer(TMEMBER(_isStriked));
+ persistMgr->transfer(TMEMBER(_fontHeight));
+ persistMgr->transfer(TMEMBER(_fontFile));
+
+
+ // persist layers
+ int numLayers;
+ if (persistMgr->getIsSaving()) {
+ numLayers = _layers.size();
+ persistMgr->transfer(TMEMBER(numLayers));
+ for (int i = 0; i < numLayers; i++) {
+ _layers[i]->persist(persistMgr);
+ }
+ } else {
+ numLayers = _layers.size();
+ persistMgr->transfer(TMEMBER(numLayers));
+ for (int i = 0; i < numLayers; i++) {
+ BaseTTFontLayer *layer = new BaseTTFontLayer;
+ layer->persist(persistMgr);
+ _layers.add(layer);
+ }
+ }
+
+ if (!persistMgr->getIsSaving()) {
+ for (int i = 0; i < NUM_CACHED_TEXTS; i++) {
+ _cachedTexts[i] = NULL;
+ }
+ _fallbackFont = _font = _deletableFont = NULL;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseFontTT::afterLoad() {
+ initFont();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseFontTT::initFont() {
+ if (!_fontFile) {
+ return STATUS_FAILED;
+ }
+
+ Common::SeekableReadStream *file = BaseFileManager::getEngineInstance()->openFile(_fontFile);
+ if (!file) {
+ //TODO: Try to fallback from Arial to FreeSans
+ /*
+ // the requested font file is not in wme file space; try loading a system font
+ AnsiString fontFileName = PathUtil::combine(BasePlatform::getSystemFontPath(), PathUtil::getFileName(_fontFile));
+ file = BaseFileManager::getEngineInstance()->openFile(fontFileName.c_str(), false);
+ if (!file) {
+ _gameRef->LOG(0, "Error loading TrueType font '%s'", _fontFile);
+ //return STATUS_FAILED;
+ }*/
+ }
+
+ if (file) {
+#ifdef USE_FREETYPE2
+ _deletableFont = Graphics::loadTTFFont(*file, 96, _fontHeight); // Use the same dpi as WME (96 vs 72).
+ _font = _deletableFont;
+#endif
+ }
+ if (!_font) {
+ _font = _fallbackFont = FontMan.getFontByUsage(Graphics::FontManager::kBigGUIFont);
+ warning("BaseFontTT::InitFont - Couldn't load font: %s", _fontFile);
+ }
+ _lineHeight = _font->getFontHeight();
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseFontTT::measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight) {
+ //TextLineList lines;
+
+ if (maxWidth >= 0) {
+ Common::Array<Common::String> lines;
+ _font->wordWrapText(text, maxWidth, lines);
+ Common::Array<Common::String>::iterator it;
+ textWidth = 0;
+ for (it = lines.begin(); it != lines.end(); ++it) {
+ textWidth = MAX(textWidth, _font->getStringWidth(*it));
+ }
+
+ //WrapText(text, maxWidth, maxHeight, lines);
+
+ textHeight = (int)(lines.size() * getLineHeight());
+ } else {
+ textWidth = _font->getStringWidth(text);
+ textHeight = _fontHeight;
+ }
+ /*
+ TextLineList::iterator it;
+ for (it = lines.begin(); it != lines.end(); ++it) {
+ TextLine *line = (*it);
+ textWidth = MAX(textWidth, line->GetWidth());
+ delete line;
+ line = NULL;
+ }*/
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/font/base_font_truetype.h b/engines/wintermute/base/font/base_font_truetype.h
new file mode 100644
index 0000000000..02dca7439f
--- /dev/null
+++ b/engines/wintermute/base/font/base_font_truetype.h
@@ -0,0 +1,152 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_FONTTT_H
+#define WINTERMUTE_BASE_FONTTT_H
+
+#include "engines/wintermute/base/font/base_font_storage.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "graphics/font.h"
+
+#define NUM_CACHED_TEXTS 30
+
+namespace Wintermute {
+
+class BaseFontTT : public BaseFont {
+private:
+ //////////////////////////////////////////////////////////////////////////
+ class BaseCachedTTFontText {
+ public:
+ WideString _text;
+ int _width;
+ TTextAlign _align;
+ int _maxHeight;
+ int _maxLength;
+ BaseSurface *_surface;
+ int _priority;
+ int _textOffset;
+ bool _marked;
+
+ BaseCachedTTFontText() {
+ //_text = L"";
+ _text = "";
+ _width = _maxHeight = _maxLength = -1;
+ _align = TAL_LEFT;
+ _surface = NULL;
+ _priority = -1;
+ _textOffset = 0;
+ _marked = false;
+ }
+
+ virtual ~BaseCachedTTFontText() {
+ if (_surface) {
+ delete _surface;
+ }
+ }
+ };
+
+public:
+ //////////////////////////////////////////////////////////////////////////
+ class BaseTTFontLayer {
+ public:
+ BaseTTFontLayer() {
+ _offsetX = _offsetY = 0;
+ _color = 0x00000000;
+ }
+
+ bool persist(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_offsetX));
+ persistMgr->transfer(TMEMBER(_offsetY));
+ persistMgr->transfer(TMEMBER(_color));
+ return STATUS_OK;
+ }
+
+ int _offsetX;
+ int _offsetY;
+ uint32 _color;
+ };
+
+public:
+ DECLARE_PERSISTENT(BaseFontTT, BaseFont)
+ BaseFontTT(BaseGame *inGame);
+ virtual ~BaseFontTT(void);
+
+ virtual int getTextWidth(byte *text, int maxLength = -1);
+ virtual int getTextHeight(byte *text, int width);
+ virtual void drawText(const byte *text, int x, int y, int width, TTextAlign align = TAL_LEFT, int max_height = -1, int maxLength = -1);
+ virtual int getLetterHeight();
+
+ bool loadBuffer(byte *buffer);
+ bool loadFile(const Common::String &filename);
+
+ float getLineHeight() const {
+ return _lineHeight;
+ }
+
+ void afterLoad();
+ void initLoop();
+
+private:
+ bool parseLayer(BaseTTFontLayer *layer, byte *buffer);
+
+ void measureText(const WideString &text, int maxWidth, int maxHeight, int &textWidth, int &textHeight);
+
+ BaseSurface *renderTextToTexture(const WideString &text, int width, TTextAlign align, int maxHeight, int &textOffset);
+
+ BaseCachedTTFontText *_cachedTexts[NUM_CACHED_TEXTS];
+
+ bool initFont();
+
+ Graphics::Font *_deletableFont;
+ const Graphics::Font *_font;
+ const Graphics::Font *_fallbackFont;
+
+ float _lineHeight;
+
+ size_t _maxCharWidth;
+ size_t _maxCharHeight;
+
+public:
+ bool _isBold;
+ bool _isItalic;
+ bool _isUnderline;
+ bool _isStriked;
+ int _fontHeight;
+ char *_fontFile;
+
+ BaseArray<BaseTTFontLayer *> _layers;
+ void clearCache();
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/base_image.cpp b/engines/wintermute/base/gfx/base_image.cpp
new file mode 100644
index 0000000000..4b15d563ed
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_image.cpp
@@ -0,0 +1,231 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/decoders/png.h"
+#include "graphics/decoders/jpeg.h"
+#include "graphics/decoders/bmp.h"
+#include "graphics/decoders/tga.h"
+#include "graphics/surface.h"
+#include "common/textconsole.h"
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+BaseImage::BaseImage() {
+ _fileManager = BaseFileManager::getEngineInstance();
+ _palette = NULL;
+ _surface = NULL;
+ _decoder = NULL;
+ _deletableSurface = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseImage::~BaseImage() {
+ delete _decoder;
+ if (_deletableSurface) {
+ _deletableSurface->free();
+ }
+ delete _deletableSurface;
+}
+
+bool BaseImage::loadFile(const Common::String &filename) {
+ _filename = filename;
+ _filename.toLowercase();
+ if (filename.hasPrefix("savegame:")) {
+ _decoder = new Graphics::BitmapDecoder();
+ } else if (_filename.hasSuffix(".png")) {
+ _decoder = new Graphics::PNGDecoder();
+ } else if (_filename.hasSuffix(".bmp")) {
+ _decoder = new Graphics::BitmapDecoder();
+ } else if (_filename.hasSuffix(".tga")) {
+ _decoder = new Graphics::TGADecoder();
+ } else if (_filename.hasSuffix(".jpg")) {
+ _decoder = new Graphics::JPEGDecoder();
+ } else {
+ error("BaseImage::loadFile : Unsupported fileformat %s", filename.c_str());
+ }
+ _filename = filename;
+ Common::SeekableReadStream *file = _fileManager->openFile(filename.c_str());
+ if (!file) {
+ return false;
+ }
+
+ _decoder->loadStream(*file);
+ _surface = _decoder->getSurface();
+ _palette = _decoder->getPalette();
+ _fileManager->closeFile(file);
+
+ return true;
+}
+
+byte BaseImage::getAlphaAt(int x, int y) const {
+ if (!_surface) {
+ return 0xFF;
+ }
+ uint32 color = *(const uint32 *)_surface->getBasePtr(x, y);
+ byte r, g, b, a;
+ _surface->format.colorToARGB(color, a, r, g, b);
+ return a;
+}
+
+void BaseImage::copyFrom(const Graphics::Surface *surface) {
+ _surface = _deletableSurface = new Graphics::Surface();
+ _deletableSurface->copyFrom(*surface);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseImage::saveBMPFile(const char *filename) const {
+ warning("BaseImage::saveBMPFile - stubbed"); // TODO
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseImage::resize(int newWidth, int newHeight) {
+ // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
+ TransparentSurface temp(*_surface, true);
+ if (_deletableSurface) {
+ _deletableSurface->free();
+ delete _deletableSurface;
+ _deletableSurface = NULL;
+ }
+ _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
+ temp.free();
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseImage::writeBMPToStream(Common::WriteStream *stream) const {
+ if (!_surface) {
+ return false;
+ }
+
+ /* The following is just copied over and inverted to write-ops from the BMP-decoder */
+ stream->writeByte('B');
+ stream->writeByte('M');
+
+ /* Since we don't care during reads, we don't care during writes: */
+ /* uint32 fileSize = */
+ stream->writeUint32LE(54 + _surface->h * _surface->pitch);
+ /* uint16 res1 = */
+ stream->writeUint16LE(0);
+ /* uint16 res2 = */
+ stream->writeUint16LE(0);
+ const uint32 imageOffset = 54;
+ stream->writeUint32LE(imageOffset);
+
+ const uint32 infoSize = 40; /* Windows v3 BMP */
+ stream->writeUint32LE(infoSize);
+
+ uint32 width = _surface->w;
+ int32 height = _surface->h;
+ stream->writeUint32LE(width);
+ stream->writeUint32LE((uint32)height);
+
+ if (width == 0 || height == 0) {
+ return false;
+ }
+
+ if (height < 0) {
+ warning("Right-side up bitmaps not supported");
+ return false;
+ }
+
+ /* uint16 planes = */ stream->writeUint16LE(1);
+ const uint16 bitsPerPixel = 24;
+ stream->writeUint16LE(bitsPerPixel);
+
+ const uint32 compression = 0;
+ stream->writeUint32LE(compression);
+
+ /* uint32 imageSize = */
+ stream->writeUint32LE(_surface->h * _surface->pitch);
+ /* uint32 pixelsPerMeterX = */
+ stream->writeUint32LE(0);
+ /* uint32 pixelsPerMeterY = */
+ stream->writeUint32LE(0);
+ const uint32 paletteColorCount = 0;
+ stream->writeUint32LE(paletteColorCount);
+ /* uint32 colorsImportant = */
+ stream->writeUint32LE(0);
+
+ // Start us at the beginning of the image (54 bytes in)
+ Graphics::PixelFormat format = Graphics::PixelFormat::createFormatCLUT8();
+
+ // BGRA for 24bpp
+ if (bitsPerPixel == 24) {
+ format = Graphics::PixelFormat(4, 8, 8, 8, 8, 8, 16, 24, 0);
+ }
+
+ Graphics::Surface *surface = _surface->convertTo(format);
+
+ int srcPitch = width * (bitsPerPixel >> 3);
+ const int extraDataLength = (srcPitch % 4) ? 4 - (srcPitch % 4) : 0;
+
+ for (int32 i = height - 1; i >= 0; i--) {
+ for (uint32 j = 0; j < width; j++) {
+ byte b, g, r;
+ uint32 color = *(uint32 *)surface->getBasePtr(j, i);
+ surface->format.colorToRGB(color, r, g, b);
+ stream->writeByte(b);
+ stream->writeByte(g);
+ stream->writeByte(r);
+ }
+
+ for (int k = 0; k < extraDataLength; k++) {
+ stream->writeByte(0);
+ }
+ }
+ surface->free();
+ delete surface;
+ return true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseImage::copyFrom(BaseImage *origImage, int newWidth, int newHeight) {
+ // WME Lite used FILTER_BILINEAR with FreeImage_Rescale here.
+
+ TransparentSurface temp(*origImage->_surface, false);
+ if (_deletableSurface) {
+ _deletableSurface->free();
+ delete _deletableSurface;
+ _deletableSurface = NULL;
+ }
+ _surface = _deletableSurface = temp.scale((uint16)newWidth, (uint16)newHeight);
+ return true;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_image.h b/engines/wintermute/base/gfx/base_image.h
new file mode 100644
index 0000000000..6d01b84184
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_image.h
@@ -0,0 +1,72 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_IMAGE_H
+#define WINTERMUTE_BASE_IMAGE_H
+
+#include "graphics/surface.h"
+#include "graphics/pixelformat.h"
+#include "graphics/decoders/image_decoder.h"
+#include "common/endian.h"
+#include "common/str.h"
+#include "common/stream.h"
+
+namespace Wintermute {
+class BaseSurface;
+class BaseFileManager;
+class BaseImage {
+
+public:
+ BaseImage();
+ ~BaseImage();
+
+ bool loadFile(const Common::String &filename);
+ const Graphics::Surface *getSurface() const {
+ return _surface;
+ };
+ const byte *getPalette() const {
+ return _palette;
+ }
+ byte getAlphaAt(int x, int y) const;
+ bool writeBMPToStream(Common::WriteStream *stream) const;
+ bool resize(int newWidth, int newHeight);
+ bool saveBMPFile(const char *filename) const;
+ bool copyFrom(BaseImage *origImage, int newWidth = 0, int newHeight = 0);
+ void copyFrom(const Graphics::Surface *surface);
+private:
+ Common::String _filename;
+ Graphics::ImageDecoder *_decoder;
+ const Graphics::Surface *_surface;
+ Graphics::Surface *_deletableSurface;
+ const byte *_palette;
+ BaseFileManager *_fileManager;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/base_renderer.cpp b/engines/wintermute/base/gfx/base_renderer.cpp
new file mode 100644
index 0000000000..9205438a5b
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_renderer.cpp
@@ -0,0 +1,381 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_active_rect.h"
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+BaseRenderer::BaseRenderer(BaseGame *inGame) : BaseClass(inGame) {
+ _window = 0;
+ _clipperWindow = 0;
+ _active = false;
+ _ready = false;
+ _windowed = true;
+ _forceAlphaColor = 0x00;
+
+ _indicatorDisplay = false;
+ _indicatorColor = BYTETORGBA(255, 0, 0, 128);
+ _indicatorProgress = 0;
+ _indicatorX = -1;
+ _indicatorY = -1;
+ _indicatorWidth = -1;
+ _indicatorHeight = 8;
+ _indicatorWidthDrawn = 0;
+
+ _loadImageName = "";
+ _saveImageName = "";
+ _saveLoadImage = NULL;
+ _loadInProgress = false;
+ _hasDrawnSaveLoadImage = false;
+
+ _saveImageX = _saveImageY = 0;
+ _loadImageX = _loadImageY = 0;
+
+ _width = _height = _bPP = 0;
+ BasePlatform::setRectEmpty(&_monitorRect);
+
+ _realWidth = _realHeight = 0;
+ _drawOffsetX = _drawOffsetY = 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseRenderer::~BaseRenderer() {
+ deleteRectList();
+ unclipCursor();
+ delete _saveLoadImage;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseRenderer::initLoop() {
+ deleteRectList();
+}
+
+void BaseRenderer::initIndicator() {
+ if (_indicatorY == -1) {
+ _indicatorY = _height - _indicatorHeight;
+ }
+ if (_indicatorX == -1) {
+ _indicatorX = 0;
+ }
+ if (_indicatorWidth == -1) {
+ _indicatorWidth = _width;
+ }
+}
+
+void BaseRenderer::setIndicator(int width, int height, int x, int y, uint32 color) {
+ _indicatorWidth = width;
+ _indicatorHeight = height;
+ _indicatorX = x;
+ _indicatorY = y;
+ _indicatorColor = color;
+}
+
+void BaseRenderer::setIndicatorVal(int value) {
+ bool redisplay = (_indicatorProgress != value);
+ _indicatorProgress = value;
+ if (redisplay)
+ displayIndicator();
+}
+
+void BaseRenderer::setLoadingScreen(const char *filename, int x, int y) {
+ // TODO: Handle NULL
+ _loadImageName = filename;
+ _loadImageX = x;
+ _loadImageY = y;
+}
+
+void BaseRenderer::setSaveImage(const char *filename, int x, int y) {
+ // TODO: Handle NULL
+ _saveImageName = filename;
+ _saveImageX = x;
+ _saveImageY = y;
+}
+
+void BaseRenderer::initSaveLoad(bool isSaving, bool quickSave) {
+ _indicatorDisplay = true;
+ _indicatorProgress = 0;
+ _hasDrawnSaveLoadImage = false;
+
+ if (isSaving && !quickSave) {
+ delete _saveLoadImage;
+ _saveLoadImage = NULL;
+ if (_saveImageName.size()) {
+ _saveLoadImage = createSurface();
+
+ if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_saveImageName, true, 0, 0, 0))) {
+ delete _saveLoadImage;
+ _saveLoadImage = NULL;
+ }
+ }
+ } else {
+ delete _saveLoadImage;
+ _saveLoadImage = NULL;
+ if (_loadImageName.size()) {
+ _saveLoadImage = createSurface();
+
+ if (!_saveLoadImage || DID_FAIL(_saveLoadImage->create(_loadImageName, true, 0, 0, 0))) {
+ delete _saveLoadImage;
+ _saveLoadImage = NULL;
+ }
+ }
+ _loadInProgress = true;
+ }
+}
+
+void BaseRenderer::endSaveLoad() {
+ _loadInProgress = false;
+ _indicatorDisplay = false;
+ _indicatorWidthDrawn = 0;
+
+ delete _saveLoadImage;
+ _saveLoadImage = NULL;
+}
+
+void BaseRenderer::persistSaveLoadImages(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_loadImageName));
+ persistMgr->transfer(TMEMBER(_saveImageName));
+ persistMgr->transfer(TMEMBER(_saveImageX));
+ persistMgr->transfer(TMEMBER(_saveImageY));
+ persistMgr->transfer(TMEMBER(_loadImageX));
+ persistMgr->transfer(TMEMBER(_loadImageY));
+}
+
+//////////////////////////////////////////////////////////////////////
+BaseObject *BaseRenderer::getObjectAt(int x, int y) {
+ Point32 point;
+ point.x = x;
+ point.y = y;
+
+ for (int i = _rectList.size() - 1; i >= 0; i--) {
+ if (BasePlatform::ptInRect(&_rectList[i]->_rect, point)) {
+ if (_rectList[i]->_precise) {
+ // frame
+ if (_rectList[i]->_frame) {
+ int xx = (int)((_rectList[i]->_frame->getRect().left + x - _rectList[i]->_rect.left + _rectList[i]->_offsetX) / (float)((float)_rectList[i]->_zoomX / (float)100));
+ int yy = (int)((_rectList[i]->_frame->getRect().top + y - _rectList[i]->_rect.top + _rectList[i]->_offsetY) / (float)((float)_rectList[i]->_zoomY / (float)100));
+
+ if (_rectList[i]->_frame->_mirrorX) {
+ int width = _rectList[i]->_frame->getRect().right - _rectList[i]->_frame->getRect().left;
+ xx = width - xx;
+ }
+
+ if (_rectList[i]->_frame->_mirrorY) {
+ int height = _rectList[i]->_frame->getRect().bottom - _rectList[i]->_frame->getRect().top;
+ yy = height - yy;
+ }
+
+ if (!_rectList[i]->_frame->_surface->isTransparentAt(xx, yy)) {
+ return _rectList[i]->_owner;
+ }
+ }
+ // region
+ else if (_rectList[i]->_region) {
+ if (_rectList[i]->_region->pointInRegion(x + _rectList[i]->_offsetX, y + _rectList[i]->_offsetY)) {
+ return _rectList[i]->_owner;
+ }
+ }
+ } else {
+ return _rectList[i]->_owner;
+ }
+ }
+ }
+
+ return (BaseObject *)NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderer::deleteRectList() {
+ for (uint32 i = 0; i < _rectList.size(); i++) {
+ delete _rectList[i];
+ }
+ _rectList.clear();
+}
+
+//////////////////////////////////////////////////////////////////////
+bool BaseRenderer::initRenderer(int width, int height, bool windowed) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void BaseRenderer::onWindowChange() {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::windowedBlt() {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::setup2D(bool Force) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::setupLines() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::drawRect(int x1, int y1, int x2, int y2, uint32 color, int width) {
+ for (int i = 0; i < width; i++) {
+ drawLine(x1 + i, y1 + i, x2 - i, y1 + i, color); // up
+ drawLine(x1 + i, y2 - i, x2 - i + 1, y2 - i, color); // down
+
+ drawLine(x1 + i, y1 + i, x1 + i, y2 - i, color); // left
+ drawLine(x2 - i, y1 + i, x2 - i, y2 - i + 1, color); // right
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::setViewport(int left, int top, int right, int bottom) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::setScreenViewport() {
+ return setViewport(_drawOffsetX, _drawOffsetY, _width + _drawOffsetX, _height + _drawOffsetY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::setViewport(Rect32 *rect) {
+ return setViewport(rect->left + _drawOffsetX,
+ rect->top + _drawOffsetY,
+ rect->right + _drawOffsetX,
+ rect->bottom + _drawOffsetY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::clipCursor() {
+ // TODO: Reimplement this. (Currently aspect-indpendence isn't quite finished)
+ /*
+ if (!_windowed) {
+ Rect32 rc;
+ GetWindowRect(_window, &rc);
+
+ // if "maintain aspect ratio" is in effect, lock mouse to visible area
+ rc.left = _drawOffsetX;
+ rc.top = _drawOffsetY;
+ rc.right = rc.left + _width;
+ rc.bottom = rc.top + _height;
+
+ ::ClipCursor(&rc);
+ }
+ */
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::unclipCursor() {
+ /*
+ if (!_windowed) ::ClipCursor(NULL);
+ */
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::pointInViewport(Point32 *p) {
+ if (p->x < _drawOffsetX) {
+ return false;
+ }
+ if (p->y < _drawOffsetY) {
+ return false;
+ }
+ if (p->x > _drawOffsetX + _width) {
+ return false;
+ }
+ if (p->y > _drawOffsetY + _height) {
+ return false;
+ }
+
+ return true;
+}
+
+void BaseRenderer::addRectToList(BaseActiveRect *rect) {
+ _rectList.push_back(rect);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderer::displayIndicator() {
+ if (!_indicatorDisplay || !_indicatorProgress) {
+ return STATUS_OK;
+ }
+ if (_saveLoadImage && !_hasDrawnSaveLoadImage) {
+ Rect32 rc;
+ BasePlatform::setRect(&rc, 0, 0, _saveLoadImage->getWidth(), _saveLoadImage->getHeight());
+ if (_loadInProgress) {
+ _saveLoadImage->displayTrans(_loadImageX, _loadImageY, rc);
+ } else {
+ _saveLoadImage->displayTrans(_saveImageX, _saveImageY, rc);
+ }
+ flip();
+ _hasDrawnSaveLoadImage = true;
+ }
+
+ if ((!_indicatorDisplay && _indicatorWidth <= 0) || _indicatorHeight <= 0) {
+ return STATUS_OK;
+ }
+ setupLines();
+ int curWidth = (int)(_indicatorWidth * (float)((float)_indicatorProgress / 100.0f));
+ for (int i = 0; i < _indicatorHeight; i++) {
+ drawLine(_indicatorX, _indicatorY + i, _indicatorX + curWidth, _indicatorY + i, _indicatorColor);
+ }
+
+ setup2D();
+ _indicatorWidthDrawn = curWidth;
+ if (_indicatorWidthDrawn) {
+ indicatorFlip();
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_renderer.h b/engines/wintermute/base/gfx/base_renderer.h
new file mode 100644
index 0000000000..0475824464
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_renderer.h
@@ -0,0 +1,221 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_RENDERER_H
+#define WINTERMUTE_BASE_RENDERER_H
+
+#include "engines/wintermute/math/rect32.h"
+#include "engines/wintermute/base/base.h"
+#include "common/rect.h"
+#include "common/array.h"
+
+namespace Wintermute {
+
+class BaseImage;
+class BaseActiveRect;
+class BaseObject;
+class BaseSurface;
+class BasePersistenceManager;
+
+/**
+ * @class BaseRenderer a common interface for the rendering portion of WME
+ * this interface is mainly intended to wrap away any differencies between
+ * software-rendering/hardware-rendering.
+ */
+class BaseRenderer: public BaseClass {
+public:
+ int _realWidth;
+ int _realHeight;
+ int _drawOffsetX;
+ int _drawOffsetY;
+
+ virtual void dumpData(const char *filename) {}
+ /**
+ * Take a screenshot of the current screenstate
+ *
+ * @return a BaseImage containing the current screen-buffer.
+ */
+ virtual BaseImage *takeScreenshot() = 0;
+ virtual bool setViewport(int left, int top, int right, int bottom);
+ virtual bool setViewport(Rect32 *rect);
+ virtual Rect32 getViewPort() = 0;
+ virtual bool setScreenViewport();
+
+ virtual Graphics::PixelFormat getPixelFormat() const = 0;
+ /**
+ * Fade the screen to black
+ *
+ * @param alpha amount to fade by (alpha value of black)
+ * @return
+ */
+ virtual void fade(uint16 alpha) = 0;
+ /**
+ * Fade a portion of the screen to a specific color
+ *
+ * @param r the red component to fade too.
+ * @param g the green component to fade too.
+ * @param b the blue component to fade too.
+ * @param a the alpha component to fade too.
+ * @param rect the portion of the screen to fade (if NULL, the entire screen will be faded).
+ */
+ virtual void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL) = 0;
+ virtual bool drawLine(int x1, int y1, int x2, int y2, uint32 color);
+ virtual bool drawRect(int x1, int y1, int x2, int y2, uint32 color, int width = 1);
+ BaseRenderer(BaseGame *inGame = NULL);
+ virtual ~BaseRenderer();
+ virtual bool setProjection() {
+ return STATUS_OK;
+ };
+
+ virtual bool windowedBlt();
+ /**
+ * Fill a portion of the screen with a specified color
+ *
+ * @param r the red component to fill with.
+ * @param g the green component to fill with.
+ * @param b the blue component to fill with.
+ */
+ virtual bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL) = 0;
+ virtual void onWindowChange();
+ virtual bool initRenderer(int width, int height, bool windowed);
+ /**
+ * Flip the backbuffer onto the screen-buffer
+ * The screen will NOT be updated before calling this function.
+ *
+ * @return true if successfull, false on error.
+ */
+ virtual bool flip() = 0;
+ /**
+ * Special flip for the indicator drawn during save/load
+ * essentially, just copies the region defined by the _indicator-variables.
+ */
+ virtual bool indicatorFlip() = 0;
+ virtual void initLoop();
+ virtual bool setup2D(bool force = false);
+ virtual bool setupLines();
+
+ /**
+ * Get the name of the current renderer
+ *
+ * @return the name of the renderer.
+ */
+ virtual Common::String getName() const = 0;
+ virtual bool displayDebugInfo() {
+ return STATUS_FAILED;
+ };
+ virtual bool drawShaderQuad() {
+ return STATUS_FAILED;
+ }
+
+ virtual float getScaleRatioX() const {
+ return 1.0f;
+ }
+ virtual float getScaleRatioY() const {
+ return 1.0f;
+ }
+
+ /**
+ * Create a Surface fit for use with the renderer.
+ * As diverse implementations of BaseRenderer might have different solutions for storing surfaces
+ * this allows for a common interface for creating surface-handles. (Mostly usefull to ease future
+ * implementation of hw-accelerated rendering, or readding 3D-support at some point).
+ *
+ * @return a surface that can be used with this renderer
+ */
+ virtual BaseSurface *createSurface() = 0;
+
+ bool clipCursor();
+ bool unclipCursor();
+
+ BaseObject *getObjectAt(int x, int y);
+ void deleteRectList();
+
+ virtual bool startSpriteBatch() {
+ return STATUS_OK;
+ };
+ virtual bool endSpriteBatch() {
+ return STATUS_OK;
+ };
+ bool pointInViewport(Point32 *P);
+ bool _active;
+ bool _ready;
+ bool _windowed;
+ int _bPP;
+ int _height;
+ int _width;
+ uint32 _window;
+ uint32 _forceAlphaColor;
+
+ void addRectToList(BaseActiveRect *rect);
+
+ // Indicator & Save/Load-related functions
+ void initIndicator();
+ void setIndicatorVal(int value);
+ void setIndicator(int width, int height, int x, int y, uint32 color);
+ void persistSaveLoadImages(BasePersistenceManager *persistMgr);
+ void initSaveLoad(bool isSaving, bool quickSave = false);
+ void endSaveLoad();
+ void setLoadingScreen(const char *filename, int x, int y);
+ void setSaveImage(const char *filename, int x, int y);
+
+ bool displayIndicator();
+protected:
+ Common::String _loadImageName;
+ Common::String _saveImageName;
+ int _saveImageX;
+ int _saveImageY;
+ int _loadImageX;
+ int _loadImageY;
+ BaseSurface *_saveLoadImage;
+ bool _hasDrawnSaveLoadImage;
+
+ int _indicatorWidthDrawn;
+ uint32 _indicatorColor;
+ int _indicatorX;
+ int _indicatorY;
+ int _indicatorWidth;
+ int _indicatorHeight;
+ bool _loadInProgress;
+ bool _indicatorDisplay;
+ int _indicatorProgress;
+protected:
+ uint32 _clipperWindow;
+
+ Rect32 _windowRect;
+ Rect32 _viewportRect;
+ Rect32 _screenRect;
+ Rect32 _monitorRect;
+private:
+ Common::Array<BaseActiveRect *> _rectList;
+};
+
+BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/base_surface.cpp b/engines/wintermute/base/gfx/base_surface.cpp
new file mode 100644
index 0000000000..d882adf5ad
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_surface.cpp
@@ -0,0 +1,149 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/wintypes.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+BaseSurface::BaseSurface(BaseGame *inGame) : BaseClass(inGame) {
+ _referenceCount = 0;
+
+ _width = _height = 0;
+
+ _filename = "";
+
+ _pixelOpReady = false;
+
+ _ckDefault = true;
+ _ckRed = _ckGreen = _ckBlue = 0;
+ _lifeTime = 0;
+ _keepLoaded = false;
+
+ _lastUsedTime = 0;
+ _valid = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+BaseSurface::~BaseSurface() {
+ if (_pixelOpReady) {
+ endPixelOp();
+ }
+}
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurface::restore() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurface::isTransparentAt(int x, int y) {
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurface::displayHalfTrans(int x, int y, Rect32 rect) {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return displayTransZoom(x, y, rect, zoomX, zoomY, alpha, blendMode, mirrorX, mirrorY);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::create(int width, int height) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::startPixelOp() {
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::endPixelOp() {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::putPixel(int x, int y, byte r, byte g, byte b, int a) {
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::comparePixel(int x, int y, byte r, byte g, byte b, int a) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+bool BaseSurface::isTransparentAtLite(int x, int y) {
+ return false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::invalidate() {
+ return STATUS_FAILED;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurface::prepareToDraw() {
+ _lastUsedTime = _gameRef->_liveTimer;
+
+ if (!_valid) {
+ //_gameRef->LOG(0, "Reviving: %s", _filename);
+ return create(_filename.c_str(), _ckDefault, _ckRed, _ckGreen, _ckBlue, _lifeTime, _keepLoaded);
+ } else {
+ return STATUS_OK;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSurface::setSize(int width, int height) {
+ _width = width;
+ _height = height;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/base_surface.h b/engines/wintermute/base/gfx/base_surface.h
new file mode 100644
index 0000000000..ee53c03e77
--- /dev/null
+++ b/engines/wintermute/base/gfx/base_surface.h
@@ -0,0 +1,99 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SURFACE_H
+#define WINTERMUTE_BASE_SURFACE_H
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/math/rect32.h"
+#include "graphics/surface.h"
+
+namespace Wintermute {
+
+class BaseSurface: public BaseClass {
+public:
+ virtual bool invalidate();
+ virtual bool prepareToDraw();
+ uint32 _lastUsedTime;
+ bool _valid;
+ int _lifeTime;
+
+ bool _pixelOpReady;
+ BaseSurface(BaseGame *inGame);
+ virtual ~BaseSurface();
+
+ virtual bool displayHalfTrans(int x, int y, Rect32 rect);
+ virtual bool isTransparentAt(int x, int y);
+ virtual bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0) = 0;
+ virtual bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false) = 0;
+ virtual bool restore();
+ virtual bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false) = 0;
+ virtual bool create(int width, int height);
+ virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false) {
+ return STATUS_FAILED;
+ }
+ virtual bool putPixel(int x, int y, byte r, byte g, byte b, int a = -1);
+ virtual bool getPixel(int x, int y, byte *r, byte *g, byte *b, byte *a = NULL);
+ virtual bool comparePixel(int x, int y, byte r, byte g, byte b, int a = -1);
+ virtual bool startPixelOp();
+ virtual bool endPixelOp();
+ virtual bool isTransparentAtLite(int x, int y);
+ void setSize(int width, int height);
+
+ int _referenceCount;
+
+ virtual int getWidth() {
+ return _width;
+ }
+ virtual int getHeight() {
+ return _height;
+ }
+ Common::String getFileNameStr() { return _filename; }
+ const char* getFileName() { return _filename.c_str(); }
+ //void SetWidth(int Width){ _width = Width; }
+ //void SetHeight(int Height){ _height = Height; }
+protected:
+ bool _ckDefault;
+ byte _ckRed;
+ byte _ckGreen;
+ byte _ckBlue;
+
+ bool _keepLoaded;
+ Common::String _filename;
+ int _height;
+ int _width;
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
new file mode 100644
index 0000000000..6d67253038
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp
@@ -0,0 +1,604 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h"
+#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
+#include "engines/wintermute/base/base_surface_storage.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/math/math_util.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "common/system.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
+#include "common/queue.h"
+#include "common/config-manager.h"
+
+namespace Wintermute {
+
+RenderTicket::RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) : _owner(owner),
+ _srcRect(*srcRect), _dstRect(*dstRect), _drawNum(0), _isValid(true), _wantsDraw(true), _hasAlpha(!disableAlpha) {
+ _colorMod = 0;
+ _mirror = TransparentSurface::FLIP_NONE;
+ if (mirrorX) {
+ _mirror |= TransparentSurface::FLIP_V;
+ }
+ if (mirrorY) {
+ _mirror |= TransparentSurface::FLIP_H;
+ }
+ if (surf) {
+ _surface = new Graphics::Surface();
+ _surface->create((uint16)srcRect->width(), (uint16)srcRect->height(), surf->format);
+ assert(_surface->format.bytesPerPixel == 4);
+ // Get a clipped copy of the surface
+ for (int i = 0; i < _surface->h; i++) {
+ memcpy(_surface->getBasePtr(0, i), surf->getBasePtr(srcRect->left, srcRect->top + i), srcRect->width() * _surface->format.bytesPerPixel);
+ }
+ // Then scale it if necessary
+ if (dstRect->width() != srcRect->width() || dstRect->height() != srcRect->height()) {
+ TransparentSurface src(*_surface, false);
+ Graphics::Surface *temp = src.scale(dstRect->width(), dstRect->height());
+ _surface->free();
+ delete _surface;
+ _surface = temp;
+ }
+ } else {
+ _surface = NULL;
+ }
+}
+
+RenderTicket::~RenderTicket() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ }
+}
+
+bool RenderTicket::operator==(RenderTicket &t) {
+ if ((t._srcRect != _srcRect) ||
+ (t._dstRect != _dstRect) ||
+ (t._mirror != _mirror) ||
+ (t._owner != _owner) ||
+ (t._hasAlpha != _hasAlpha) ||
+ (t._colorMod != _colorMod)) {
+ return false;
+ }
+ return true;
+}
+
+BaseRenderer *makeOSystemRenderer(BaseGame *inGame) {
+ return new BaseRenderOSystem(inGame);
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseRenderOSystem::BaseRenderOSystem(BaseGame *inGame) : BaseRenderer(inGame) {
+ _renderSurface = new Graphics::Surface();
+ _blankSurface = new Graphics::Surface();
+ _drawNum = 1;
+ _needsFlip = true;
+
+ _borderLeft = _borderRight = _borderTop = _borderBottom = 0;
+ _ratioX = _ratioY = 1.0f;
+ setAlphaMod(255);
+ setColorMod(255, 255, 255);
+ _dirtyRect = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseRenderOSystem::~BaseRenderOSystem() {
+ _renderSurface->free();
+ delete _renderSurface;
+ _blankSurface->free();
+ delete _blankSurface;
+ TransparentSurface::destroyLookup();
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderOSystem::initRenderer(int width, int height, bool windowed) {
+ _width = width;
+ _height = height;
+ _renderRect.setWidth(_width);
+ _renderRect.setHeight(_height);
+
+ _realWidth = width;
+ _realHeight = height;
+
+ //TODO: Tiny resolution-displays might want to do some resolution-selection logic here
+
+ //_realWidth = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResWidth", _width);
+ //_realHeight = BaseEngine::instance().getRegistry()->readInt("Debug", "ForceResHeight", _height);
+
+ float origAspect = (float)_width / (float)_height;
+ float realAspect = (float)_realWidth / (float)_realHeight;
+
+ float ratio;
+ if (origAspect < realAspect) {
+ // normal to wide
+ ratio = (float)_realHeight / (float)_height;
+ } else {
+ // wide to normal
+ ratio = (float)_realWidth / (float)_width;
+ }
+
+ _borderLeft = (int)((_realWidth - (_width * ratio)) / 2);
+ _borderRight = (int)(_realWidth - (_width * ratio) - _borderLeft);
+
+ _borderTop = (int)((_realHeight - (_height * ratio)) / 2);
+ _borderBottom = (int)(_realHeight - (_height * ratio) - _borderTop);
+
+
+
+ _ratioX = (float)(_realWidth - _borderLeft - _borderRight) / (float)_width;
+ _ratioY = (float)(_realHeight - _borderTop - _borderBottom) / (float)_height;
+
+ _windowed = !ConfMan.getBool("fullscreen");
+
+ Graphics::PixelFormat format(4, 8, 8, 8, 8, 16, 8, 0, 24);
+ g_system->beginGFXTransaction();
+ g_system->initSize(_width, _height, &format);
+ OSystem::TransactionError gfxError = g_system->endGFXTransaction();
+
+ if (gfxError != OSystem::kTransactionSuccess) {
+ warning("Couldn't setup GFX-backend for %dx%dx%d", _width, _height, format.bytesPerPixel * 8);
+ return STATUS_FAILED;
+ }
+
+ g_system->showMouse(false);
+
+ _renderSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat());
+ _blankSurface->create(g_system->getWidth(), g_system->getHeight(), g_system->getScreenFormat());
+ _blankSurface->fillRect(Common::Rect(0, 0, _blankSurface->h, _blankSurface->w), _blankSurface->format.ARGBToColor(255, 0, 0, 0));
+ _active = true;
+
+ _clearColor = _renderSurface->format.ARGBToColor(255, 0, 0, 0);
+
+ return STATUS_OK;
+}
+
+void BaseRenderOSystem::setAlphaMod(byte alpha) {
+ byte r = RGBCOLGetR(_colorMod);
+ byte g = RGBCOLGetB(_colorMod);
+ byte b = RGBCOLGetB(_colorMod);
+ _colorMod = BS_ARGB(alpha, r, g, b);
+}
+
+void BaseRenderOSystem::setColorMod(byte r, byte g, byte b) {
+ byte alpha = RGBCOLGetA(_colorMod);
+ _colorMod = BS_ARGB(alpha, r, g, b);
+}
+
+bool BaseRenderOSystem::indicatorFlip() {
+ g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_indicatorX, _indicatorY), _renderSurface->pitch, _indicatorX, _indicatorY, _indicatorWidthDrawn, _indicatorHeight);
+ g_system->updateScreen();
+ return STATUS_OK;
+}
+
+bool BaseRenderOSystem::flip() {
+ if (!_disableDirtyRects) {
+ drawTickets();
+ } else {
+ // Clear the scale-buffered tickets that wasn't reused.
+ RenderQueueIterator it = _renderQueue.begin();
+ while (it != _renderQueue.end()) {
+ if ((*it)->_wantsDraw == false) {
+ RenderTicket *ticket = *it;
+ it = _renderQueue.erase(it);
+ delete ticket;
+ } else {
+ (*it)->_wantsDraw = false;
+ ++it;
+ }
+ }
+ }
+ if (_needsFlip || _disableDirtyRects) {
+ if (_disableDirtyRects) {
+ g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, 0, 0, _renderSurface->w, _renderSurface->h);
+ }
+ // g_system->copyRectToScreen((byte *)_renderSurface->pixels, _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
+ delete _dirtyRect;
+ _dirtyRect = NULL;
+ g_system->updateScreen();
+ _needsFlip = false;
+ }
+ _drawNum = 1;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderOSystem::fill(byte r, byte g, byte b, Common::Rect *rect) {
+ _clearColor = _renderSurface->format.ARGBToColor(0xFF, r, g, b);
+ if (!_disableDirtyRects) {
+ return STATUS_OK;
+ }
+ if (!rect) {
+// TODO: This should speed things up, but for some reason it misses the size by quite a bit.
+/* if (r == 0 && g == 0 && b == 0) {
+ // Simply memcpy from the buffered black-surface, way faster than Surface::fillRect.
+ memcpy(_renderSurface->pixels, _blankSurface->pixels, _renderSurface->pitch * _renderSurface->h);
+ return STATUS_OK;
+ }*/
+ rect = &_renderRect;
+ }
+ // TODO: This doesn't work with dirty rects
+ _renderSurface->fillRect(*rect, _clearColor);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::fade(uint16 alpha) {
+ byte dwAlpha = (byte)(255 - alpha);
+ return fadeToColor(0, 0, 0, dwAlpha);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect) {
+ // This particular warning is rather messy, as this function is called a ton,
+ // thus we avoid printing it more than once.
+
+ // TODO: Add fading with dirty rects.
+ if (!_disableDirtyRects) {
+ warning("BaseRenderOSystem::FadeToColor - Breaks when using dirty rects");
+ }
+
+ Common::Rect fillRect;
+
+ if (rect) {
+ fillRect.left = rect->left;
+ fillRect.top = rect->top;
+ fillRect.setWidth(rect->width());
+ fillRect.setHeight(rect->height());
+ } else {
+ Rect32 rc;
+ _gameRef->getCurrentViewportRect(&rc);
+ fillRect.left = (int16)rc.left;
+ fillRect.top = (int16)rc.top;
+ fillRect.setWidth((int16)(rc.right - rc.left));
+ fillRect.setHeight((int16)(rc.bottom - rc.top));
+ }
+ modTargetRect(&fillRect);
+
+ //TODO: This is only here until I'm sure about the final pixelformat
+ uint32 col = _renderSurface->format.ARGBToColor(a, r, g, b);
+
+ setAlphaMod(255);
+ setColorMod(255, 255, 255);
+ Graphics::Surface surf;
+ surf.create((uint16)fillRect.width(), (uint16)fillRect.height(), _renderSurface->format);
+ Common::Rect sizeRect(fillRect);
+ sizeRect.translate(-fillRect.top, -fillRect.left);
+ surf.fillRect(fillRect, col);
+ drawSurface(NULL, &surf, &sizeRect, &fillRect, false, false);
+ surf.free();
+
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, a);
+ //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
+ //SDL_RenderFillRect(_renderer, &fillRect);
+}
+
+Graphics::PixelFormat BaseRenderOSystem::getPixelFormat() const {
+ return _renderSurface->format;
+}
+
+void BaseRenderOSystem::drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha) {
+ // Skip rects that are completely outside the screen:
+ if ((dstRect->left < 0 && dstRect->right < 0) || (dstRect->top < 0 && dstRect->bottom < 0)) {
+ return;
+ }
+
+ if (owner) { // Fade-tickets are owner-less
+ RenderTicket compare(owner, NULL, srcRect, dstRect, mirrorX, mirrorY, disableAlpha);
+ compare._colorMod = _colorMod;
+ RenderQueueIterator it;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
+ if ((*it)->_owner == owner && *(*it) == compare && (*it)->_isValid) {
+ (*it)->_colorMod = _colorMod;
+ if (_disableDirtyRects) {
+ drawFromSurface(*it, NULL);
+ } else {
+ drawFromTicket(*it);
+ }
+ return;
+ }
+ }
+ }
+ RenderTicket *ticket = new RenderTicket(owner, surf, srcRect, dstRect, mirrorX, mirrorY, disableAlpha);
+ ticket->_colorMod = _colorMod;
+ if (!_disableDirtyRects) {
+ drawFromTicket(ticket);
+ } else {
+ ticket->_wantsDraw = true;
+ _renderQueue.push_back(ticket);
+ drawFromSurface(ticket, NULL);
+ }
+}
+
+void BaseRenderOSystem::invalidateTicket(RenderTicket *renderTicket) {
+ addDirtyRect(renderTicket->_dstRect);
+ renderTicket->_isValid = false;
+// renderTicket->_canDelete = true; // TODO: Maybe readd this, to avoid even more duplicates.
+}
+
+void BaseRenderOSystem::invalidateTicketsFromSurface(BaseSurfaceOSystem *surf) {
+ RenderQueueIterator it;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
+ if ((*it)->_owner == surf) {
+ invalidateTicket(*it);
+ }
+ }
+}
+
+void BaseRenderOSystem::drawFromTicket(RenderTicket *renderTicket) {
+ renderTicket->_wantsDraw = true;
+ // A new item always has _drawNum == 0
+ if (renderTicket->_drawNum == 0) {
+ // In-order
+ if (_renderQueue.empty() || _drawNum > (_renderQueue.back())->_drawNum) {
+ renderTicket->_drawNum = _drawNum++;
+ _renderQueue.push_back(renderTicket);
+ addDirtyRect(renderTicket->_dstRect);
+ } else {
+ // Before something
+ Common::List<RenderTicket *>::iterator pos;
+ for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) {
+ if ((*pos)->_drawNum >= _drawNum) {
+ break;
+ }
+ }
+ _renderQueue.insert(pos, renderTicket);
+ Common::List<RenderTicket *>::iterator it;
+ renderTicket->_drawNum = _drawNum++;
+ // Increment the following tickets, so they still are in line
+ for (it = pos; it != _renderQueue.end(); ++it) {
+ (*it)->_drawNum++;
+ (*it)->_wantsDraw = false;
+ }
+ addDirtyRect(renderTicket->_dstRect);
+ }
+ } else {
+ // Was drawn last round, still in the same order
+ if (_drawNum == renderTicket->_drawNum) {
+ _drawNum++;
+ } else {
+ // Remove the ticket from the list
+ RenderQueueIterator it = _renderQueue.begin();
+ while (it != _renderQueue.end()) {
+ if ((*it) == renderTicket) {
+ it = _renderQueue.erase(it);
+ break;
+ } else {
+ ++it;
+ }
+ }
+ if (it != _renderQueue.end()) {
+ // Decreement the following tickets.
+ for (; it != _renderQueue.end(); ++it) {
+ (*it)->_drawNum--;
+ }
+ }
+ // Is not in order, so readd it as if it was a new ticket
+ renderTicket->_drawNum = 0;
+ drawFromTicket(renderTicket);
+ }
+ }
+}
+
+void BaseRenderOSystem::addDirtyRect(const Common::Rect &rect) {
+ if (!_dirtyRect) {
+ _dirtyRect = new Common::Rect(rect);
+ } else {
+ _dirtyRect->extend(rect);
+ }
+ _dirtyRect->clip(_renderRect);
+}
+
+void BaseRenderOSystem::drawTickets() {
+ RenderQueueIterator it = _renderQueue.begin();
+ // Clean out the old tickets
+ int decrement = 0;
+ while (it != _renderQueue.end()) {
+ if ((*it)->_wantsDraw == false || (*it)->_isValid == false) {
+ RenderTicket *ticket = *it;
+ addDirtyRect((*it)->_dstRect);
+ it = _renderQueue.erase(it);
+ delete ticket;
+ decrement++;
+ } else {
+ (*it)->_drawNum -= decrement;
+ ++it;
+ }
+ }
+ if (!_dirtyRect || _dirtyRect->width() == 0 || _dirtyRect->height() == 0) {
+ return;
+ }
+ // The color-mods are stored in the RenderTickets on add, since we set that state again during
+ // draw, we need to keep track of what it was prior to draw.
+ uint32 oldColorMod = _colorMod;
+
+ // Apply the clear-color to the dirty rect.
+ _renderSurface->fillRect(*_dirtyRect, _clearColor);
+ _drawNum = 1;
+ for (it = _renderQueue.begin(); it != _renderQueue.end(); ++it) {
+ RenderTicket *ticket = *it;
+ assert(ticket->_drawNum == _drawNum++);
+ if (ticket->_isValid && ticket->_dstRect.intersects(*_dirtyRect)) {
+ // dstClip is the area we want redrawn.
+ Common::Rect dstClip(ticket->_dstRect);
+ // reduce it to the dirty rect
+ dstClip.clip(*_dirtyRect);
+ // we need to keep track of the position to redraw the dirty rect
+ Common::Rect pos(dstClip);
+ int16 offsetX = ticket->_dstRect.left;
+ int16 offsetY = ticket->_dstRect.top;
+ // convert from screen-coords to surface-coords.
+ dstClip.translate(-offsetX, -offsetY);
+
+ _colorMod = ticket->_colorMod;
+ drawFromSurface(ticket->getSurface(), &ticket->_srcRect, &pos, &dstClip, ticket->_mirror);
+ _needsFlip = true;
+ }
+ // Some tickets want redraw but don't actually clip the dirty area (typically the ones that shouldnt become clear-color)
+ ticket->_wantsDraw = false;
+ }
+ g_system->copyRectToScreen((byte *)_renderSurface->getBasePtr(_dirtyRect->left, _dirtyRect->top), _renderSurface->pitch, _dirtyRect->left, _dirtyRect->top, _dirtyRect->width(), _dirtyRect->height());
+
+ // Revert the colorMod-state.
+ _colorMod = oldColorMod;
+}
+
+// Replacement for SDL2's SDL_RenderCopy
+void BaseRenderOSystem::drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect) {
+ TransparentSurface src(*ticket->getSurface(), false);
+ bool doDelete = false;
+ if (!clipRect) {
+ doDelete = true;
+ clipRect = new Common::Rect();
+ clipRect->setWidth(ticket->getSurface()->w);
+ clipRect->setHeight(ticket->getSurface()->h);
+ }
+
+ src._enableAlphaBlit = ticket->_hasAlpha;
+ src.blit(*_renderSurface, ticket->_dstRect.left, ticket->_dstRect.top, ticket->_mirror, clipRect, _colorMod, clipRect->width(), clipRect->height());
+ if (doDelete) {
+ delete clipRect;
+ }
+}
+void BaseRenderOSystem::drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror) {
+ TransparentSurface src(*surf, false);
+ bool doDelete = false;
+ if (!clipRect) {
+ doDelete = true;
+ clipRect = new Common::Rect();
+ clipRect->setWidth(surf->w);
+ clipRect->setHeight(surf->h);
+ }
+
+ src.blit(*_renderSurface, dstRect->left, dstRect->top, mirror, clipRect, _colorMod, clipRect->width(), clipRect->height());
+ if (doDelete) {
+ delete clipRect;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderOSystem::drawLine(int x1, int y1, int x2, int y2, uint32 color) {
+
+ if (!_disableDirtyRects) {
+ warning("BaseRenderOSystem::DrawLine - doesn't work for dirty rects yet");
+ }
+
+ byte r = RGBCOLGetR(color);
+ byte g = RGBCOLGetG(color);
+ byte b = RGBCOLGetB(color);
+ byte a = RGBCOLGetA(color);
+
+ //SDL_SetRenderDrawColor(_renderer, r, g, b, a);
+ //SDL_SetRenderDrawBlendMode(_renderer, SDL_BLENDMODE_BLEND);
+
+ Point32 point1, point2;
+ point1.x = x1;
+ point1.y = y1;
+ pointToScreen(&point1);
+
+ point2.x = x2;
+ point2.y = y2;
+ pointToScreen(&point2);
+
+ // TODO: This thing is mostly here until I'm sure about the final color-format.
+ uint32 colorVal = _renderSurface->format.ARGBToColor(a, r, g, b);
+ _renderSurface->drawLine(point1.x, point1.y, point2.x, point2.y, colorVal);
+ //SDL_RenderDrawLine(_renderer, point1.x, point1.y, point2.x, point2.y);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseImage *BaseRenderOSystem::takeScreenshot() {
+// TODO: Clip by viewport.
+ BaseImage *screenshot = new BaseImage();
+ screenshot->copyFrom(_renderSurface);
+ return screenshot;
+}
+
+//////////////////////////////////////////////////////////////////////////
+Common::String BaseRenderOSystem::getName() const {
+ return "ScummVM-OSystem-renderer";
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseRenderOSystem::setViewport(int left, int top, int right, int bottom) {
+ Common::Rect rect;
+ // TODO: Hopefully this is the same logic that ScummVM uses.
+ rect.left = (int16)(left + _borderLeft);
+ rect.top = (int16)(top + _borderTop);
+ rect.right = (int16)((right - left) * _ratioX);
+ rect.bottom = (int16)((bottom - top) * _ratioY);
+
+ _renderRect = rect;
+ return STATUS_OK;
+}
+
+Rect32 BaseRenderOSystem::getViewPort() {
+ Rect32 ret;
+ ret.top = _renderRect.top;
+ ret.bottom = _renderRect.bottom;
+ ret.left = _renderRect.left;
+ ret.right = _renderRect.right;
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::modTargetRect(Common::Rect *rect) {
+ rect->left = (int16)MathUtil::round(rect->left * _ratioX + _borderLeft - _renderRect.left);
+ rect->top = (int16)MathUtil::round(rect->top * _ratioY + _borderTop - _renderRect.top);
+ rect->setWidth((int16)MathUtil::roundUp(rect->width() * _ratioX));
+ rect->setHeight((int16)MathUtil::roundUp(rect->height() * _ratioY));
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::pointFromScreen(Point32 *point) {
+ point->x = (int16)(point->x / _ratioX - _borderLeft / _ratioX + _renderRect.left);
+ point->y = (int16)(point->y / _ratioY - _borderTop / _ratioY + _renderRect.top);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::pointToScreen(Point32 *point) {
+ point->x = (int16)MathUtil::roundUp(point->x * _ratioX) + _borderLeft - _renderRect.left;
+ point->y = (int16)MathUtil::roundUp(point->y * _ratioY) + _borderTop - _renderRect.top;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseRenderOSystem::dumpData(const char *filename) {
+ warning("BaseRenderOSystem::DumpData(%s) - stubbed", filename); // TODO
+}
+
+BaseSurface *BaseRenderOSystem::createSurface() {
+ return new BaseSurfaceOSystem(_gameRef);
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/osystem/base_render_osystem.h b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
new file mode 100644
index 0000000000..1e72508cd0
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h
@@ -0,0 +1,131 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_RENDERER_SDL_H
+#define WINTERMUTE_BASE_RENDERER_SDL_H
+
+#include "engines/wintermute/base/gfx/base_renderer.h"
+#include "common/rect.h"
+#include "graphics/surface.h"
+#include "common/list.h"
+
+namespace Wintermute {
+class BaseSurfaceOSystem;
+class RenderTicket {
+ Graphics::Surface *_surface;
+public:
+ RenderTicket(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRest, bool mirrorX = false, bool mirrorY = false, bool disableAlpha = false);
+ RenderTicket() : _isValid(true), _wantsDraw(false), _drawNum(0) {}
+ ~RenderTicket();
+ const Graphics::Surface *getSurface() { return _surface; }
+ Common::Rect _srcRect;
+ Common::Rect _dstRect;
+ uint32 _mirror;
+ bool _hasAlpha;
+
+ bool _isValid;
+ bool _wantsDraw;
+ uint32 _drawNum;
+ uint32 _colorMod;
+
+ BaseSurfaceOSystem *_owner;
+ bool operator==(RenderTicket &a);
+};
+
+class BaseRenderOSystem : public BaseRenderer {
+public:
+ BaseRenderOSystem(BaseGame *inGame);
+ ~BaseRenderOSystem();
+
+ Common::String getName() const;
+
+ bool initRenderer(int width, int height, bool windowed);
+ bool flip();
+ virtual bool indicatorFlip();
+ bool fill(byte r, byte g, byte b, Common::Rect *rect = NULL);
+ Graphics::PixelFormat getPixelFormat() const;
+ void fade(uint16 alpha);
+ void fadeToColor(byte r, byte g, byte b, byte a, Common::Rect *rect = NULL);
+
+ bool drawLine(int x1, int y1, int x2, int y2, uint32 color);
+
+ BaseImage *takeScreenshot();
+
+ void setAlphaMod(byte alpha);
+ void setColorMod(byte r, byte g, byte b);
+ void invalidateTicket(RenderTicket *renderTicket);
+ void invalidateTicketsFromSurface(BaseSurfaceOSystem *surf);
+ void drawFromTicket(RenderTicket *renderTicket);
+
+ bool setViewport(int left, int top, int right, int bottom);
+ bool setViewport(Rect32 *rect) { return BaseRenderer::setViewport(rect); }
+ Rect32 getViewPort();
+ void modTargetRect(Common::Rect *rect);
+ void pointFromScreen(Point32 *point);
+ void pointToScreen(Point32 *point);
+
+ void dumpData(const char *filename);
+
+ float getScaleRatioX() const {
+ return _ratioX;
+ }
+ float getScaleRatioY() const {
+ return _ratioY;
+ }
+
+ void drawSurface(BaseSurfaceOSystem *owner, const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, bool mirrorX, bool mirrorY, bool disableAlpha = false);
+ BaseSurface *createSurface();
+private:
+ void addDirtyRect(const Common::Rect &rect);
+ void drawTickets();
+ void drawFromSurface(RenderTicket *ticket, Common::Rect *clipRect);
+ void drawFromSurface(const Graphics::Surface *surf, Common::Rect *srcRect, Common::Rect *dstRect, Common::Rect *clipRect, uint32 mirror);
+ typedef Common::List<RenderTicket *>::iterator RenderQueueIterator;
+ Common::Rect *_dirtyRect;
+ Common::List<RenderTicket *> _renderQueue;
+ bool _needsFlip;
+ uint32 _drawNum;
+ Common::Rect _renderRect;
+ Graphics::Surface *_renderSurface;
+ Graphics::Surface *_blankSurface;
+
+ int _borderLeft;
+ int _borderTop;
+ int _borderRight;
+ int _borderBottom;
+
+ static const bool _disableDirtyRects = true;
+ float _ratioX;
+ float _ratioY;
+ uint32 _colorMod;
+ uint32 _clearColor;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
new file mode 100644
index 0000000000..d5464782a3
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp
@@ -0,0 +1,429 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_file.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/gfx/osystem/base_surface_osystem.h"
+#include "engines/wintermute/base/gfx/osystem/base_render_osystem.h"
+#include "engines/wintermute/base/gfx/base_image.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "graphics/decoders/png.h"
+#include "graphics/decoders/bmp.h"
+#include "graphics/decoders/jpeg.h"
+#include "graphics/decoders/tga.h"
+#include "engines/wintermute/graphics/transparent_surface.h"
+#include "graphics/pixelformat.h"
+#include "graphics/surface.h"
+#include "common/stream.h"
+#include "common/system.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+BaseSurfaceOSystem::BaseSurfaceOSystem(BaseGame *inGame) : BaseSurface(inGame) {
+ _surface = new Graphics::Surface();
+ _alphaMask = NULL;
+ _hasAlpha = true;
+ _lockPixels = NULL;
+ _lockPitch = 0;
+ _loaded = false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseSurfaceOSystem::~BaseSurfaceOSystem() {
+ if (_surface) {
+ _surface->free();
+ delete _surface;
+ _surface = NULL;
+ }
+
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+
+ _gameRef->addMem(-_width * _height * 4);
+ BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
+ renderer->invalidateTicketsFromSurface(this);
+}
+
+bool hasTransparency(Graphics::Surface *surf) {
+ if (surf->format.bytesPerPixel != 4) {
+ warning("hasTransparency:: non 32 bpp surface passed as argument");
+ return false;
+ }
+ uint8 r, g, b, a;
+ for (int i = 0; i < surf->h; i++) {
+ for (int j = 0; j < surf->w; j++) {
+ uint32 pix = *(uint32 *)surf->getBasePtr(j, i);
+ surf->format.colorToARGB(pix, a, r, g, b);
+ if (a != 255) {
+ return true;
+ }
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime, bool keepLoaded) {
+ /* BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer); */
+ _filename = filename;
+// const Graphics::Surface *surface = image->getSurface();
+
+ if (defaultCK) {
+ ckRed = 255;
+ ckGreen = 0;
+ ckBlue = 255;
+ }
+
+ _ckDefault = defaultCK;
+ _ckRed = ckRed;
+ _ckGreen = ckGreen;
+ _ckBlue = ckBlue;
+
+ if (_lifeTime == 0 || lifeTime == -1 || lifeTime > _lifeTime) {
+ _lifeTime = lifeTime;
+ }
+
+ _keepLoaded = keepLoaded;
+ if (_keepLoaded) {
+ _lifeTime = -1;
+ }
+
+ return STATUS_OK;
+}
+
+bool BaseSurfaceOSystem::finishLoad() {
+ BaseImage *image = new BaseImage();
+ if (!image->loadFile(_filename)) {
+ return false;
+ }
+
+ _width = image->getSurface()->w;
+ _height = image->getSurface()->h;
+
+ bool isSaveGameGrayscale = scumm_strnicmp(_filename.c_str(), "savegame:", 9) == 0 && (_filename.c_str()[_filename.size() - 1] == 'g' || _filename.c_str()[_filename.size() - 1] == 'G');
+ if (isSaveGameGrayscale) {
+ warning("grayscaleConversion not yet implemented");
+ // FIBITMAP *newImg = FreeImage_ConvertToGreyscale(img); TODO
+ }
+
+ // no alpha, set color key
+ /* if (surface->format.bytesPerPixel != 4)
+ SDL_SetColorKey(surf, SDL_TRUE, SDL_MapRGB(surf->format, ck_red, ck_green, ck_blue));*/
+
+ // convert 32-bit BMPs to 24-bit or they appear totally transparent (does any app actually write alpha in BMP properly?)
+ // Well, actually, we don't convert via 24-bit as the color-key application overwrites the Alpha-channel anyhow.
+ _surface->free();
+ delete _surface;
+ if (_filename.hasSuffix(".bmp") && image->getSurface()->format.bytesPerPixel == 4) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
+ TransparentSurface trans(*_surface);
+ trans.applyColorKey(_ckRed, _ckGreen, _ckBlue);
+ } else if (image->getSurface()->format.bytesPerPixel == 1 && image->getPalette()) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat(), image->getPalette());
+ TransparentSurface trans(*_surface);
+ trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true);
+ } else if (image->getSurface()->format.bytesPerPixel >= 3 && image->getSurface()->format != g_system->getScreenFormat()) {
+ _surface = image->getSurface()->convertTo(g_system->getScreenFormat());
+ if (image->getSurface()->format.bytesPerPixel == 3) {
+ TransparentSurface trans(*_surface);
+ trans.applyColorKey(_ckRed, _ckGreen, _ckBlue, true);
+ }
+ } else {
+ _surface = new Graphics::Surface();
+ _surface->copyFrom(*image->getSurface());
+ }
+
+ _hasAlpha = hasTransparency(_surface);
+ _valid = true;
+
+ _gameRef->addMem(_width * _height * 4);
+
+ delete image;
+
+ _loaded = true;
+
+ return true;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSurfaceOSystem::genAlphaMask(Graphics::Surface *surface) {
+ warning("BaseSurfaceOSystem::GenAlphaMask - Not ported yet");
+ return;
+ // TODO: Reimplement this
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+ if (!surface) {
+ return;
+ }
+
+ bool hasColorKey;
+ /* uint32 colorKey; */
+ uint8 ckRed, ckGreen, ckBlue;
+ /* if (SDL_GetColorKey(surface, &colorKey) == 0) {
+ hasColorKey = true;
+ SDL_GetRGB(colorKey, surface->format, &ckRed, &ckGreen, &ckBlue);
+ } else hasColorKey = false;
+ */
+ _alphaMask = new byte[surface->w * surface->h];
+
+ bool hasTransparency = false;
+ for (int y = 0; y < surface->h; y++) {
+ for (int x = 0; x < surface->w; x++) {
+ uint32 pixel = getPixelAt(surface, x, y);
+
+ uint8 r, g, b, a;
+ surface->format.colorToARGB(pixel, a, r, g, b);
+ //SDL_GetRGBA(pixel, surface->format, &r, &g, &b, &a);
+
+ if (hasColorKey && r == ckRed && g == ckGreen && b == ckBlue) {
+ a = 0;
+ }
+
+ _alphaMask[y * surface->w + x] = a;
+ if (a < 255) {
+ hasTransparency = true;
+ }
+ }
+ }
+
+ if (!hasTransparency) {
+ delete[] _alphaMask;
+ _alphaMask = NULL;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseSurfaceOSystem::getPixelAt(Graphics::Surface *surface, int x, int y) {
+ warning("BaseSurfaceOSystem::GetPixel - Not ported yet");
+ int bpp = surface->format.bytesPerPixel;
+ /* Here p is the address to the pixel we want to retrieve */
+ uint8 *p = (uint8 *)surface->pixels + y * surface->pitch + x * bpp;
+
+ switch (bpp) {
+ case 1:
+ return *p;
+ break;
+
+ case 2:
+ return *(uint16 *)p;
+ break;
+
+ case 3:
+#ifdef SCUMM_BIG_ENDIAN
+ // if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
+ return p[0] << 16 | p[1] << 8 | p[2];
+#else
+ //else
+ return p[0] | p[1] << 8 | p[2] << 16;
+#endif
+ break;
+
+ case 4:
+ return *(uint32 *)p;
+ break;
+
+ default:
+ return 0; /* shouldn't happen, but avoids warnings */
+ }
+ return 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::create(int width, int height) {
+ _width = width;
+ _height = height;
+
+ _gameRef->addMem(_width * _height * 4);
+
+ _valid = true;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::isTransparentAt(int x, int y) {
+ return isTransparentAtLite(x, y);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::isTransparentAtLite(int x, int y) {
+ if (x < 0 || x >= _surface->w || y < 0 || y >= _surface->h) {
+ return true;
+ }
+
+ if (_surface->format.bytesPerPixel == 4) {
+ uint32 pixel = *(uint32 *)_surface->getBasePtr(x, y);
+ uint8 r, g, b, a;
+ _surface->format.colorToARGB(pixel, a, r, g, b);
+ if (a <= 128) {
+ return true;
+ } else {
+ return false;
+ }
+ }
+
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::startPixelOp() {
+ //SDL_LockTexture(_texture, NULL, &_lockPixels, &_lockPitch);
+ // Any pixel-op makes the caching useless:
+ BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
+ renderer->invalidateTicketsFromSurface(this);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::endPixelOp() {
+ //SDL_UnlockTexture(_texture);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return drawSprite(x, y, &rect, 100, 100, 0xFFFFFFFF, true, blendMode, mirrorX, mirrorY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::displayTrans(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::displayTransOffset(int x, int y, Rect32 rect, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
+ return drawSprite(x, y, &rect, 100, 100, alpha, false, blendMode, mirrorX, mirrorY, offsetX, offsetY);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha, bool transparent, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return drawSprite(x, y, &rect, zoomX, zoomY, alpha, !transparent, blendMode, mirrorX, mirrorY);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::displayTransform(int x, int y, int hotX, int hotY, Rect32 rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY) {
+ return drawSprite(x, y, &rect, zoomX, zoomY, alpha, false, blendMode, mirrorX, mirrorY);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSurfaceOSystem::drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX, int offsetY) {
+ BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
+
+ if (!_loaded) {
+ finishLoad();
+ }
+
+ if (renderer->_forceAlphaColor != 0) {
+ alpha = renderer->_forceAlphaColor;
+ }
+
+ byte r = RGBCOLGetR(alpha);
+ byte g = RGBCOLGetG(alpha);
+ byte b = RGBCOLGetB(alpha);
+ byte a = RGBCOLGetA(alpha);
+
+ renderer->setAlphaMod(a);
+ renderer->setColorMod(r, g, b);
+
+#if 0 // These are kept for reference if BlendMode is reimplemented at some point.
+ if (alphaDisable) {
+ SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_NONE);
+ } else {
+ SDL_SetTextureBlendMode(_texture, SDL_BLENDMODE_BLEND);
+ }
+#endif
+ // TODO: This _might_ miss the intended behaviour by 1 in each direction
+ // But I think it fits the model used in Wintermute.
+ Common::Rect srcRect;
+ srcRect.left = rect->left;
+ srcRect.top = rect->top;
+ srcRect.setWidth(rect->right - rect->left);
+ srcRect.setHeight(rect->bottom - rect->top);
+
+ Common::Rect position;
+ position.left = x + offsetX;
+ position.top = y + offsetY;
+
+ // Crop off-by-ones:
+ if (position.left == -1) {
+ position.left = 0; // TODO: Something is wrong
+ }
+ if (position.top == -1) {
+ position.top = 0; // TODO: Something is wrong
+ }
+
+ position.setWidth((int16)((float)srcRect.width() * zoomX / 100.f));
+ position.setHeight((int16)((float)srcRect.height() * zoomX / 100.f));
+
+ renderer->modTargetRect(&position);
+
+ /* position.left += offsetX;
+ position.top += offsetY;*/
+
+ // TODO: This actually requires us to have the SAME source-offsets every time,
+ // But no checking is in place for that yet.
+
+ // TODO: Optimize by not doing alpha-blits if we lack or disable alpha
+ bool hasAlpha;
+ if (_hasAlpha && !alphaDisable) {
+ hasAlpha = true;
+ } else {
+ hasAlpha = false;
+ }
+ if (alphaDisable) {
+ warning("BaseSurfaceOSystem::drawSprite - AlphaDisable ignored");
+ }
+
+ renderer->drawSurface(this, _surface, &srcRect, &position, mirrorX, mirrorY, !hasAlpha);
+
+ return STATUS_OK;
+}
+
+bool BaseSurfaceOSystem::putSurface(const Graphics::Surface &surface, bool hasAlpha) {
+ _loaded = true;
+ _surface->free();
+ _surface->copyFrom(surface);
+ _hasAlpha = hasAlpha;
+ BaseRenderOSystem *renderer = static_cast<BaseRenderOSystem *>(_gameRef->_renderer);
+ renderer->invalidateTicketsFromSurface(this);
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
new file mode 100644
index 0000000000..43422ef4e7
--- /dev/null
+++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h
@@ -0,0 +1,99 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SURFACESDL_H
+#define WINTERMUTE_BASE_SURFACESDL_H
+
+#include "graphics/surface.h"
+#include "engines/wintermute/base/gfx/base_surface.h"
+#include "common/list.h"
+
+namespace Wintermute {
+struct TransparentSurface;
+class BaseImage;
+class BaseSurfaceOSystem : public BaseSurface {
+public:
+ BaseSurfaceOSystem(BaseGame *inGame);
+ ~BaseSurfaceOSystem();
+
+ bool create(const Common::String &filename, bool defaultCK, byte ckRed, byte ckGreen, byte ckBlue, int lifeTime = -1, bool keepLoaded = false);
+ bool create(int width, int height);
+
+ bool isTransparentAt(int x, int y);
+ bool isTransparentAtLite(int x, int y);
+
+ bool startPixelOp();
+ bool endPixelOp();
+
+
+ bool displayTransZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false);
+ bool displayTrans(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false);
+ bool displayTransOffset(int x, int y, Rect32 rect, uint32 alpha = 0xFFFFFFFF, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false, int offsetX = 0, int offsetY = 0);
+ bool display(int x, int y, Rect32 rect, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false);
+ bool displayZoom(int x, int y, Rect32 rect, float zoomX, float zoomY, uint32 alpha = 0xFFFFFFFF, bool transparent = false, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false);
+ bool displayTransform(int x, int y, int hotX, int hotY, Rect32 Rect, float zoomX, float zoomY, uint32 alpha, float rotate, TSpriteBlendMode blendMode = BLEND_NORMAL, bool mirrorX = false, bool mirrorY = false);
+ virtual bool putSurface(const Graphics::Surface &surface, bool hasAlpha = false);
+ /* static unsigned DLL_CALLCONV ReadProc(void *buffer, unsigned size, unsigned count, fi_handle handle);
+ static int DLL_CALLCONV SeekProc(fi_handle handle, long offset, int origin);
+ static long DLL_CALLCONV TellProc(fi_handle handle);*/
+ virtual int getWidth() {
+ if (!_loaded) {
+ finishLoad();
+ }
+ if (_surface) {
+ return _surface->w;
+ }
+ return _width;
+ }
+ virtual int getHeight() {
+ if (!_loaded) {
+ finishLoad();
+ }
+ if (_surface) {
+ return _surface->h;
+ }
+ return _height;
+ }
+
+private:
+ Graphics::Surface *_surface;
+ bool _loaded;
+ bool finishLoad();
+ bool drawSprite(int x, int y, Rect32 *rect, float zoomX, float zoomY, uint32 alpha, bool alphaDisable, TSpriteBlendMode blendMode, bool mirrorX, bool mirrorY, int offsetX = 0, int offsetY = 0);
+ void genAlphaMask(Graphics::Surface *surface);
+ uint32 getPixelAt(Graphics::Surface *surface, int x, int y);
+
+ bool _hasAlpha;
+ void *_lockPixels;
+ int _lockPitch;
+ byte *_alphaMask;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/particles/part_emitter.cpp b/engines/wintermute/base/particles/part_emitter.cpp
new file mode 100644
index 0000000000..3655b89131
--- /dev/null
+++ b/engines/wintermute/base/particles/part_emitter.cpp
@@ -0,0 +1,1256 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/particles/part_emitter.h"
+#include "engines/wintermute/base/particles/part_particle.h"
+#include "engines/wintermute/math/vector2.h"
+#include "engines/wintermute/math/matrix4.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+#include "common/math.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(PartEmitter, false)
+
+//////////////////////////////////////////////////////////////////////////
+PartEmitter::PartEmitter(BaseGame *inGame, BaseScriptHolder *owner) : BaseObject(inGame) {
+ _width = _height = 0;
+
+ BasePlatform::setRectEmpty(&_border);
+ _borderThicknessLeft = _borderThicknessRight = _borderThicknessTop = _borderThicknessBottom = 0;
+
+ _angle1 = _angle2 = 0;
+
+ _velocity1 = _velocity2 = 0.0f;
+ _velocityZBased = false;
+
+ _scale1 = _scale2 = 100.0f;
+ _scaleZBased = false;
+
+ _maxParticles = 100;
+
+ _lifeTime1 = _lifeTime2 = 1000;
+ _lifeTimeZBased = false;
+
+ _lastGenTime = 0;
+ _genInterval = 0;
+ _genAmount = 1;
+
+ _overheadTime = 0;
+ _running = false;
+
+ _maxBatches = 0;
+ _batchesGenerated = 0;
+
+ _fadeInTime = _fadeOutTime = 0;
+
+ _alpha1 = _alpha2 = 255;
+ _alphaTimeBased = false;
+
+ _rotation1 = _rotation2 = 0.0f;
+ _angVelocity1 = _angVelocity2 = 0.0f;
+
+ _growthRate1 = _growthRate2 = 0.0f;
+ _exponentialGrowth = false;
+
+ _useRegion = false;
+
+ _emitEvent = NULL;
+ _owner = owner;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+PartEmitter::~PartEmitter(void) {
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ delete _particles[i];
+ }
+ _particles.clear();
+
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ delete _forces[i];
+ }
+ _forces.clear();
+
+
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ delete[] _sprites[i];
+ }
+ _sprites.clear();
+
+ delete[] _emitEvent;
+ _emitEvent = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::addSprite(const char *filename) {
+ if (!filename) {
+ return STATUS_FAILED;
+ }
+
+ // do we already have the file?
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ if (scumm_stricmp(filename, _sprites[i]) == 0) {
+ return STATUS_OK;
+ }
+ }
+
+ // check if file exists
+ Common::SeekableReadStream *File = BaseFileManager::getEngineInstance()->openFile(filename);
+ if (!File) {
+ _gameRef->LOG(0, "Sprite '%s' not found", filename);
+ return STATUS_FAILED;
+ } else {
+ BaseFileManager::getEngineInstance()->closeFile(File);
+ }
+
+ char *str = new char[strlen(filename) + 1];
+ strcpy(str, filename);
+ _sprites.add(str);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::removeSprite(const char *filename) {
+ for (uint32 i = 0; i < _sprites.size(); i++) {
+ if (scumm_stricmp(filename, _sprites[i]) == 0) {
+ delete[] _sprites[i];
+ _sprites.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+ return STATUS_FAILED;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::initParticle(PartParticle *particle, uint32 currentTime, uint32 timerDelta) {
+ if (!particle) {
+ return STATUS_FAILED;
+ }
+ if (_sprites.size() == 0) {
+ return STATUS_FAILED;
+ }
+
+ int posX = BaseUtils::randomInt(_posX, _posX + _width);
+ int posY = BaseUtils::randomInt(_posY, _posY + _height);
+ float posZ = BaseUtils::randomFloat(0.0f, 100.0f);
+
+ float velocity;
+ if (_velocityZBased) {
+ velocity = _velocity1 + posZ * (_velocity2 - _velocity1) / 100;
+ } else {
+ velocity = BaseUtils::randomFloat(_velocity1, _velocity2);
+ }
+
+ float scale;
+ if (_scaleZBased) {
+ scale = _scale1 + posZ * (_scale2 - _scale1) / 100;
+ } else {
+ scale = BaseUtils::randomFloat(_scale1, _scale2);
+ }
+
+ int lifeTime;
+ if (_lifeTimeZBased) {
+ lifeTime = (int)(_lifeTime2 - posZ * (_lifeTime2 - _lifeTime1) / 100);
+ } else {
+ lifeTime = BaseUtils::randomInt(_lifeTime1, _lifeTime2);
+ }
+
+ float angle = BaseUtils::randomAngle(_angle1, _angle2);
+ int spriteIndex = BaseUtils::randomInt(0, _sprites.size() - 1);
+
+ float rotation = BaseUtils::randomAngle(_rotation1, _rotation2);
+ float angVelocity = BaseUtils::randomFloat(_angVelocity1, _angVelocity2);
+ float growthRate = BaseUtils::randomFloat(_growthRate1, _growthRate2);
+
+ if (!BasePlatform::isRectEmpty(&_border)) {
+ int thicknessLeft = (int)(_borderThicknessLeft - (float)_borderThicknessLeft * posZ / 100.0f);
+ int thicknessRight = (int)(_borderThicknessRight - (float)_borderThicknessRight * posZ / 100.0f);
+ int thicknessTop = (int)(_borderThicknessTop - (float)_borderThicknessTop * posZ / 100.0f);
+ int thicknessBottom = (int)(_borderThicknessBottom - (float)_borderThicknessBottom * posZ / 100.0f);
+
+ particle->_border = _border;
+ particle->_border.left += thicknessLeft;
+ particle->_border.right -= thicknessRight;
+ particle->_border.top += thicknessTop;
+ particle->_border.bottom -= thicknessBottom;
+ }
+
+ Vector2 vecPos((float)posX, (float)posY);
+ Vector2 vecVel(0, velocity);
+
+ Matrix4 matRot;
+ matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ matRot.transformVector2(vecVel);
+
+ if (_alphaTimeBased) {
+ particle->_alpha1 = _alpha1;
+ particle->_alpha2 = _alpha2;
+ } else {
+ int alpha = BaseUtils::randomInt(_alpha1, _alpha2);
+ particle->_alpha1 = alpha;
+ particle->_alpha2 = alpha;
+ }
+
+ particle->_creationTime = currentTime;
+ particle->_pos = vecPos;
+ particle->_posZ = posZ;
+ particle->_velocity = vecVel;
+ particle->_scale = scale;
+ particle->_lifeTime = lifeTime;
+ particle->_rotation = rotation;
+ particle->_angVelocity = angVelocity;
+ particle->_growthRate = growthRate;
+ particle->_exponentialGrowth = _exponentialGrowth;
+ particle->_isDead = DID_FAIL(particle->setSprite(_sprites[spriteIndex]));
+ particle->fadeIn(currentTime, _fadeInTime);
+
+
+ if (particle->_isDead) {
+ return STATUS_FAILED;
+ } else {
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::update() {
+ if (!_running) {
+ return STATUS_OK;
+ } else {
+ return updateInternal(_gameRef->_timer, _gameRef->_timerDelta);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::updateInternal(uint32 currentTime, uint32 timerDelta) {
+ int numLive = 0;
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->update(this, currentTime, timerDelta);
+
+ if (!_particles[i]->_isDead) {
+ numLive++;
+ }
+ }
+
+
+ // we're understaffed
+ if (numLive < _maxParticles) {
+ bool needsSort = false;
+ if ((int)(currentTime - _lastGenTime) > _genInterval) {
+ _lastGenTime = currentTime;
+ _batchesGenerated++;
+
+ if (_maxBatches > 0 && _batchesGenerated > _maxBatches) {
+ return STATUS_OK;
+ }
+
+ int toGen = MIN(_genAmount, _maxParticles - numLive);
+ while (toGen > 0) {
+ int firstDeadIndex = -1;
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (_particles[i]->_isDead) {
+ firstDeadIndex = i;
+ break;
+ }
+ }
+
+ PartParticle *particle;
+ if (firstDeadIndex >= 0) {
+ particle = _particles[firstDeadIndex];
+ } else {
+ particle = new PartParticle(_gameRef);
+ _particles.add(particle);
+ }
+ initParticle(particle, currentTime, timerDelta);
+ needsSort = true;
+
+ toGen--;
+ }
+ }
+ if (needsSort && (_scaleZBased || _velocityZBased || _lifeTimeZBased)) {
+ sortParticlesByZ();
+ }
+
+ // we actually generated some particles and we're not in fast-forward mode
+ if (needsSort && _overheadTime == 0) {
+ if (_owner && _emitEvent) {
+ _owner->applyEvent(_emitEvent);
+ }
+ }
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::display(BaseRegion *region) {
+ if (_sprites.size() <= 1) {
+ _gameRef->_renderer->startSpriteBatch();
+ }
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (region != NULL && _useRegion) {
+ if (!region->pointInRegion((int)_particles[i]->_pos.x, (int)_particles[i]->_pos.y)) {
+ continue;
+ }
+ }
+
+ _particles[i]->display(this);
+ }
+
+ if (_sprites.size() <= 1) {
+ _gameRef->_renderer->endSpriteBatch();
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::start() {
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->_isDead = true;
+ }
+ _running = true;
+ _batchesGenerated = 0;
+
+
+ if (_overheadTime > 0) {
+ uint32 delta = 500;
+ int steps = _overheadTime / delta;
+ uint32 currentTime = _gameRef->_timer - _overheadTime;
+
+ for (int i = 0; i < steps; i++) {
+ updateInternal(currentTime, delta);
+ currentTime += delta;
+ }
+ _overheadTime = 0;
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::sortParticlesByZ() {
+ // sort particles by _posY
+ Common::sort(_particles.begin(), _particles.end(), PartEmitter::compareZ);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int PartEmitter::compareZ(const void *obj1, const void *obj2) {
+ const PartParticle *p1 = *(const PartParticle *const *)obj1;
+ const PartParticle *p2 = *(const PartParticle *const *)obj2;
+
+ if (p1->_posZ < p2->_posZ) {
+ return -1;
+ } else if (p1->_posZ > p2->_posZ) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::setBorder(int x, int y, int width, int height) {
+ BasePlatform::setRect(&_border, x, y, x + width, y + height);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom) {
+ _borderThicknessLeft = thicknessLeft;
+ _borderThicknessRight = thicknessRight;
+ _borderThicknessTop = thicknessTop;
+ _borderThicknessBottom = thicknessBottom;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+PartForce *PartEmitter::addForceByName(const Common::String &name) {
+ PartForce *force = NULL;
+
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
+ force = _forces[i];
+ break;
+ }
+ }
+ if (!force) {
+ force = new PartForce(_gameRef);
+ if (force) {
+ force->setName(name.c_str());
+ _forces.add(force);
+ }
+ }
+ return force;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::addForce(const Common::String &name, PartForce::TForceType type, int posX, int posY, float angle, float strength) {
+ PartForce *force = addForceByName(name);
+ if (!force) {
+ return STATUS_FAILED;
+ }
+
+ force->_type = type;
+ force->_pos = Vector2(posX, posY);
+
+ force->_direction = Vector2(0, strength);
+ Matrix4 matRot;
+ matRot.rotationZ(Common::deg2rad(BaseUtils::normalizeAngle(angle - 180)));
+ matRot.transformVector2(force->_direction);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::removeForce(const Common::String &name) {
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ if (scumm_stricmp(name.c_str(), _forces[i]->getName()) == 0) {
+ delete _forces[i];
+ _forces.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// high level scripting interface
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetBorder
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SetBorder") == 0) {
+ stack->correctParams(4);
+ int borderX = stack->pop()->getInt();
+ int borderY = stack->pop()->getInt();
+ int borderWidth = stack->pop()->getInt();
+ int borderHeight = stack->pop()->getInt();
+
+ stack->pushBool(DID_SUCCEED(setBorder(borderX, borderY, borderWidth, borderHeight)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetBorderThickness
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetBorderThickness") == 0) {
+ stack->correctParams(4);
+ int left = stack->pop()->getInt();
+ int right = stack->pop()->getInt();
+ int top = stack->pop()->getInt();
+ int bottom = stack->pop()->getInt();
+
+ stack->pushBool(DID_SUCCEED(setBorderThickness(left, right, top, bottom)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AddSprite
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddSprite") == 0) {
+ stack->correctParams(1);
+ const char *spriteFile = stack->pop()->getString();
+ stack->pushBool(DID_SUCCEED(addSprite(spriteFile)));
+
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveSprite
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveSprite") == 0) {
+ stack->correctParams(1);
+ const char *spriteFile = stack->pop()->getString();
+ stack->pushBool(DID_SUCCEED(removeSprite(spriteFile)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Start
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Start") == 0) {
+ stack->correctParams(1);
+ _overheadTime = stack->pop()->getInt();
+ stack->pushBool(DID_SUCCEED(start()));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Stop
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Stop") == 0) {
+ stack->correctParams(0);
+
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ delete _particles[i];
+ }
+ _particles.clear();
+
+ _running = false;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Pause
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Pause") == 0) {
+ stack->correctParams(0);
+ _running = false;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Resume
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Resume") == 0) {
+ stack->correctParams(0);
+ _running = true;
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddGlobalForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddGlobalForce") == 0) {
+ stack->correctParams(3);
+ const char *forceName = stack->pop()->getString();
+ float angle = stack->pop()->getFloat();
+ float strength = stack->pop()->getFloat();
+
+ stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, 0, 0, angle, strength)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AddPointForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AddPointForce") == 0) {
+ stack->correctParams(5);
+ const char *forceName = stack->pop()->getString();
+ int posX = stack->pop()->getInt();
+ int posY = stack->pop()->getInt();
+ float angle = stack->pop()->getFloat();
+ float strength = stack->pop()->getFloat();
+
+ stack->pushBool(DID_SUCCEED(addForce(forceName, PartForce::FORCE_GLOBAL, posX, posY, angle, strength)));
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RemoveForce
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RemoveForce") == 0) {
+ stack->correctParams(1);
+ const char *forceName = stack->pop()->getString();
+
+ stack->pushBool(DID_SUCCEED(removeForce(forceName)));
+
+ return STATUS_OK;
+ } else {
+ return BaseObject::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *PartEmitter::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("particle-emitter");
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "X") == 0) {
+ _scValue->setInt(_posX);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _scValue->setInt(_posY);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Width") == 0) {
+ _scValue->setInt(_width);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Height") == 0) {
+ _scValue->setInt(_height);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale1") == 0) {
+ _scValue->setFloat(_scale1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Scale2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale2") == 0) {
+ _scValue->setFloat(_scale2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleZBased") == 0) {
+ _scValue->setBool(_scaleZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity1") == 0) {
+ _scValue->setFloat(_velocity1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity2") == 0) {
+ _scValue->setFloat(_velocity2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // VelocityZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VelocityZBased") == 0) {
+ _scValue->setBool(_velocityZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime1") == 0) {
+ _scValue->setInt(_lifeTime1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime2") == 0) {
+ _scValue->setInt(_lifeTime2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTimeZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTimeZBased") == 0) {
+ _scValue->setBool(_lifeTimeZBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Angle1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle1") == 0) {
+ _scValue->setInt(_angle1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Angle2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle2") == 0) {
+ _scValue->setInt(_angle2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity1") == 0) {
+ _scValue->setFloat(_angVelocity1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity2") == 0) {
+ _scValue->setFloat(_angVelocity2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation1") == 0) {
+ _scValue->setFloat(_rotation1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation2") == 0) {
+ _scValue->setFloat(_rotation2);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha1") == 0) {
+ _scValue->setInt(_alpha1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha2") == 0) {
+ _scValue->setInt(_alpha2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaTimeBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaTimeBased") == 0) {
+ _scValue->setBool(_alphaTimeBased);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxParticles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxParticles") == 0) {
+ _scValue->setInt(_maxParticles);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // NumLiveParticles (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "NumLiveParticles") == 0) {
+ int numAlive = 0;
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ if (_particles[i] && !_particles[i]->_isDead) {
+ numAlive++;
+ }
+ }
+ _scValue->setInt(numAlive);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationInterval
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationInterval") == 0) {
+ _scValue->setInt(_genInterval);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationAmount
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationAmount") == 0) {
+ _scValue->setInt(_genAmount);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // MaxBatches
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxBatches") == 0) {
+ _scValue->setInt(_maxBatches);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeInTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeInTime") == 0) {
+ _scValue->setInt(_fadeInTime);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // FadeOutTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeOutTime") == 0) {
+ _scValue->setInt(_fadeOutTime);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate1") == 0) {
+ _scValue->setFloat(_growthRate1);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate2") == 0) {
+ _scValue->setFloat(_growthRate2);
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ExponentialGrowth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ExponentialGrowth") == 0) {
+ _scValue->setBool(_exponentialGrowth);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // UseRegion
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "UseRegion") == 0) {
+ _scValue->setBool(_useRegion);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EmitEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EmitEvent") == 0) {
+ if (!_emitEvent) {
+ _scValue->setNULL();
+ } else {
+ _scValue->setString(_emitEvent);
+ }
+ return _scValue;
+ } else {
+ return BaseObject::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // X
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "X") == 0) {
+ _posX = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Y
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Y") == 0) {
+ _posY = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Width
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Width") == 0) {
+ _width = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Height
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Height") == 0) {
+ _height = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Scale1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale1") == 0) {
+ _scale1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Scale2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Scale2") == 0) {
+ _scale2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ScaleZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ScaleZBased") == 0) {
+ _scaleZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity1") == 0) {
+ _velocity1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Velocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Velocity2") == 0) {
+ _velocity2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // VelocityZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "VelocityZBased") == 0) {
+ _velocityZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime1") == 0) {
+ _lifeTime1 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTime2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTime2") == 0) {
+ _lifeTime2 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // LifeTimeZBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "LifeTimeZBased") == 0) {
+ _lifeTimeZBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Angle1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle1") == 0) {
+ _angle1 = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Angle2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Angle2") == 0) {
+ _angle2 = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity1") == 0) {
+ _angVelocity1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AngVelocity2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AngVelocity2") == 0) {
+ _angVelocity2 = value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation1") == 0) {
+ _rotation1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Rotation2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Rotation2") == 0) {
+ _rotation2 = value->getFloat();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha1") == 0) {
+ _alpha1 = value->getInt();
+ if (_alpha1 < 0) {
+ _alpha1 = 0;
+ }
+ if (_alpha1 > 255) {
+ _alpha1 = 255;
+ }
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Alpha2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Alpha2") == 0) {
+ _alpha2 = value->getInt();
+ if (_alpha2 < 0) {
+ _alpha2 = 0;
+ }
+ if (_alpha2 > 255) {
+ _alpha2 = 255;
+ }
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // AlphaTimeBased
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AlphaTimeBased") == 0) {
+ _alphaTimeBased = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // MaxParticles
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxParticles") == 0) {
+ _maxParticles = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationInterval
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationInterval") == 0) {
+ _genInterval = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GenerationAmount
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GenerationAmount") == 0) {
+ _genAmount = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // MaxBatches
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "MaxBatches") == 0) {
+ _maxBatches = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // FadeInTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeInTime") == 0) {
+ _fadeInTime = value->getInt();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // FadeOutTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "FadeOutTime") == 0) {
+ _fadeOutTime = value->getInt();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate1
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate1") == 0) {
+ _growthRate1 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GrowthRate2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GrowthRate2") == 0) {
+ _growthRate2 = value->getFloat();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // ExponentialGrowth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ExponentialGrowth") == 0) {
+ _exponentialGrowth = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // UseRegion
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "UseRegion") == 0) {
+ _useRegion = value->getBool();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // EmitEvent
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "EmitEvent") == 0) {
+ delete[] _emitEvent;
+ _emitEvent = NULL;
+ if (!value->isNULL()) {
+ BaseUtils::setString(&_emitEvent, value->getString());
+ }
+ return STATUS_OK;
+ } else {
+ return BaseObject::scSetProperty(name, value);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *PartEmitter::scToString() {
+ return "[particle emitter]";
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartEmitter::persist(BasePersistenceManager *persistMgr) {
+ BaseObject::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_width));
+ persistMgr->transfer(TMEMBER(_height));
+
+ persistMgr->transfer(TMEMBER(_angle1));
+ persistMgr->transfer(TMEMBER(_angle2));
+
+ persistMgr->transfer(TMEMBER(_velocity1));
+ persistMgr->transfer(TMEMBER(_velocity2));
+ persistMgr->transfer(TMEMBER(_velocityZBased));
+
+ persistMgr->transfer(TMEMBER(_scale1));
+ persistMgr->transfer(TMEMBER(_scale2));
+ persistMgr->transfer(TMEMBER(_scaleZBased));
+
+ persistMgr->transfer(TMEMBER(_maxParticles));
+
+ persistMgr->transfer(TMEMBER(_lifeTime1));
+ persistMgr->transfer(TMEMBER(_lifeTime2));
+ persistMgr->transfer(TMEMBER(_lifeTimeZBased));
+
+ persistMgr->transfer(TMEMBER(_genInterval));
+ persistMgr->transfer(TMEMBER(_genAmount));
+
+ persistMgr->transfer(TMEMBER(_running));
+ persistMgr->transfer(TMEMBER(_overheadTime));
+
+ persistMgr->transfer(TMEMBER(_border));
+ persistMgr->transfer(TMEMBER(_borderThicknessLeft));
+ persistMgr->transfer(TMEMBER(_borderThicknessRight));
+ persistMgr->transfer(TMEMBER(_borderThicknessTop));
+ persistMgr->transfer(TMEMBER(_borderThicknessBottom));
+
+ persistMgr->transfer(TMEMBER(_fadeInTime));
+ persistMgr->transfer(TMEMBER(_fadeOutTime));
+
+ persistMgr->transfer(TMEMBER(_alpha1));
+ persistMgr->transfer(TMEMBER(_alpha2));
+ persistMgr->transfer(TMEMBER(_alphaTimeBased));
+
+ persistMgr->transfer(TMEMBER(_angVelocity1));
+ persistMgr->transfer(TMEMBER(_angVelocity2));
+
+ persistMgr->transfer(TMEMBER(_rotation1));
+ persistMgr->transfer(TMEMBER(_rotation2));
+
+ persistMgr->transfer(TMEMBER(_growthRate1));
+ persistMgr->transfer(TMEMBER(_growthRate2));
+ persistMgr->transfer(TMEMBER(_exponentialGrowth));
+
+ persistMgr->transfer(TMEMBER(_useRegion));
+
+ persistMgr->transfer(TMEMBER_INT(_maxBatches));
+ persistMgr->transfer(TMEMBER_INT(_batchesGenerated));
+
+ persistMgr->transfer(TMEMBER(_emitEvent));
+ persistMgr->transfer(TMEMBER(_owner));
+
+
+ _sprites.persist(persistMgr);
+
+ uint32 numForces;
+ if (persistMgr->getIsSaving()) {
+ numForces = _forces.size();
+ persistMgr->transfer(TMEMBER(numForces));
+ for (uint32 i = 0; i < _forces.size(); i++) {
+ _forces[i]->persist(persistMgr);
+ }
+ } else {
+ persistMgr->transfer(TMEMBER(numForces));
+ for (uint32 i = 0; i < numForces; i++) {
+ PartForce *force = new PartForce(_gameRef);
+ force->persist(persistMgr);
+ _forces.add(force);
+ }
+ }
+
+ uint32 numParticles;
+ if (persistMgr->getIsSaving()) {
+ numParticles = _particles.size();
+ persistMgr->transfer(TMEMBER(numParticles));
+ for (uint32 i = 0; i < _particles.size(); i++) {
+ _particles[i]->persist(persistMgr);
+ }
+ } else {
+ persistMgr->transfer(TMEMBER(numParticles));
+ for (uint32 i = 0; i < numParticles; i++) {
+ PartParticle *particle = new PartParticle(_gameRef);
+ particle->persist(persistMgr);
+ _particles.add(particle);
+ }
+ }
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_emitter.h b/engines/wintermute/base/particles/part_emitter.h
new file mode 100644
index 0000000000..9a35cd9bbc
--- /dev/null
+++ b/engines/wintermute/base/particles/part_emitter.h
@@ -0,0 +1,140 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_PARTEMITTER_H
+#define WINTERMUTE_PARTEMITTER_H
+
+
+#include "engines/wintermute/base/base_object.h"
+#include "engines/wintermute/base/particles/part_force.h"
+
+namespace Wintermute {
+class BaseRegion;
+class PartParticle;
+class PartEmitter : public BaseObject {
+public:
+ DECLARE_PERSISTENT(PartEmitter, BaseObject)
+
+ PartEmitter(BaseGame *inGame, BaseScriptHolder *Owner);
+ virtual ~PartEmitter(void);
+
+ int _fadeOutTime;
+
+ bool start();
+
+ bool update();
+ bool display() { return display(NULL); } // To avoid shadowing the inherited display-function.
+ bool display(BaseRegion *region);
+
+ bool sortParticlesByZ();
+ bool addSprite(const char *filename);
+ bool removeSprite(const char *filename);
+ bool setBorder(int x, int y, int width, int height);
+ bool setBorderThickness(int thicknessLeft, int thicknessRight, int thicknessTop, int thicknessBottom);
+
+ bool addForce(const Common::String &name, PartForce::TForceType type, int posX, int posY, float angle, float strength);
+ bool removeForce(const Common::String &name);
+
+ BaseArray<PartForce *> _forces;
+
+ // scripting interface
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scSetProperty(const char *name, ScValue *value);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ virtual const char *scToString();
+
+
+private:
+ int _width;
+ int _height;
+
+ int _angle1;
+ int _angle2;
+
+ float _rotation1;
+ float _rotation2;
+
+ float _angVelocity1;
+ float _angVelocity2;
+
+ float _growthRate1;
+ float _growthRate2;
+ bool _exponentialGrowth;
+
+ float _velocity1;
+ float _velocity2;
+ bool _velocityZBased;
+
+ float _scale1;
+ float _scale2;
+ bool _scaleZBased;
+
+ int _maxParticles;
+
+ int _lifeTime1;
+ int _lifeTime2;
+ bool _lifeTimeZBased;
+
+ int _genInterval;
+ int _genAmount;
+
+ bool _running;
+ int _overheadTime;
+
+ int _maxBatches;
+ int _batchesGenerated;
+
+ Rect32 _border;
+ int _borderThicknessLeft;
+ int _borderThicknessRight;
+ int _borderThicknessTop;
+ int _borderThicknessBottom;
+
+ int _fadeInTime;
+
+ int _alpha1;
+ int _alpha2;
+ bool _alphaTimeBased;
+
+ bool _useRegion;
+
+ char *_emitEvent;
+ BaseScriptHolder *_owner;
+
+ PartForce *addForceByName(const Common::String &name);
+ int static compareZ(const void *obj1, const void *obj2);
+ bool initParticle(PartParticle *particle, uint32 currentTime, uint32 timerDelta);
+ bool updateInternal(uint32 currentTime, uint32 timerDelta);
+ uint32 _lastGenTime;
+ BaseArray<PartParticle *> _particles;
+ BaseArray<char *> _sprites;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/particles/part_force.cpp b/engines/wintermute/base/particles/part_force.cpp
new file mode 100644
index 0000000000..df84162504
--- /dev/null
+++ b/engines/wintermute/base/particles/part_force.cpp
@@ -0,0 +1,65 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/base/particles/part_force.h"
+#include "engines/wintermute/base/base_persistence_manager.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+PartForce::PartForce(BaseGame *inGame) : BaseNamedObject(inGame) {
+ _pos = Vector2(0.0f, 0.0f);
+ _direction = Vector2(0.0f, 0.0f);
+ _type = FORCE_POINT;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+PartForce::~PartForce(void) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartForce::persist(BasePersistenceManager *persistMgr) {
+ if (persistMgr->getIsSaving()) {
+ const char *name = getName();
+ persistMgr->transfer(TMEMBER(name));
+ } else {
+ const char *name;
+ persistMgr->transfer(TMEMBER(name));
+ setName(name);
+ }
+ persistMgr->transfer(TMEMBER(_pos));
+ persistMgr->transfer(TMEMBER(_direction));
+ persistMgr->transfer(TMEMBER_INT(_type));
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_force.h b/engines/wintermute/base/particles/part_force.h
new file mode 100644
index 0000000000..27f4cb7d90
--- /dev/null
+++ b/engines/wintermute/base/particles/part_force.h
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_PARTFORCE_H
+#define WINTERMUTE_PARTFORCE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/base/base_named_object.h"
+#include "engines/wintermute/math/vector2.h"
+
+namespace Wintermute {
+
+class PartForce : public BaseNamedObject {
+public:
+ enum TForceType {
+ FORCE_POINT, FORCE_GLOBAL
+ };
+
+ PartForce(BaseGame *inGame);
+ virtual ~PartForce(void);
+
+ Vector2 _pos;
+ Vector2 _direction;
+ TForceType _type;
+
+ bool persist(BasePersistenceManager *PersistMgr);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/particles/part_particle.cpp b/engines/wintermute/base/particles/part_particle.cpp
new file mode 100644
index 0000000000..0b850d9618
--- /dev/null
+++ b/engines/wintermute/base/particles/part_particle.cpp
@@ -0,0 +1,269 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/particles/part_particle.h"
+#include "engines/wintermute/base/particles/part_emitter.h"
+#include "engines/wintermute/base/base_sprite.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "common/str.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////////
+PartParticle::PartParticle(BaseGame *inGame) : BaseClass(inGame) {
+ _pos = Vector2(0.0f, 0.0f);
+ _posZ = 0.0f;
+ _velocity = Vector2(0.0f, 0.0f);
+ _scale = 100.0f;
+ _sprite = NULL;
+ _creationTime = 0;
+ _lifeTime = 0;
+ _isDead = true;
+ BasePlatform::setRectEmpty(&_border);
+
+ _state = PARTICLE_NORMAL;
+ _fadeStart = 0;
+ _fadeTime = 0;
+ _currentAlpha = 255;
+
+ _alpha1 = _alpha2 = 255;
+
+ _rotation = 0.0f;
+ _angVelocity = 0.0f;
+
+ _growthRate = 0.0f;
+ _exponentialGrowth = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+PartParticle::~PartParticle(void) {
+ delete _sprite;
+ _sprite = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::setSprite(const Common::String &filename) {
+ if (_sprite && _sprite->getFilename() && scumm_stricmp(filename.c_str(), _sprite->getFilename()) == 0) {
+ _sprite->reset();
+ return STATUS_OK;
+ }
+
+ delete _sprite;
+ _sprite = NULL;
+
+ SystemClassRegistry::getInstance()->_disabled = true;
+ _sprite = new BaseSprite(_gameRef, (BaseObject*)_gameRef);
+ if (_sprite && DID_SUCCEED(_sprite->loadFile(filename))) {
+ SystemClassRegistry::getInstance()->_disabled = false;
+ return STATUS_OK;
+ } else {
+ delete _sprite;
+ _sprite = NULL;
+ SystemClassRegistry::getInstance()->_disabled = false;
+ return STATUS_FAILED;
+ }
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::update(PartEmitter *emitter, uint32 currentTime, uint32 timerDelta) {
+ if (_state == PARTICLE_FADEIN) {
+ if (currentTime - _fadeStart >= (uint32)_fadeTime) {
+ _state = PARTICLE_NORMAL;
+ _currentAlpha = _alpha1;
+ } else {
+ _currentAlpha = (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _alpha1);
+ }
+
+ return STATUS_OK;
+ } else if (_state == PARTICLE_FADEOUT) {
+ if (currentTime - _fadeStart >= (uint32)_fadeTime) {
+ _isDead = true;
+ return STATUS_OK;
+ } else {
+ _currentAlpha = _fadeStartAlpha - (int)(((float)currentTime - (float)_fadeStart) / (float)_fadeTime * _fadeStartAlpha);
+ }
+
+ return STATUS_OK;
+ } else {
+ // time is up
+ if (_lifeTime > 0) {
+ if (currentTime - _creationTime >= (uint32)_lifeTime) {
+ if (emitter->_fadeOutTime > 0) {
+ fadeOut(currentTime, emitter->_fadeOutTime);
+ } else {
+ _isDead = true;
+ }
+ }
+ }
+
+ // particle hit the border
+ if (!_isDead && !BasePlatform::isRectEmpty(&_border)) {
+ Point32 p;
+ p.x = (int32)_pos.x;
+ p.y = (int32)_pos.y;
+ if (!BasePlatform::ptInRect(&_border, p)) {
+ fadeOut(currentTime, emitter->_fadeOutTime);
+ }
+ }
+ if (_state != PARTICLE_NORMAL) {
+ return STATUS_OK;
+ }
+
+ // update alpha
+ if (_lifeTime > 0) {
+ int age = (int)(currentTime - _creationTime);
+ int alphaDelta = (int)(_alpha2 - _alpha1);
+
+ _currentAlpha = _alpha1 + (int)(((float)alphaDelta / (float)_lifeTime * (float)age));
+ }
+
+ // update position
+ float elapsedTime = (float)timerDelta / 1000.f;
+
+ for (uint32 i = 0; i < emitter->_forces.size(); i++) {
+ PartForce *force = emitter->_forces[i];
+ switch (force->_type) {
+ case PartForce::FORCE_GLOBAL:
+ _velocity += force->_direction * elapsedTime;
+ break;
+
+ case PartForce::FORCE_POINT: {
+ Vector2 vecDist = force->_pos - _pos;
+ float dist = fabs(vecDist.length());
+
+ dist = 100.0f / dist;
+
+ _velocity += force->_direction * dist * elapsedTime;
+ }
+ break;
+ }
+ }
+ _pos += _velocity * elapsedTime;
+
+ // update rotation
+ _rotation += _angVelocity * elapsedTime;
+ _rotation = BaseUtils::normalizeAngle(_rotation);
+
+ // update scale
+ if (_exponentialGrowth) {
+ _scale += _scale / 100.0f * _growthRate * elapsedTime;
+ } else {
+ _scale += _growthRate * elapsedTime;
+ }
+
+ if (_scale <= 0.0f) {
+ _isDead = true;
+ }
+
+
+ return STATUS_OK;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::display(PartEmitter *emitter) {
+ if (!_sprite) {
+ return STATUS_FAILED;
+ }
+ if (_isDead) {
+ return STATUS_OK;
+ }
+
+ _sprite->getCurrentFrame();
+ return _sprite->display((int)_pos.x, (int)_pos.y,
+ NULL,
+ _scale, _scale,
+ BYTETORGBA(255, 255, 255, _currentAlpha),
+ _rotation,
+ emitter->_blendMode);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::fadeIn(uint32 currentTime, int fadeTime) {
+ _currentAlpha = 0;
+ _fadeStart = currentTime;
+ _fadeTime = fadeTime;
+ _state = PARTICLE_FADEIN;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::fadeOut(uint32 currentTime, int fadeTime) {
+ //_currentAlpha = 255;
+ _fadeStartAlpha = _currentAlpha;
+ _fadeStart = currentTime;
+ _fadeTime = fadeTime;
+ _state = PARTICLE_FADEOUT;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool PartParticle::persist(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_alpha1));
+ persistMgr->transfer(TMEMBER(_alpha2));
+ persistMgr->transfer(TMEMBER(_border));
+ persistMgr->transfer(TMEMBER(_pos));
+ persistMgr->transfer(TMEMBER(_posZ));
+ persistMgr->transfer(TMEMBER(_velocity));
+ persistMgr->transfer(TMEMBER(_scale));
+ persistMgr->transfer(TMEMBER(_creationTime));
+ persistMgr->transfer(TMEMBER(_lifeTime));
+ persistMgr->transfer(TMEMBER(_isDead));
+ persistMgr->transfer(TMEMBER_INT(_state));
+ persistMgr->transfer(TMEMBER(_fadeStart));
+ persistMgr->transfer(TMEMBER(_fadeTime));
+ persistMgr->transfer(TMEMBER(_currentAlpha));
+ persistMgr->transfer(TMEMBER(_angVelocity));
+ persistMgr->transfer(TMEMBER(_rotation));
+ persistMgr->transfer(TMEMBER(_growthRate));
+ persistMgr->transfer(TMEMBER(_exponentialGrowth));
+ persistMgr->transfer(TMEMBER(_fadeStartAlpha));
+
+ if (persistMgr->getIsSaving()) {
+ const char *filename = _sprite->getFilename();
+ persistMgr->transfer(TMEMBER(filename));
+ } else {
+ char *filename;
+ persistMgr->transfer(TMEMBER(filename));
+ SystemClassRegistry::getInstance()->_disabled = true;
+ setSprite(filename);
+ SystemClassRegistry::getInstance()->_disabled = false;
+ delete[] filename;
+ filename = NULL;
+ }
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/particles/part_particle.h b/engines/wintermute/base/particles/part_particle.h
new file mode 100644
index 0000000000..4b8c2f131e
--- /dev/null
+++ b/engines/wintermute/base/particles/part_particle.h
@@ -0,0 +1,90 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_PARTPARTICLE_H
+#define WINTERMUTE_PARTPARTICLE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/math/rect32.h"
+#include "engines/wintermute/math/vector2.h"
+
+namespace Wintermute {
+
+class PartEmitter;
+class BaseSprite;
+class BasePersistenceManager;
+
+class PartParticle : public BaseClass {
+public:
+ enum TParticleState {
+ PARTICLE_NORMAL, PARTICLE_FADEIN, PARTICLE_FADEOUT
+ };
+
+ PartParticle(BaseGame *inGame);
+ virtual ~PartParticle(void);
+
+ float _growthRate;
+ bool _exponentialGrowth;
+
+ float _rotation;
+ float _angVelocity;
+
+ int _alpha1;
+ int _alpha2;
+
+ Rect32 _border;
+ Vector2 _pos;
+ float _posZ;
+ Vector2 _velocity;
+ float _scale;
+ BaseSprite *_sprite;
+ uint32 _creationTime;
+ int _lifeTime;
+ bool _isDead;
+ TParticleState _state;
+
+ bool update(PartEmitter *emitter, uint32 currentTime, uint32 timerDelta);
+ bool display(PartEmitter *emitter);
+
+ bool setSprite(const Common::String &filename);
+
+ bool fadeIn(uint32 currentTime, int fadeTime);
+ bool fadeOut(uint32 currentTime, int fadeTime);
+
+ bool persist(BasePersistenceManager *PersistMgr);
+private:
+ uint32 _fadeStart;
+ int _fadeTime;
+ int _currentAlpha;
+ int _fadeStartAlpha;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/saveload.cpp b/engines/wintermute/base/saveload.cpp
new file mode 100644
index 0000000000..06e9fd2565
--- /dev/null
+++ b/engines/wintermute/base/saveload.cpp
@@ -0,0 +1,203 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_persistence_manager.h"
+#include "engines/wintermute/wintermute.h"
+#include "engines/wintermute/base/saveload.h"
+#include "engines/wintermute/ad/ad_scene.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_game.h" // Temporary
+#include "engines/wintermute/base/base_region.h"
+#include "engines/wintermute/base/base_sub_frame.h"
+#include "engines/wintermute/base/font/base_font.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "common/savefile.h"
+#include "common/config-manager.h"
+
+namespace Wintermute {
+
+bool SaveLoad::loadGame(const Common::String &filename, BaseGame *gameRef) {
+ gameRef->LOG(0, "Loading game '%s'...", filename.c_str());
+
+ bool ret;
+
+ gameRef->_renderer->initSaveLoad(false);
+
+ gameRef->_loadInProgress = true;
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ if (DID_SUCCEED(ret = pm->initLoad(filename))) {
+ //if (DID_SUCCEED(ret = cleanup())) {
+ if (DID_SUCCEED(ret = SystemClassRegistry::getInstance()->loadTable(gameRef, pm))) {
+ if (DID_SUCCEED(ret = SystemClassRegistry::getInstance()->loadInstances(gameRef, pm))) {
+ // Restore random-seed:
+ BaseEngine::instance().getRandomSource()->setSeed(pm->getDWORD());
+
+ // data initialization after load
+ SaveLoad::initAfterLoad();
+
+ gameRef->applyEvent("AfterLoad", true);
+
+ gameRef->displayContent(true, false);
+ //_renderer->flip();
+ }
+ }
+ }
+
+ delete pm;
+ gameRef->_loadInProgress = false;
+
+ gameRef->_renderer->endSaveLoad();
+
+ //_gameRef->LOG(0, "Load end %d", BaseUtils::GetUsedMemMB());
+ // AdGame:
+ if (DID_SUCCEED(ret)) {
+ SystemClassRegistry::getInstance()->enumInstances(SaveLoad::afterLoadRegion, "AdRegion", NULL);
+ }
+ return ret;
+}
+
+bool SaveLoad::saveGame(int slot, const char *desc, bool quickSave, BaseGame *gameRef) {
+ Common::String filename = SaveLoad::getSaveSlotFilename(slot);
+
+ gameRef->LOG(0, "Saving game '%s'...", filename.c_str());
+
+ gameRef->applyEvent("BeforeSave", true);
+
+ bool ret;
+
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ if (DID_SUCCEED(ret = pm->initSave(desc))) {
+ gameRef->_renderer->initSaveLoad(true, quickSave); // TODO: The original code inited the indicator before the conditionals
+ if (DID_SUCCEED(ret = SystemClassRegistry::getInstance()->saveTable(gameRef, pm, quickSave))) {
+ if (DID_SUCCEED(ret = SystemClassRegistry::getInstance()->saveInstances(gameRef, pm, quickSave))) {
+ pm->putDWORD(BaseEngine::instance().getRandomSource()->getSeed());
+ if (DID_SUCCEED(ret = pm->saveFile(filename))) {
+ ConfMan.setInt("most_recent_saveslot", slot);
+ }
+ }
+ }
+ }
+
+ delete pm;
+
+ gameRef->_renderer->endSaveLoad();
+
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SaveLoad::initAfterLoad() {
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadRegion, "BaseRegion", NULL);
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadSubFrame, "BaseSubFrame", NULL);
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadSound, "BaseSound", NULL);
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadFont, "BaseFontTT", NULL);
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadScript, "ScScript", NULL);
+ // AdGame:
+ SystemClassRegistry::getInstance()->enumInstances(afterLoadScene, "AdScene", NULL);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadScene(void *scene, void *data) {
+ ((AdScene *)scene)->afterLoad();
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadRegion(void *region, void *data) {
+ ((BaseRegion *)region)->createRegion();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadSubFrame(void *subframe, void *data) {
+ ((BaseSubFrame *)subframe)->setSurfaceSimple();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadSound(void *sound, void *data) {
+ ((BaseSound *)sound)->setSoundSimple();
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadFont(void *font, void *data) {
+ ((BaseFont *)font)->afterLoad();
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SaveLoad::afterLoadScript(void *script, void *data) {
+ ((ScScript *)script)->afterLoad();
+}
+
+Common::String SaveLoad::getSaveSlotFilename(int slot) {
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ Common::String filename = pm->getFilenameForSlot(slot);
+ delete pm;
+ debugC(kWintermuteDebugSaveGame, "getSaveSlotFileName(%d) = %s", slot, filename.c_str());
+ return filename;
+}
+
+bool SaveLoad::getSaveSlotDescription(int slot, char *buffer) {
+ buffer[0] = '\0';
+
+ Common::String filename = getSaveSlotFilename(slot);
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ if (!pm) {
+ return false;
+ }
+
+ if (!(pm->initLoad(filename))) {
+ delete pm;
+ return false;
+ }
+
+ strcpy(buffer, pm->_savedDescription);
+ delete pm;
+
+ return true;
+}
+
+bool SaveLoad::isSaveSlotUsed(int slot) {
+ Common::String filename = getSaveSlotFilename(slot);
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ bool ret = pm->getSaveExists(slot);
+ delete pm;
+ return ret;
+}
+
+bool SaveLoad::emptySaveSlot(int slot) {
+ Common::String filename = getSaveSlotFilename(slot);
+ BasePersistenceManager *pm = new BasePersistenceManager();
+ ((WintermuteEngine *)g_engine)->getSaveFileMan()->removeSavefile(pm->getFilenameForSlot(slot));
+ delete pm;
+ return true;
+}
+
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/saveload.h b/engines/wintermute/base/saveload.h
new file mode 100644
index 0000000000..e448cc8814
--- /dev/null
+++ b/engines/wintermute/base/saveload.h
@@ -0,0 +1,57 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SAVEGAME_H
+#define WINTERMUTE_SAVEGAME_H
+
+#include "common/str.h"
+
+namespace Wintermute {
+class BaseGame;
+class SaveLoad {
+public:
+ static bool emptySaveSlot(int slot);
+ static bool isSaveSlotUsed(int slot);
+ static bool getSaveSlotDescription(int slot, char *buffer);
+ static Common::String getSaveSlotFilename(int slot);
+
+ static bool loadGame(const Common::String &filename, BaseGame *gameRef);
+ static bool saveGame(int slot, const char *desc, bool quickSave, BaseGame *gameRef);
+ static bool initAfterLoad();
+ static void afterLoadScene(void *scene, void *data);
+ static void afterLoadRegion(void *region, void *data);
+private:
+ static void afterLoadSubFrame(void *subframe, void *data);
+ static void afterLoadSound(void *sound, void *data);
+ static void afterLoadFont(void *font, void *data);
+ static void afterLoadScript(void *script, void *data);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/dcscript.h b/engines/wintermute/base/scriptables/dcscript.h
new file mode 100644
index 0000000000..4aae897dc2
--- /dev/null
+++ b/engines/wintermute/base/scriptables/dcscript.h
@@ -0,0 +1,141 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_DCSCRIPT_H
+#define WINTERMUTE_DCSCRIPT_H
+
+namespace Wintermute {
+
+#define SCRIPT_MAGIC 0xDEC0ADDE
+#define SCRIPT_VERSION 0x0102
+
+// value types
+typedef enum {
+ VAL_NULL,
+ VAL_STRING,
+ VAL_INT,
+ VAL_BOOL,
+ VAL_FLOAT,
+ VAL_OBJECT,
+ VAL_NATIVE,
+ VAL_VARIABLE_REF
+} TValType;
+
+
+// script states
+typedef enum {
+ SCRIPT_RUNNING,
+ SCRIPT_WAITING,
+ SCRIPT_SLEEPING,
+ SCRIPT_FINISHED,
+ SCRIPT_PERSISTENT,
+ SCRIPT_ERROR,
+ SCRIPT_PAUSED,
+ SCRIPT_WAITING_SCRIPT,
+ SCRIPT_THREAD_FINISHED
+} TScriptState;
+
+// opcodes
+typedef enum {
+ II_DEF_VAR = 0,
+ II_DEF_GLOB_VAR,
+ II_RET,
+ II_RET_EVENT,
+ II_CALL,
+ II_CALL_BY_EXP,
+ II_EXTERNAL_CALL,
+ II_SCOPE,
+ II_CORRECT_STACK,
+ II_CREATE_OBJECT,
+ II_POP_EMPTY,
+ II_PUSH_VAR,
+ II_PUSH_VAR_REF,
+ II_POP_VAR,
+ II_PUSH_VAR_THIS, // push current this on stack
+ II_PUSH_INT,
+ II_PUSH_BOOL,
+ II_PUSH_FLOAT,
+ II_PUSH_STRING,
+ II_PUSH_NULL,
+ II_PUSH_THIS_FROM_STACK,
+ II_PUSH_THIS,
+ II_POP_THIS,
+ II_PUSH_BY_EXP,
+ II_POP_BY_EXP,
+ II_JMP,
+ II_JMP_FALSE,
+ II_ADD,
+ II_SUB,
+ II_MUL,
+ II_DIV,
+ II_MODULO,
+ II_NOT,
+ II_AND,
+ II_OR,
+ II_CMP_EQ,
+ II_CMP_NE,
+ II_CMP_L,
+ II_CMP_G,
+ II_CMP_LE,
+ II_CMP_GE,
+ II_CMP_STRICT_EQ,
+ II_CMP_STRICT_NE,
+ II_DBG_LINE,
+ II_POP_REG1,
+ II_PUSH_REG1,
+ II_DEF_CONST_VAR
+} TInstruction;
+
+// external data types
+typedef enum {
+ TYPE_VOID = 0,
+ TYPE_BOOL,
+ TYPE_LONG,
+ TYPE_BYTE,
+ TYPE_STRING,
+ TYPE_FLOAT,
+ TYPE_DOUBLE,
+ TYPE_MEMBUFFER
+} TExternalType;
+
+
+// call types
+typedef enum {
+ CALL_STDCALL = 0,
+ CALL_CDECL,
+ CALL_THISCALL
+} TCallType;
+
+// element types
+typedef enum {
+ ELEMENT_STRING = 0
+} TElementType;
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script.cpp b/engines/wintermute/base/scriptables/script.cpp
new file mode 100644
index 0000000000..9469bd46a7
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script.cpp
@@ -0,0 +1,1467 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/scriptables/script_engine.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "common/memstream.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(ScScript, false)
+
+//////////////////////////////////////////////////////////////////////////
+ScScript::ScScript(BaseGame *inGame, ScEngine *engine) : BaseClass(inGame) {
+ _buffer = NULL;
+ _bufferSize = _iP = 0;
+ _scriptStream = NULL;
+ _filename = NULL;
+ _currentLine = 0;
+
+ _symbols = NULL;
+ _numSymbols = 0;
+
+ _engine = engine;
+
+ _globals = NULL;
+
+ _scopeStack = NULL;
+ _callStack = NULL;
+ _thisStack = NULL;
+ _stack = NULL;
+
+ _operand = NULL;
+ _reg1 = NULL;
+
+ _functions = NULL;
+ _numFunctions = 0;
+
+ _methods = NULL;
+ _numMethods = 0;
+
+ _events = NULL;
+ _numEvents = 0;
+
+ _externals = NULL;
+ _numExternals = 0;
+
+ _state = SCRIPT_FINISHED;
+ _origState = SCRIPT_FINISHED;
+
+ _waitObject = NULL;
+ _waitTime = 0;
+ _waitFrozen = false;
+ _waitScript = NULL;
+
+ _timeSlice = 0;
+
+ _thread = false;
+ _methodThread = false;
+ _threadEvent = NULL;
+
+ _freezable = true;
+ _owner = NULL;
+
+ _unbreakable = false;
+ _parentScript = NULL;
+
+ _tracingMode = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript::~ScScript() {
+ cleanup();
+}
+
+void ScScript::readHeader() {
+ uint32 oldPos = _scriptStream->pos();
+ _scriptStream->seek(0);
+ _header.magic = _scriptStream->readUint32LE();
+ _header.version = _scriptStream->readUint32LE();
+ _header.codeStart = _scriptStream->readUint32LE();
+ _header.funcTable = _scriptStream->readUint32LE();
+ _header.symbolTable = _scriptStream->readUint32LE();
+ _header.eventTable = _scriptStream->readUint32LE();
+ _header.externalsTable = _scriptStream->readUint32LE();
+ _header.methodTable = _scriptStream->readUint32LE();
+ _scriptStream->seek(oldPos);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::initScript() {
+ if (!_scriptStream) {
+ _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
+ }
+ readHeader();
+
+ if (_header.magic != SCRIPT_MAGIC) {
+ _gameRef->LOG(0, "File '%s' is not a valid compiled script", _filename);
+ cleanup();
+ return STATUS_FAILED;
+ }
+
+ if (_header.version > SCRIPT_VERSION) {
+ _gameRef->LOG(0, "Script '%s' has a wrong version %d.%d (expected %d.%d)", _filename, _header.version / 256, _header.version % 256, SCRIPT_VERSION / 256, SCRIPT_VERSION % 256);
+ cleanup();
+ return STATUS_FAILED;
+ }
+
+ initTables();
+
+ // init stacks
+ _scopeStack = new ScStack(_gameRef);
+ _callStack = new ScStack(_gameRef);
+ _thisStack = new ScStack(_gameRef);
+ _stack = new ScStack(_gameRef);
+
+ _operand = new ScValue(_gameRef);
+ _reg1 = new ScValue(_gameRef);
+
+
+ // skip to the beginning
+ _iP = _header.codeStart;
+ _scriptStream->seek(_iP);
+ _currentLine = 0;
+
+ // ready to rumble...
+ _state = SCRIPT_RUNNING;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::initTables() {
+ uint32 origIP = _iP;
+
+ readHeader();
+ // load symbol table
+ _iP = _header.symbolTable;
+
+ _numSymbols = getDWORD();
+ _symbols = new char*[_numSymbols];
+ for (uint32 i = 0; i < _numSymbols; i++) {
+ uint32 index = getDWORD();
+ _symbols[index] = getString();
+ }
+
+ // load functions table
+ _iP = _header.funcTable;
+
+ _numFunctions = getDWORD();
+ _functions = new TFunctionPos[_numFunctions];
+ for (uint32 i = 0; i < _numFunctions; i++) {
+ _functions[i].pos = getDWORD();
+ _functions[i].name = getString();
+ }
+
+
+ // load events table
+ _iP = _header.eventTable;
+
+ _numEvents = getDWORD();
+ _events = new TEventPos[_numEvents];
+ for (uint32 i = 0; i < _numEvents; i++) {
+ _events[i].pos = getDWORD();
+ _events[i].name = getString();
+ }
+
+
+ // load externals
+ if (_header.version >= 0x0101) {
+ _iP = _header.externalsTable;
+
+ _numExternals = getDWORD();
+ _externals = new TExternalFunction[_numExternals];
+ for (uint32 i = 0; i < _numExternals; i++) {
+ _externals[i].dll_name = getString();
+ _externals[i].name = getString();
+ _externals[i].call_type = (TCallType)getDWORD();
+ _externals[i].returns = (TExternalType)getDWORD();
+ _externals[i].nu_params = getDWORD();
+ if (_externals[i].nu_params > 0) {
+ _externals[i].params = new TExternalType[_externals[i].nu_params];
+ for (int j = 0; j < _externals[i].nu_params; j++) {
+ _externals[i].params[j] = (TExternalType)getDWORD();
+ }
+ }
+ }
+ }
+
+ // load method table
+ _iP = _header.methodTable;
+
+ _numMethods = getDWORD();
+ _methods = new TMethodPos[_numMethods];
+ for (uint32 i = 0; i < _numMethods; i++) {
+ _methods[i].pos = getDWORD();
+ _methods[i].name = getString();
+ }
+
+
+ _iP = origIP;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner) {
+ cleanup();
+
+ _thread = false;
+ _methodThread = false;
+
+ delete[] _threadEvent;
+ _threadEvent = NULL;
+
+ _filename = new char[strlen(filename) + 1];
+ if (_filename) {
+ strcpy(_filename, filename);
+ }
+
+ _buffer = new byte [size];
+ if (!_buffer) {
+ return STATUS_FAILED;
+ }
+
+ memcpy(_buffer, buffer, size);
+
+ _bufferSize = size;
+
+ bool res = initScript();
+ if (DID_FAIL(res)) {
+ return res;
+ }
+
+ // establish global variables table
+ _globals = new ScValue(_gameRef);
+
+ _owner = owner;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::createThread(ScScript *original, uint32 initIP, const Common::String &eventName) {
+ cleanup();
+
+ _thread = true;
+ _methodThread = false;
+ _threadEvent = new char[eventName.size() + 1];
+ if (_threadEvent) {
+ strcpy(_threadEvent, eventName.c_str());
+ }
+
+ // copy filename
+ _filename = new char[strlen(original->_filename) + 1];
+ if (_filename) {
+ strcpy(_filename, original->_filename);
+ }
+
+ // copy buffer
+ _buffer = new byte [original->_bufferSize];
+ if (!_buffer) {
+ return STATUS_FAILED;
+ }
+
+ memcpy(_buffer, original->_buffer, original->_bufferSize);
+ _bufferSize = original->_bufferSize;
+
+ // initialize
+ bool res = initScript();
+ if (DID_FAIL(res)) {
+ return res;
+ }
+
+ // copy globals
+ _globals = original->_globals;
+
+ // skip to the beginning of the event
+ _iP = initIP;
+ _scriptStream->seek(_iP);
+
+ _timeSlice = original->_timeSlice;
+ _freezable = original->_freezable;
+ _owner = original->_owner;
+
+ _engine = original->_engine;
+ _parentScript = original;
+
+ return STATUS_OK;
+}
+
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::createMethodThread(ScScript *original, const Common::String &methodName) {
+ uint32 ip = original->getMethodPos(methodName);
+ if (ip == 0) {
+ return STATUS_FAILED;
+ }
+
+ cleanup();
+
+ _thread = true;
+ _methodThread = true;
+ _threadEvent = new char[methodName.size() + 1];
+ if (_threadEvent) {
+ strcpy(_threadEvent, methodName.c_str());
+ }
+
+ // copy filename
+ _filename = new char[strlen(original->_filename) + 1];
+ if (_filename) {
+ strcpy(_filename, original->_filename);
+ }
+
+ // copy buffer
+ _buffer = new byte [original->_bufferSize];
+ if (!_buffer) {
+ return STATUS_FAILED;
+ }
+
+ memcpy(_buffer, original->_buffer, original->_bufferSize);
+ _bufferSize = original->_bufferSize;
+
+ // initialize
+ bool res = initScript();
+ if (DID_FAIL(res)) {
+ return res;
+ }
+
+ // copy globals
+ _globals = original->_globals;
+
+ // skip to the beginning of the event
+ _iP = ip;
+
+ _timeSlice = original->_timeSlice;
+ _freezable = original->_freezable;
+ _owner = original->_owner;
+
+ _engine = original->_engine;
+ _parentScript = original;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScScript::cleanup() {
+ if (_buffer) {
+ delete[] _buffer;
+ }
+ _buffer = NULL;
+
+ if (_filename) {
+ delete[] _filename;
+ }
+ _filename = NULL;
+
+ if (_symbols) {
+ delete[] _symbols;
+ }
+ _symbols = NULL;
+ _numSymbols = 0;
+
+ if (_globals && !_thread) {
+ delete _globals;
+ }
+ _globals = NULL;
+
+ delete _scopeStack;
+ _scopeStack = NULL;
+
+ delete _callStack;
+ _callStack = NULL;
+
+ delete _thisStack;
+ _thisStack = NULL;
+
+ delete _stack;
+ _stack = NULL;
+
+ if (_functions) {
+ delete[] _functions;
+ }
+ _functions = NULL;
+ _numFunctions = 0;
+
+ if (_methods) {
+ delete[] _methods;
+ }
+ _methods = NULL;
+ _numMethods = 0;
+
+ if (_events) {
+ delete[] _events;
+ }
+ _events = NULL;
+ _numEvents = 0;
+
+
+ if (_externals) {
+ for (uint32 i = 0; i < _numExternals; i++) {
+ if (_externals[i].nu_params > 0) {
+ delete[] _externals[i].params;
+ }
+ }
+ delete[] _externals;
+ }
+ _externals = NULL;
+ _numExternals = 0;
+
+ delete _operand;
+ delete _reg1;
+ _operand = NULL;
+ _reg1 = NULL;
+
+ delete[] _threadEvent;
+ _threadEvent = NULL;
+
+ _state = SCRIPT_FINISHED;
+
+ _waitObject = NULL;
+ _waitTime = 0;
+ _waitFrozen = false;
+ _waitScript = NULL;
+
+ _parentScript = NULL; // ref only
+
+ delete _scriptStream;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 ScScript::getDWORD() {
+ _scriptStream->seek((int32)_iP);
+ uint32 ret = _scriptStream->readUint32LE();
+ _iP += sizeof(uint32);
+// assert(oldRet == ret);
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+double ScScript::getFloat() {
+ _scriptStream->seek((int32)_iP);
+ byte buffer[8];
+ _scriptStream->read(buffer, 8);
+
+#ifdef SCUMM_BIG_ENDIAN
+ // TODO: For lack of a READ_LE_UINT64
+ SWAP(buffer[0], buffer[7]);
+ SWAP(buffer[1], buffer[6]);
+ SWAP(buffer[2], buffer[5]);
+ SWAP(buffer[3], buffer[4]);
+#endif
+
+ double ret = *(double *)(buffer);
+ _iP += 8; // Hardcode the double-size used originally.
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+char *ScScript::getString() {
+ char *ret = (char *)(_buffer + _iP);
+ while (*(char *)(_buffer + _iP) != '\0') {
+ _iP++;
+ }
+ _iP++; // string terminator
+ _scriptStream->seek(_iP);
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::executeInstruction() {
+ bool ret = STATUS_OK;
+
+ uint32 dw;
+ const char *str = NULL;
+
+ //ScValue* op = new ScValue(_gameRef);
+ _operand->cleanup();
+
+ ScValue *op1;
+ ScValue *op2;
+
+ uint32 inst = getDWORD();
+ switch (inst) {
+
+ case II_DEF_VAR:
+ _operand->setNULL();
+ dw = getDWORD();
+ if (_scopeStack->_sP < 0) {
+ _globals->setProp(_symbols[dw], _operand);
+ } else {
+ _scopeStack->getTop()->setProp(_symbols[dw], _operand);
+ }
+
+ break;
+
+ case II_DEF_GLOB_VAR:
+ case II_DEF_CONST_VAR: {
+ dw = getDWORD();
+ /* char *temp = _symbols[dw]; // TODO delete */
+ // only create global var if it doesn't exist
+ if (!_engine->_globals->propExists(_symbols[dw])) {
+ _operand->setNULL();
+ _engine->_globals->setProp(_symbols[dw], _operand, false, inst == II_DEF_CONST_VAR);
+ }
+ break;
+ }
+
+ case II_RET:
+ if (_scopeStack->_sP >= 0 && _callStack->_sP >= 0) {
+ _scopeStack->pop();
+ _iP = (uint32)_callStack->pop()->getInt();
+ } else {
+ if (_thread) {
+ _state = SCRIPT_THREAD_FINISHED;
+ } else {
+ if (_numEvents == 0 && _numMethods == 0) {
+ _state = SCRIPT_FINISHED;
+ } else {
+ _state = SCRIPT_PERSISTENT;
+ }
+ }
+ }
+
+ break;
+
+ case II_RET_EVENT:
+ _state = SCRIPT_FINISHED;
+ break;
+
+
+ case II_CALL:
+ dw = getDWORD();
+
+ _operand->setInt(_iP);
+ _callStack->push(_operand);
+
+ _iP = dw;
+
+ break;
+
+ case II_CALL_BY_EXP: {
+ // push var
+ // push string
+ str = _stack->pop()->getString();
+ char *methodName = new char[strlen(str) + 1];
+ strcpy(methodName, str);
+
+ ScValue *var = _stack->pop();
+ if (var->_type == VAL_VARIABLE_REF) {
+ var = var->_valRef;
+ }
+
+ bool res = STATUS_FAILED;
+ bool triedNative = false;
+
+ // we are already calling this method, try native
+ if (_thread && _methodThread && strcmp(methodName, _threadEvent) == 0 && var->_type == VAL_NATIVE && _owner == var->getNative()) {
+ triedNative = true;
+ res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
+ }
+
+ if (DID_FAIL(res)) {
+ if (var->isNative() && var->getNative()->canHandleMethod(methodName)) {
+ if (!_unbreakable) {
+ _waitScript = var->getNative()->invokeMethodThread(methodName);
+ if (!_waitScript) {
+ _stack->correctParams(0);
+ runtimeError("Error invoking method '%s'.", methodName);
+ _stack->pushNULL();
+ } else {
+ _state = SCRIPT_WAITING_SCRIPT;
+ _waitScript->copyParameters(_stack);
+ }
+ } else {
+ // can call methods in unbreakable mode
+ _stack->correctParams(0);
+ runtimeError("Cannot call method '%s'. Ignored.", methodName);
+ _stack->pushNULL();
+ }
+ delete[] methodName;
+ break;
+ }
+ /*
+ ScValue* val = var->getProp(MethodName);
+ if (val){
+ dw = GetFuncPos(val->getString());
+ if (dw==0){
+ TExternalFunction* f = GetExternal(val->getString());
+ if (f){
+ ExternalCall(_stack, _thisStack, f);
+ }
+ else{
+ // not an internal nor external, try for native function
+ _gameRef->ExternalCall(this, _stack, _thisStack, val->getString());
+ }
+ }
+ else{
+ _operand->setInt(_iP);
+ _callStack->Push(_operand);
+ _iP = dw;
+ }
+ }
+ */
+ else {
+ res = STATUS_FAILED;
+ if (var->_type == VAL_NATIVE && !triedNative) {
+ res = var->_valNative->scCallMethod(this, _stack, _thisStack, methodName);
+ }
+
+ if (DID_FAIL(res)) {
+ _stack->correctParams(0);
+ runtimeError("Call to undefined method '%s'. Ignored.", methodName);
+ _stack->pushNULL();
+ }
+ }
+ }
+ delete[] methodName;
+ }
+ break;
+
+ case II_EXTERNAL_CALL: {
+ uint32 symbolIndex = getDWORD();
+
+ TExternalFunction *f = getExternal(_symbols[symbolIndex]);
+ if (f) {
+ externalCall(_stack, _thisStack, f);
+ } else {
+ _gameRef->externalCall(this, _stack, _thisStack, _symbols[symbolIndex]);
+ }
+
+ break;
+ }
+ case II_SCOPE:
+ _operand->setNULL();
+ _scopeStack->push(_operand);
+ break;
+
+ case II_CORRECT_STACK:
+ dw = getDWORD(); // params expected
+ _stack->correctParams(dw);
+ break;
+
+ case II_CREATE_OBJECT:
+ _operand->setObject();
+ _stack->push(_operand);
+ break;
+
+ case II_POP_EMPTY:
+ _stack->pop();
+ break;
+
+ case II_PUSH_VAR: {
+ ScValue *var = getVar(_symbols[getDWORD()]);
+ if (false && /*var->_type==VAL_OBJECT ||*/ var->_type == VAL_NATIVE) {
+ _operand->setReference(var);
+ _stack->push(_operand);
+ } else {
+ _stack->push(var);
+ }
+ break;
+ }
+
+ case II_PUSH_VAR_REF: {
+ ScValue *var = getVar(_symbols[getDWORD()]);
+ _operand->setReference(var);
+ _stack->push(_operand);
+ break;
+ }
+
+ case II_POP_VAR: {
+ char *varName = _symbols[getDWORD()];
+ ScValue *var = getVar(varName);
+ if (var) {
+ ScValue *val = _stack->pop();
+ if (!val) {
+ runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
+ var->setNULL();
+ } else {
+ if (val->getType() == VAL_VARIABLE_REF) {
+ val = val->_valRef;
+ }
+ if (val->_type == VAL_NATIVE) {
+ var->setValue(val);
+ } else {
+ var->copy(val);
+ }
+ }
+ }
+
+ break;
+ }
+
+ case II_PUSH_VAR_THIS:
+ _stack->push(_thisStack->getTop());
+ break;
+
+ case II_PUSH_INT:
+ _stack->pushInt((int)getDWORD());
+ break;
+
+ case II_PUSH_FLOAT:
+ _stack->pushFloat(getFloat());
+ break;
+
+
+ case II_PUSH_BOOL:
+ _stack->pushBool(getDWORD() != 0);
+
+ break;
+
+ case II_PUSH_STRING:
+ _stack->pushString(getString());
+ break;
+
+ case II_PUSH_NULL:
+ _stack->pushNULL();
+ break;
+
+ case II_PUSH_THIS_FROM_STACK:
+ _operand->setReference(_stack->getTop());
+ _thisStack->push(_operand);
+ break;
+
+ case II_PUSH_THIS:
+ _operand->setReference(getVar(_symbols[getDWORD()]));
+ _thisStack->push(_operand);
+ break;
+
+ case II_POP_THIS:
+ _thisStack->pop();
+ break;
+
+ case II_PUSH_BY_EXP: {
+ str = _stack->pop()->getString();
+ ScValue *val = _stack->pop()->getProp(str);
+ if (val) {
+ _stack->push(val);
+ } else {
+ _stack->pushNULL();
+ }
+
+ break;
+ }
+
+ case II_POP_BY_EXP: {
+ str = _stack->pop()->getString();
+ ScValue *var = _stack->pop();
+ ScValue *val = _stack->pop();
+
+ if (val == NULL) {
+ runtimeError("Script stack corruption detected. Please report this script at WME bug reports forum.");
+ var->setNULL();
+ } else {
+ var->setProp(str, val);
+ }
+
+ break;
+ }
+
+ case II_PUSH_REG1:
+ _stack->push(_reg1);
+ break;
+
+ case II_POP_REG1:
+ _reg1->copy(_stack->pop());
+ break;
+
+ case II_JMP:
+ _iP = getDWORD();
+ break;
+
+ case II_JMP_FALSE: {
+ dw = getDWORD();
+ //if (!_stack->pop()->getBool()) _iP = dw;
+ ScValue *val = _stack->pop();
+ if (!val) {
+ runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
+ } else {
+ if (!val->getBool()) {
+ _iP = dw;
+ }
+ }
+ break;
+ }
+
+ case II_ADD:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ if (op1->isNULL() || op2->isNULL()) {
+ _operand->setNULL();
+ } else if (op1->getType() == VAL_STRING || op2->getType() == VAL_STRING) {
+ char *tempStr = new char [strlen(op1->getString()) + strlen(op2->getString()) + 1];
+ strcpy(tempStr, op1->getString());
+ strcat(tempStr, op2->getString());
+ _operand->setString(tempStr);
+ delete[] tempStr;
+ } else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
+ _operand->setInt(op1->getInt() + op2->getInt());
+ } else {
+ _operand->setFloat(op1->getFloat() + op2->getFloat());
+ }
+
+ _stack->push(_operand);
+
+ break;
+
+ case II_SUB:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ if (op1->isNULL() || op2->isNULL()) {
+ _operand->setNULL();
+ } else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
+ _operand->setInt(op1->getInt() - op2->getInt());
+ } else {
+ _operand->setFloat(op1->getFloat() - op2->getFloat());
+ }
+
+ _stack->push(_operand);
+
+ break;
+
+ case II_MUL:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ if (op1->isNULL() || op2->isNULL()) {
+ _operand->setNULL();
+ } else if (op1->getType() == VAL_INT && op2->getType() == VAL_INT) {
+ _operand->setInt(op1->getInt() * op2->getInt());
+ } else {
+ _operand->setFloat(op1->getFloat() * op2->getFloat());
+ }
+
+ _stack->push(_operand);
+
+ break;
+
+ case II_DIV:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ if (op2->getFloat() == 0.0f) {
+ runtimeError("Division by zero.");
+ }
+
+ if (op1->isNULL() || op2->isNULL() || op2->getFloat() == 0.0f) {
+ _operand->setNULL();
+ } else {
+ _operand->setFloat(op1->getFloat() / op2->getFloat());
+ }
+
+ _stack->push(_operand);
+
+ break;
+
+ case II_MODULO:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ if (op2->getInt() == 0) {
+ runtimeError("Division by zero.");
+ }
+
+ if (op1->isNULL() || op2->isNULL() || op2->getInt() == 0) {
+ _operand->setNULL();
+ } else {
+ _operand->setInt(op1->getInt() % op2->getInt());
+ }
+
+ _stack->push(_operand);
+
+ break;
+
+ case II_NOT:
+ op1 = _stack->pop();
+ //if (op1->isNULL()) _operand->setNULL();
+ if (op1->isNULL()) {
+ _operand->setBool(true);
+ } else {
+ _operand->setBool(!op1->getBool());
+ }
+ _stack->push(_operand);
+
+ break;
+
+ case II_AND:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+ if (op1 == NULL || op2 == NULL) {
+ runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
+ _operand->setBool(false);
+ } else {
+ _operand->setBool(op1->getBool() && op2->getBool());
+ }
+ _stack->push(_operand);
+ break;
+
+ case II_OR:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+ if (op1 == NULL || op2 == NULL) {
+ runtimeError("Script corruption detected. Did you use '=' instead of '==' for comparison?");
+ _operand->setBool(false);
+ } else {
+ _operand->setBool(op1->getBool() || op2->getBool());
+ }
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_EQ:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(false);
+ else if (op1->isNative() && op2->isNative()){
+ _operand->setBool(op1->getNative() == op2->getNative());
+ }
+ else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){
+ _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())==0);
+ }
+ else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() == op2->getFloat());
+ }
+ else{
+ _operand->setBool(op1->getInt() == op2->getInt());
+ }
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) == 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_NE:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if ((op1->isNULL() && !op2->isNULL()) || (!op1->isNULL() && op2->isNULL())) _operand->setBool(true);
+ else if (op1->isNative() && op2->isNative()){
+ _operand->setBool(op1->getNative() != op2->getNative());
+ }
+ else if (op1->getType()==VAL_STRING || op2->getType()==VAL_STRING){
+ _operand->setBool(scumm_stricmp(op1->getString(), op2->getString())!=0);
+ }
+ else if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() != op2->getFloat());
+ }
+ else{
+ _operand->setBool(op1->getInt() != op2->getInt());
+ }
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) != 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_L:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() < op2->getFloat());
+ }
+ else _operand->setBool(op1->getInt() < op2->getInt());
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) < 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_G:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() > op2->getFloat());
+ }
+ else _operand->setBool(op1->getInt() > op2->getInt());
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) > 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_LE:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() <= op2->getFloat());
+ }
+ else _operand->setBool(op1->getInt() <= op2->getInt());
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) <= 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_GE:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ /*
+ if (op1->getType()==VAL_FLOAT && op2->getType()==VAL_FLOAT){
+ _operand->setBool(op1->getFloat() >= op2->getFloat());
+ }
+ else _operand->setBool(op1->getInt() >= op2->getInt());
+ */
+
+ _operand->setBool(ScValue::compare(op1, op2) >= 0);
+ _stack->push(_operand);
+ break;
+
+ case II_CMP_STRICT_EQ:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ //_operand->setBool(op1->getType()==op2->getType() && op1->getFloat()==op2->getFloat());
+ _operand->setBool(ScValue::compareStrict(op1, op2) == 0);
+ _stack->push(_operand);
+
+ break;
+
+ case II_CMP_STRICT_NE:
+ op2 = _stack->pop();
+ op1 = _stack->pop();
+
+ //_operand->setBool(op1->getType()!=op2->getType() || op1->getFloat()!=op2->getFloat());
+ _operand->setBool(ScValue::compareStrict(op1, op2) != 0);
+ _stack->push(_operand);
+ break;
+
+ case II_DBG_LINE: {
+ int newLine = getDWORD();
+ if (newLine != _currentLine) {
+ _currentLine = newLine;
+ }
+ break;
+
+ }
+ default:
+ _gameRef->LOG(0, "Fatal: Invalid instruction %d ('%s', line %d, IP:0x%x)\n", inst, _filename, _currentLine, _iP - sizeof(uint32));
+ _state = SCRIPT_FINISHED;
+ ret = STATUS_FAILED;
+ } // switch(instruction)
+
+ //delete op;
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 ScScript::getFuncPos(const Common::String &name) {
+ for (uint32 i = 0; i < _numFunctions; i++) {
+ if (name == _functions[i].name) {
+ return _functions[i].pos;
+ }
+ }
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 ScScript::getMethodPos(const Common::String &name) {
+ for (uint32 i = 0; i < _numMethods; i++) {
+ if (name == _methods[i].name) {
+ return _methods[i].pos;
+ }
+ }
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScScript::getVar(char *name) {
+ ScValue *ret = NULL;
+
+ // scope locals
+ if (_scopeStack->_sP >= 0) {
+ if (_scopeStack->getTop()->propExists(name)) {
+ ret = _scopeStack->getTop()->getProp(name);
+ }
+ }
+
+ // script globals
+ if (ret == NULL) {
+ if (_globals->propExists(name)) {
+ ret = _globals->getProp(name);
+ }
+ }
+
+ // engine globals
+ if (ret == NULL) {
+ if (_engine->_globals->propExists(name)) {
+ ret = _engine->_globals->getProp(name);
+ }
+ }
+
+ if (ret == NULL) {
+ //RuntimeError("Variable '%s' is inaccessible in the current block. Consider changing the script.", name);
+ _gameRef->LOG(0, "Warning: variable '%s' is inaccessible in the current block. Consider changing the script (script:%s, line:%d)", name, _filename, _currentLine);
+ ScValue *val = new ScValue(_gameRef);
+ ScValue *scope = _scopeStack->getTop();
+ if (scope) {
+ scope->setProp(name, val);
+ ret = _scopeStack->getTop()->getProp(name);
+ } else {
+ _globals->setProp(name, val);
+ ret = _globals->getProp(name);
+ }
+ delete val;
+ }
+
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::waitFor(BaseObject *object) {
+ if (_unbreakable) {
+ runtimeError("Script cannot be interrupted.");
+ return STATUS_OK;
+ }
+
+ _state = SCRIPT_WAITING;
+ _waitObject = object;
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::waitForExclusive(BaseObject *object) {
+ _engine->resetObject(object);
+ return waitFor(object);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::sleep(uint32 duration) {
+ if (_unbreakable) {
+ runtimeError("Script cannot be interrupted.");
+ return STATUS_OK;
+ }
+
+ _state = SCRIPT_SLEEPING;
+ if (_gameRef->_state == GAME_FROZEN) {
+ _waitTime = g_system->getMillis() + duration;
+ _waitFrozen = true;
+ } else {
+ _waitTime = _gameRef->_timer + duration;
+ _waitFrozen = false;
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::finish(bool includingThreads) {
+ if (_state != SCRIPT_FINISHED && includingThreads) {
+ _state = SCRIPT_FINISHED;
+ finishThreads();
+ } else {
+ _state = SCRIPT_FINISHED;
+ }
+
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::run() {
+ _state = SCRIPT_RUNNING;
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////
+void ScScript::runtimeError(const char *fmt, ...) {
+ char buff[256];
+ va_list va;
+
+ va_start(va, fmt);
+ vsprintf(buff, fmt, va);
+ va_end(va);
+
+ _gameRef->LOG(0, "Runtime error. Script '%s', line %d", _filename, _currentLine);
+ _gameRef->LOG(0, " %s", buff);
+
+ if (!_gameRef->_suppressScriptErrors) {
+ _gameRef->quickMessage("Script runtime error. View log for details.");
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::persist(BasePersistenceManager *persistMgr) {
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ // buffer
+ if (persistMgr->getIsSaving()) {
+ if (_state != SCRIPT_PERSISTENT && _state != SCRIPT_FINISHED && _state != SCRIPT_THREAD_FINISHED) {
+ persistMgr->transfer(TMEMBER(_bufferSize));
+ persistMgr->putBytes(_buffer, _bufferSize);
+ } else {
+ // don't save idle/finished scripts
+ int bufferSize = 0;
+ persistMgr->transfer(TMEMBER(bufferSize));
+ }
+ } else {
+ persistMgr->transfer(TMEMBER(_bufferSize));
+ if (_bufferSize > 0) {
+ _buffer = new byte[_bufferSize];
+ persistMgr->getBytes(_buffer, _bufferSize);
+ _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
+ initTables();
+ } else {
+ _buffer = NULL;
+ _scriptStream = NULL;
+ }
+ }
+
+ persistMgr->transfer(TMEMBER(_callStack));
+ persistMgr->transfer(TMEMBER(_currentLine));
+ persistMgr->transfer(TMEMBER(_engine));
+ persistMgr->transfer(TMEMBER(_filename));
+ persistMgr->transfer(TMEMBER(_freezable));
+ persistMgr->transfer(TMEMBER(_globals));
+ persistMgr->transfer(TMEMBER(_iP));
+ persistMgr->transfer(TMEMBER(_scopeStack));
+ persistMgr->transfer(TMEMBER(_stack));
+ persistMgr->transfer(TMEMBER_INT(_state));
+ persistMgr->transfer(TMEMBER(_operand));
+ persistMgr->transfer(TMEMBER_INT(_origState));
+ persistMgr->transfer(TMEMBER(_owner));
+ persistMgr->transfer(TMEMBER(_reg1));
+ persistMgr->transfer(TMEMBER(_thread));
+ persistMgr->transfer(TMEMBER(_threadEvent));
+ persistMgr->transfer(TMEMBER(_thisStack));
+ persistMgr->transfer(TMEMBER(_timeSlice));
+ persistMgr->transfer(TMEMBER(_waitObject));
+ persistMgr->transfer(TMEMBER(_waitScript));
+ persistMgr->transfer(TMEMBER(_waitTime));
+ persistMgr->transfer(TMEMBER(_waitFrozen));
+
+ persistMgr->transfer(TMEMBER(_methodThread));
+ persistMgr->transfer(TMEMBER(_methodThread));
+ persistMgr->transfer(TMEMBER(_unbreakable));
+ persistMgr->transfer(TMEMBER(_parentScript));
+
+ if (!persistMgr->getIsSaving()) {
+ _tracingMode = false;
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript *ScScript::invokeEventHandler(const Common::String &eventName, bool unbreakable) {
+ //if (_state!=SCRIPT_PERSISTENT) return NULL;
+
+ uint32 pos = getEventPos(eventName);
+ if (!pos) {
+ return NULL;
+ }
+
+ ScScript *thread = new ScScript(_gameRef, _engine);
+ if (thread) {
+ bool ret = thread->createThread(this, pos, eventName);
+ if (DID_SUCCEED(ret)) {
+ thread->_unbreakable = unbreakable;
+ _engine->_scripts.add(thread);
+ return thread;
+ } else {
+ delete thread;
+ return NULL;
+ }
+ } else {
+ return NULL;
+ }
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 ScScript::getEventPos(const Common::String &name) {
+ for (int i = _numEvents - 1; i >= 0; i--) {
+ if (scumm_stricmp(name.c_str(), _events[i].name) == 0) {
+ return _events[i].pos;
+ }
+ }
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::canHandleEvent(const Common::String &eventName) {
+ return getEventPos(eventName) != 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::canHandleMethod(const Common::String &methodName) {
+ return getMethodPos(methodName) != 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::pause() {
+ if (_state == SCRIPT_PAUSED) {
+ _gameRef->LOG(0, "Attempting to pause a paused script ('%s', line %d)", _filename, _currentLine);
+ return STATUS_FAILED;
+ }
+
+ if (!_freezable || _state == SCRIPT_PERSISTENT) {
+ return STATUS_OK;
+ }
+
+ _origState = _state;
+ _state = SCRIPT_PAUSED;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::resume() {
+ if (_state != SCRIPT_PAUSED) {
+ return STATUS_OK;
+ }
+
+ _state = _origState;
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript::TExternalFunction *ScScript::getExternal(char *name) {
+ for (uint32 i = 0; i < _numExternals; i++) {
+ if (strcmp(name, _externals[i].name) == 0) {
+ return &_externals[i];
+ }
+ }
+ return NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function) {
+
+ _gameRef->LOG(0, "External functions are not supported on this platform.");
+ stack->correctParams(0);
+ stack->pushNULL();
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::copyParameters(ScStack *stack) {
+ int i;
+ int numParams = stack->pop()->getInt();
+ for (i = numParams - 1; i >= 0; i--) {
+ _stack->push(stack->getAt(i));
+ }
+ _stack->pushInt(numParams);
+
+ for (i = 0; i < numParams; i++) {
+ stack->pop();
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScScript::finishThreads() {
+ for (uint32 i = 0; i < _engine->_scripts.size(); i++) {
+ ScScript *scr = _engine->_scripts[i];
+ if (scr->_thread && scr->_state != SCRIPT_FINISHED && scr->_owner == _owner && scumm_stricmp(scr->_filename, _filename) == 0) {
+ scr->finish(true);
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// IWmeDebugScript interface implementation
+int ScScript::dbgGetLine() {
+ return _currentLine;
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *ScScript::dbgGetFilename() {
+ return _filename;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void ScScript::afterLoad() {
+ if (_buffer == NULL) {
+ byte *buffer = _engine->getCompiledScript(_filename, &_bufferSize);
+ if (!buffer) {
+ _gameRef->LOG(0, "Error reinitializing script '%s' after load. Script will be terminated.", _filename);
+ _state = SCRIPT_ERROR;
+ return;
+ }
+
+ _buffer = new byte [_bufferSize];
+ memcpy(_buffer, buffer, _bufferSize);
+
+ delete _scriptStream;
+ _scriptStream = new Common::MemoryReadStream(_buffer, _bufferSize);
+
+ initTables();
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script.h b/engines/wintermute/base/scriptables/script.h
new file mode 100644
index 0000000000..0616bce58a
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script.h
@@ -0,0 +1,174 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SCSCRIPT_H
+#define WINTERMUTE_SCSCRIPT_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
+#include "engines/wintermute/coll_templ.h"
+
+namespace Wintermute {
+class BaseScriptHolder;
+class BaseObject;
+class ScEngine;
+class ScStack;
+class ScScript : public BaseClass {
+public:
+ BaseArray<int> _breakpoints;
+ bool _tracingMode;
+
+ ScScript *_parentScript;
+ bool _unbreakable;
+ bool finishThreads();
+ bool copyParameters(ScStack *stack);
+
+ void afterLoad();
+private:
+ ScValue *_operand;
+ ScValue *_reg1;
+public:
+ bool _freezable;
+ bool resume();
+ bool pause();
+ bool canHandleEvent(const Common::String &eventName);
+ bool canHandleMethod(const Common::String &methodName);
+ bool createThread(ScScript *original, uint32 initIP, const Common::String &eventName);
+ bool createMethodThread(ScScript *original, const Common::String &methodName);
+ ScScript *invokeEventHandler(const Common::String &eventName, bool unbreakable = false);
+ uint32 _timeSlice;
+ DECLARE_PERSISTENT(ScScript, BaseClass)
+ void runtimeError(const char *fmt, ...);
+ bool run();
+ bool finish(bool includingThreads = false);
+ bool sleep(uint32 duration);
+ bool waitForExclusive(BaseObject *object);
+ bool waitFor(BaseObject *object);
+ uint32 _waitTime;
+ bool _waitFrozen;
+ BaseObject *_waitObject;
+ ScScript *_waitScript;
+ TScriptState _state;
+ TScriptState _origState;
+ ScValue *getVar(char *name);
+ uint32 getFuncPos(const Common::String &name);
+ uint32 getEventPos(const Common::String &name);
+ uint32 getMethodPos(const Common::String &name);
+ typedef struct {
+ uint32 magic;
+ uint32 version;
+ uint32 codeStart;
+ uint32 funcTable;
+ uint32 symbolTable;
+ uint32 eventTable;
+ uint32 externalsTable;
+ uint32 methodTable;
+ } TScriptHeader;
+
+ TScriptHeader _header;
+
+ typedef struct {
+ char *name;
+ uint32 pos;
+ } TFunctionPos;
+
+ typedef struct {
+ char *name;
+ uint32 pos;
+ } TMethodPos;
+
+ typedef struct {
+ char *name;
+ uint32 pos;
+ } TEventPos;
+
+ typedef struct {
+ char *name;
+ char *dll_name;
+ TCallType call_type;
+ TExternalType returns;
+ int nu_params;
+ TExternalType *params;
+ } TExternalFunction;
+
+
+ ScStack *_callStack;
+ ScStack *_thisStack;
+ ScStack *_scopeStack;
+ ScStack *_stack;
+ ScValue *_globals;
+ ScEngine *_engine;
+ int _currentLine;
+ bool executeInstruction();
+ char *getString();
+ uint32 getDWORD();
+ double getFloat();
+ void cleanup();
+ bool create(const char *filename, byte *buffer, uint32 size, BaseScriptHolder *owner);
+ uint32 _iP;
+private:
+ void readHeader();
+ uint32 _bufferSize;
+ byte *_buffer;
+public:
+ Common::SeekableReadStream *_scriptStream;
+ ScScript(BaseGame *inGame, ScEngine *engine);
+ virtual ~ScScript();
+ char *_filename;
+ bool _thread;
+ bool _methodThread;
+ char *_threadEvent;
+ BaseScriptHolder *_owner;
+ ScScript::TExternalFunction *getExternal(char *name);
+ bool externalCall(ScStack *stack, ScStack *thisStack, ScScript::TExternalFunction *function);
+private:
+ char **_symbols;
+ uint32 _numSymbols;
+ TFunctionPos *_functions;
+ TMethodPos *_methods;
+ TEventPos *_events;
+ uint32 _numExternals;
+ TExternalFunction *_externals;
+ uint32 _numFunctions;
+ uint32 _numMethods;
+ uint32 _numEvents;
+
+ bool initScript();
+ bool initTables();
+
+
+// IWmeDebugScript interface implementation
+public:
+ virtual int dbgGetLine();
+ virtual const char *dbgGetFilename();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_engine.cpp b/engines/wintermute/base/scriptables/script_engine.cpp
new file mode 100644
index 0000000000..20e2ccadd1
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_engine.cpp
@@ -0,0 +1,610 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_engine.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_ext_math.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/utils.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(ScEngine, true)
+
+#define COMPILER_DLL "dcscomp.dll"
+//////////////////////////////////////////////////////////////////////////
+ScEngine::ScEngine(BaseGame *inGame) : BaseClass(inGame) {
+ _gameRef->LOG(0, "Initializing scripting engine...");
+
+ if (_compilerAvailable) {
+ _gameRef->LOG(0, " Script compiler bound successfuly");
+ } else {
+ _gameRef->LOG(0, " Script compiler is NOT available");
+ }
+
+ _globals = new ScValue(_gameRef);
+
+
+ // register 'Game' as global variable
+ if (!_globals->propExists("Game")) {
+ ScValue val(_gameRef);
+ val.setNative(_gameRef, true);
+ _globals->setProp("Game", &val);
+ }
+
+ // register 'Math' as global variable
+ if (!_globals->propExists("Math")) {
+ ScValue val(_gameRef);
+ val.setNative(_gameRef->_mathClass, true);
+ _globals->setProp("Math", &val);
+ }
+
+ // prepare script cache
+ for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
+ _cachedScripts[i] = NULL;
+ }
+
+ _currentScript = NULL;
+
+ _isProfiling = false;
+ _profilingStartTime = 0;
+
+ //EnableProfiling();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScEngine::~ScEngine() {
+ _gameRef->LOG(0, "Shutting down scripting engine");
+
+ disableProfiling();
+
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::cleanup() {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (!_scripts[i]->_thread && _scripts[i]->_owner) {
+ _scripts[i]->_owner->removeScript(_scripts[i]);
+ }
+ delete _scripts[i];
+ _scripts.remove_at(i);
+ i--;
+ }
+
+ _scripts.clear();
+
+ delete _globals;
+ _globals = NULL;
+
+ emptyScriptCache();
+
+ _currentScript = NULL; // ref only
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+byte *ScEngine::loadFile(void *data, char *filename, uint32 *size) {
+ return BaseFileManager::getEngineInstance()->readWholeFile(filename, size);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::closeFile(void *data, byte *buffer) {
+ delete[] buffer;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::parseElement(void *data, int line, int type, void *elementData) {
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScScript *ScEngine::runScript(const char *filename, BaseScriptHolder *owner) {
+ byte *compBuffer;
+ uint32 compSize;
+
+ // get script from cache
+ compBuffer = getCompiledScript(filename, &compSize);
+ if (!compBuffer) {
+ return NULL;
+ }
+
+ // add new script
+ ScScript *script = new ScScript(_gameRef, this);
+ bool ret = script->create(filename, compBuffer, compSize, owner);
+ if (DID_FAIL(ret)) {
+ _gameRef->LOG(ret, "Error running script '%s'...", filename);
+ delete script;
+ return NULL;
+ } else {
+ // publish the "self" pseudo-variable
+ ScValue val(_gameRef);
+ if (owner) {
+ val.setNative(owner, true);
+ } else {
+ val.setNULL();
+ }
+
+ script->_globals->setProp("self", &val);
+ script->_globals->setProp("this", &val);
+
+ _scripts.add(script);
+
+ return script;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+byte *ScEngine::getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache) {
+ // is script in cache?
+ if (!ignoreCache) {
+ for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
+ if (_cachedScripts[i] && scumm_stricmp(_cachedScripts[i]->_filename.c_str(), filename) == 0) {
+ _cachedScripts[i]->_timestamp = g_system->getMillis();
+ *outSize = _cachedScripts[i]->_size;
+ return _cachedScripts[i]->_buffer;
+ }
+ }
+ }
+
+ // nope, load it
+ byte *compBuffer;
+ uint32 compSize;
+
+ uint32 size;
+
+ byte *buffer = BaseEngine::instance().getFileManager()->readWholeFile(filename, &size);
+ if (!buffer) {
+ _gameRef->LOG(0, "ScEngine::GetCompiledScript - error opening script '%s'", filename);
+ return NULL;
+ }
+
+ // needs to be compiled?
+ if (FROM_LE_32(*(uint32 *)buffer) == SCRIPT_MAGIC) {
+ compBuffer = buffer;
+ compSize = size;
+ } else {
+ if (!_compilerAvailable) {
+ _gameRef->LOG(0, "ScEngine::GetCompiledScript - script '%s' needs to be compiled but compiler is not available", filename);
+ delete[] buffer;
+ return NULL;
+ }
+ // This code will never be called, since _compilerAvailable is const false.
+ // It's only here in the event someone would want to reinclude the compiler.
+ error("Script needs compilation, ScummVM does not contain a WME compiler");
+ }
+
+ byte *ret = NULL;
+
+ // add script to cache
+ CScCachedScript *cachedScript = new CScCachedScript(filename, compBuffer, compSize);
+ if (cachedScript) {
+ int index = 0;
+ uint32 minTime = g_system->getMillis();
+ for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
+ if (_cachedScripts[i] == NULL) {
+ index = i;
+ break;
+ } else if (_cachedScripts[i]->_timestamp <= minTime) {
+ minTime = _cachedScripts[i]->_timestamp;
+ index = i;
+ }
+ }
+
+ if (_cachedScripts[index] != NULL) {
+ delete _cachedScripts[index];
+ }
+ _cachedScripts[index] = cachedScript;
+
+ ret = cachedScript->_buffer;
+ *outSize = cachedScript->_size;
+ }
+
+
+ // cleanup
+ delete[] buffer;
+
+ return ret;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::tick() {
+ if (_scripts.size() == 0) {
+ return STATUS_OK;
+ }
+
+
+ // resolve waiting scripts
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+
+ switch (_scripts[i]->_state) {
+ case SCRIPT_WAITING: {
+ /*
+ bool obj_found=false;
+ for(int j=0; j<_gameRef->_regObjects.size(); j++)
+ {
+ if (_gameRef->_regObjects[j] == _scripts[i]->_waitObject)
+ {
+ if (_gameRef->_regObjects[j]->IsReady()) _scripts[i]->Run();
+ obj_found = true;
+ break;
+ }
+ }
+ if (!obj_found) _scripts[i]->finish(); // _waitObject no longer exists
+ */
+ if (_gameRef->validObject(_scripts[i]->_waitObject)) {
+ if (_scripts[i]->_waitObject->isReady()) {
+ _scripts[i]->run();
+ }
+ } else {
+ _scripts[i]->finish();
+ }
+ break;
+ }
+
+ case SCRIPT_SLEEPING: {
+ if (_scripts[i]->_waitFrozen) {
+ if (_scripts[i]->_waitTime <= g_system->getMillis()) {
+ _scripts[i]->run();
+ }
+ } else {
+ if (_scripts[i]->_waitTime <= _gameRef->_timer) {
+ _scripts[i]->run();
+ }
+ }
+ break;
+ }
+
+ case SCRIPT_WAITING_SCRIPT: {
+ if (!isValidScript(_scripts[i]->_waitScript) || _scripts[i]->_waitScript->_state == SCRIPT_ERROR) {
+ // fake return value
+ _scripts[i]->_stack->pushNULL();
+ _scripts[i]->_waitScript = NULL;
+ _scripts[i]->run();
+ } else {
+ if (_scripts[i]->_waitScript->_state == SCRIPT_THREAD_FINISHED) {
+ // copy return value
+ _scripts[i]->_stack->push(_scripts[i]->_waitScript->_stack->pop());
+ _scripts[i]->run();
+ _scripts[i]->_waitScript->finish();
+ _scripts[i]->_waitScript = NULL;
+ }
+ }
+ break;
+ }
+ default:
+ break;
+ } // switch
+ } // for each script
+
+
+ // execute scripts
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+
+ // skip paused scripts
+ if (_scripts[i]->_state == SCRIPT_PAUSED) {
+ continue;
+ }
+
+ // time sliced script
+ if (_scripts[i]->_timeSlice > 0) {
+ uint32 startTime = g_system->getMillis();
+ while (_scripts[i]->_state == SCRIPT_RUNNING && g_system->getMillis() - startTime < _scripts[i]->_timeSlice) {
+ _currentScript = _scripts[i];
+ _scripts[i]->executeInstruction();
+ }
+ if (_isProfiling && _scripts[i]->_filename) {
+ addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime);
+ }
+ }
+
+ // normal script
+ else {
+ uint32 startTime = 0;
+ bool isProfiling = _isProfiling;
+ if (isProfiling) {
+ startTime = g_system->getMillis();
+ }
+
+ while (_scripts[i]->_state == SCRIPT_RUNNING) {
+ _currentScript = _scripts[i];
+ _scripts[i]->executeInstruction();
+ }
+ if (isProfiling && _scripts[i]->_filename) {
+ addScriptTime(_scripts[i]->_filename, g_system->getMillis() - startTime);
+ }
+ }
+ _currentScript = NULL;
+ }
+
+ removeFinishedScripts();
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::tickUnbreakable() {
+ // execute unbreakable scripts
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (!_scripts[i]->_unbreakable) {
+ continue;
+ }
+
+ while (_scripts[i]->_state == SCRIPT_RUNNING) {
+ _currentScript = _scripts[i];
+ _scripts[i]->executeInstruction();
+ }
+ _scripts[i]->finish();
+ _currentScript = NULL;
+ }
+ removeFinishedScripts();
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::removeFinishedScripts() {
+ // remove finished scripts
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR) {
+ if (!_scripts[i]->_thread && _scripts[i]->_owner) {
+ _scripts[i]->_owner->removeScript(_scripts[i]);
+ }
+
+ delete _scripts[i];
+ _scripts.remove_at(i);
+ i--;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int ScEngine::getNumScripts(int *running, int *waiting, int *persistent) {
+ int numRunning = 0, numWaiting = 0, numPersistent = 0, numTotal = 0;
+
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i]->_state == SCRIPT_FINISHED) {
+ continue;
+ }
+ switch (_scripts[i]->_state) {
+ case SCRIPT_RUNNING:
+ case SCRIPT_SLEEPING:
+ case SCRIPT_PAUSED:
+ numRunning++;
+ break;
+ case SCRIPT_WAITING:
+ numWaiting++;
+ break;
+ case SCRIPT_PERSISTENT:
+ numPersistent++;
+ break;
+ default:
+ warning("ScEngine::GetNumScripts - unhandled enum");
+ break;
+ }
+ numTotal++;
+ }
+ if (running) {
+ *running = numRunning;
+ }
+ if (waiting) {
+ *waiting = numWaiting;
+ }
+ if (persistent) {
+ *persistent = numPersistent;
+ }
+
+ return numTotal;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::emptyScriptCache() {
+ for (int i = 0; i < MAX_CACHED_SCRIPTS; i++) {
+ if (_cachedScripts[i]) {
+ delete _cachedScripts[i];
+ _cachedScripts[i] = NULL;
+ }
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::resetObject(BaseObject *Object) {
+ // terminate all scripts waiting for this object
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i]->_state == SCRIPT_WAITING && _scripts[i]->_waitObject == Object) {
+ if (!_gameRef->_compatKillMethodThreads) {
+ resetScript(_scripts[i]);
+ }
+
+ bool isThread = _scripts[i]->_methodThread || _scripts[i]->_thread;
+ _scripts[i]->finish(!isThread); // 1.9b1 - top-level script kills its threads as well
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::resetScript(ScScript *script) {
+ // terminate all scripts waiting for this script
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i]->_state == SCRIPT_WAITING_SCRIPT && _scripts[i]->_waitScript == script) {
+ _scripts[i]->finish();
+ }
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::persist(BasePersistenceManager *persistMgr) {
+ if (!persistMgr->getIsSaving()) {
+ cleanup();
+ }
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+ persistMgr->transfer(TMEMBER(_currentScript));
+ persistMgr->transfer(TMEMBER(_globals));
+ _scripts.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::editorCleanup() {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i]->_owner == NULL && (_scripts[i]->_state == SCRIPT_FINISHED || _scripts[i]->_state == SCRIPT_ERROR)) {
+ delete _scripts[i];
+ _scripts.remove_at(i);
+ i--;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::pauseAll() {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i] != _currentScript) {
+ _scripts[i]->pause();
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::resumeAll() {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ _scripts[i]->resume();
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::isValidScript(ScScript *script) {
+ for (uint32 i = 0; i < _scripts.size(); i++) {
+ if (_scripts[i] == script) {
+ return true;
+ }
+ }
+ return false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScEngine::clearGlobals(bool includingNatives) {
+ _globals->CleanProps(includingNatives);
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::addScriptTime(const char *filename, uint32 time) {
+ if (!_isProfiling) {
+ return;
+ }
+
+ AnsiString fileName = filename;
+ fileName.toLowercase();
+ _scriptTimes[fileName] += time;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::enableProfiling() {
+ if (_isProfiling) {
+ return;
+ }
+
+ // destroy old data, if any
+ _scriptTimes.clear();
+
+ _profilingStartTime = g_system->getMillis();
+ _isProfiling = true;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::disableProfiling() {
+ if (!_isProfiling) {
+ return;
+ }
+
+ dumpStats();
+ _isProfiling = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScEngine::dumpStats() {
+ error("DumpStats not ported to ScummVM yet");
+ /* uint32 totalTime = g_system->getMillis() - _profilingStartTime;
+
+ typedef std::vector <std::pair<uint32, std::string> > TimeVector;
+ TimeVector times;
+
+ ScriptTimes::iterator it;
+ for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) {
+ times.push_back(std::pair<uint32, std::string> (it->_value, it->_key));
+ }
+ std::sort(times.begin(), times.end());
+
+
+ TimeVector::reverse_iterator tit;
+
+ _gameRef->LOG(0, "***** Script profiling information: *****");
+ _gameRef->LOG(0, " %-40s %fs", "Total execution time", (float)totalTime / 1000);
+
+ for (tit = times.rbegin(); tit != times.rend(); ++tit) {
+ _gameRef->LOG(0, " %-40s %fs (%f%%)", tit->second.c_str(), (float)tit->first / 1000, (float)tit->first / (float)totalTime * 100);
+ }*/
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_engine.h b/engines/wintermute/base/scriptables/script_engine.h
new file mode 100644
index 0000000000..1a023326eb
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_engine.h
@@ -0,0 +1,135 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SCENGINE_H
+#define WINTERMUTE_SCENGINE_H
+
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/base/base.h"
+
+namespace Wintermute {
+
+#define MAX_CACHED_SCRIPTS 20
+class ScScript;
+class ScValue;
+class BaseObject;
+class BaseScriptHolder;
+class ScEngine : public BaseClass {
+public:
+ class CScCachedScript {
+ public:
+ CScCachedScript(const char *filename, byte *buffer, uint32 size) {
+ _timestamp = g_system->getMillis();
+ _buffer = new byte[size];
+ if (_buffer) {
+ memcpy(_buffer, buffer, size);
+ }
+ _size = size;
+ _filename = filename;
+ };
+
+ ~CScCachedScript() {
+ if (_buffer) {
+ delete[] _buffer;
+ }
+ };
+
+ uint32 _timestamp;
+ byte *_buffer;
+ uint32 _size;
+ Common::String _filename;
+ };
+
+ class CScBreakpoint {
+ public:
+ CScBreakpoint(const char *filename) {
+ _filename = filename;
+ }
+
+ ~CScBreakpoint() {
+ _lines.clear();
+ }
+
+ Common::String _filename;
+ BaseArray<int> _lines;
+ };
+
+public:
+ bool clearGlobals(bool includingNatives = false);
+ bool tickUnbreakable();
+ bool removeFinishedScripts();
+ bool isValidScript(ScScript *script);
+
+ ScScript *_currentScript;
+ bool resumeAll();
+ bool pauseAll();
+ void editorCleanup();
+ bool resetObject(BaseObject *Object);
+ bool resetScript(ScScript *script);
+ bool emptyScriptCache();
+ byte *getCompiledScript(const char *filename, uint32 *outSize, bool ignoreCache = false);
+ DECLARE_PERSISTENT(ScEngine, BaseClass)
+ bool cleanup();
+ int getNumScripts(int *running = NULL, int *waiting = NULL, int *persistent = NULL);
+ bool tick();
+ ScValue *_globals;
+ ScScript *runScript(const char *filename, BaseScriptHolder *owner = NULL);
+ static const bool _compilerAvailable = false;
+
+ ScEngine(BaseGame *inGame);
+ virtual ~ScEngine();
+ static byte *loadFile(void *data, char *filename, uint32 *size);
+ static void closeFile(void *data, byte *buffer);
+ static void parseElement(void *data, int line, int type, void *elementData);
+
+ BaseArray<ScScript *> _scripts;
+
+ void enableProfiling();
+ void disableProfiling();
+ bool getIsProfiling() {
+ return _isProfiling;
+ }
+
+ void addScriptTime(const char *filename, uint32 Time);
+ void dumpStats();
+
+private:
+
+ CScCachedScript *_cachedScripts[MAX_CACHED_SCRIPTS];
+ bool _isProfiling;
+ uint32 _profilingStartTime;
+
+ typedef Common::HashMap<Common::String, uint32> ScriptTimes;
+ ScriptTimes _scriptTimes;
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_array.cpp b/engines/wintermute/base/scriptables/script_ext_array.cpp
new file mode 100644
index 0000000000..5ed07f0da6
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_array.cpp
@@ -0,0 +1,252 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/system/sys_instance.h"
+#include "engines/wintermute/base/scriptables/script_ext_array.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(SXArray, false)
+
+BaseScriptable *makeSXArray(BaseGame *inGame, ScStack *stack) {
+ return new SXArray(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXArray::SXArray(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
+ _length = 0;
+ _values = new ScValue(_gameRef);
+
+ int numParams = stack->pop()->getInt(0);
+
+ if (numParams == 1) {
+ _length = stack->pop()->getInt(0);
+ } else if (numParams > 1) {
+ _length = numParams;
+ char paramName[20];
+ for (int i = 0; i < numParams; i++) {
+ sprintf(paramName, "%d", i);
+ _values->setProp(paramName, stack->pop());
+ }
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXArray::SXArray(BaseGame *inGame) : BaseScriptable(inGame) {
+ _length = 0;
+ _values = new ScValue(_gameRef);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXArray::~SXArray() {
+ delete _values;
+ _values = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *SXArray::scToString() {
+ char dummy[32768];
+ strcpy(dummy, "");
+ char propName[20];
+ for (int i = 0; i < _length; i++) {
+ sprintf(propName, "%d", i);
+ ScValue *val = _values->getProp(propName);
+ if (val) {
+ if (strlen(dummy) + strlen(val->getString()) < 32768) {
+ strcat(dummy, val->getString());
+ }
+ }
+
+ if (i < _length - 1 && strlen(dummy) + 1 < 32768) {
+ strcat(dummy, ",");
+ }
+ }
+ _strRep = dummy;
+ return _strRep.c_str();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXArray::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // Push
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Push") == 0) {
+ int numParams = stack->pop()->getInt(0);
+ char paramName[20];
+
+ for (int i = 0; i < numParams; i++) {
+ _length++;
+ sprintf(paramName, "%d", _length - 1);
+ _values->setProp(paramName, stack->pop(), true);
+ }
+ stack->pushInt(_length);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Pop
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Pop") == 0) {
+
+ stack->correctParams(0);
+
+ if (_length > 0) {
+ char paramName[20];
+ sprintf(paramName, "%d", _length - 1);
+ stack->push(_values->getProp(paramName));
+ _values->deleteProp(paramName);
+ _length--;
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXArray::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("array");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Length
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Length") == 0) {
+ _scValue->setInt(_length);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // [number]
+ //////////////////////////////////////////////////////////////////////////
+ else {
+ char paramName[20];
+ if (validNumber(name, paramName)) {
+ return _values->getProp(paramName);
+ } else {
+ return _scValue;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXArray::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Length
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Length") == 0) {
+ int origLength = _length;
+ _length = MAX(value->getInt(0), 0);
+
+ char propName[20];
+ if (_length < origLength) {
+ for (int i = _length; i < origLength; i++) {
+ sprintf(propName, "%d", i);
+ _values->deleteProp(propName);
+ }
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // [number]
+ //////////////////////////////////////////////////////////////////////////
+ else {
+ char paramName[20];
+ if (validNumber(name, paramName)) {
+ int index = atoi(paramName);
+ if (index >= _length) {
+ _length = index + 1;
+ }
+ return _values->setProp(paramName, value);
+ } else {
+ return STATUS_FAILED;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXArray::persist(BasePersistenceManager *persistMgr) {
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_length));
+ persistMgr->transfer(TMEMBER(_values));
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXArray::validNumber(const char *origStr, char *outStr) {
+ bool isNumber = true;
+ for (uint32 i = 0; i < strlen(origStr); i++) {
+ if (!(origStr[i] >= '0' && origStr[i] <= '9')) {
+ isNumber = false;
+ break;
+ }
+ }
+
+ if (isNumber) {
+ int index = atoi(origStr);
+ sprintf(outStr, "%d", index);
+ return true;
+ } else {
+ return false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SXArray::push(ScValue *val) {
+ char paramName[20];
+ _length++;
+ sprintf(paramName, "%d", _length - 1);
+ _values->setProp(paramName, val, true);
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_array.h b/engines/wintermute/base/scriptables/script_ext_array.h
new file mode 100644
index 0000000000..d9805ef94f
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_array.h
@@ -0,0 +1,56 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXARRAY_H
+#define WINTERMUTE_SXARRAY_H
+
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class SXArray : public BaseScriptable {
+public:
+ bool push(ScValue *val);
+ bool validNumber(const char *origStr, char *outStr);
+ DECLARE_PERSISTENT(SXArray, BaseScriptable)
+ SXArray(BaseGame *inGame, ScStack *stack);
+ SXArray(BaseGame *inGame);
+ virtual ~SXArray();
+ ScValue *scGetProperty(const char *name);
+ bool scSetProperty(const char *name, ScValue *value);
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ const char *scToString();
+private:
+ int _length;
+ ScValue *_values;
+ Common::String _strRep;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_date.cpp b/engines/wintermute/base/scriptables/script_ext_date.cpp
new file mode 100644
index 0000000000..11eead3b9c
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_date.cpp
@@ -0,0 +1,293 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_ext_date.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(SXDate, false)
+
+BaseScriptable *makeSXDate(BaseGame *inGame, ScStack *stack) {
+ return new SXDate(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXDate::SXDate(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
+ stack->correctParams(6);
+
+ memset(&_tm, 0, sizeof(_tm));
+
+ ScValue *valYear = stack->pop();
+ _tm.tm_year = valYear->getInt() - 1900;
+ _tm.tm_mon = stack->pop()->getInt() - 1;
+ _tm.tm_mday = stack->pop()->getInt();
+ _tm.tm_hour = stack->pop()->getInt();
+ _tm.tm_min = stack->pop()->getInt();
+ _tm.tm_sec = stack->pop()->getInt();
+
+ if (valYear->isNULL()) {
+ g_system->getTimeAndDate(_tm);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXDate::~SXDate() {
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *SXDate::scToString() {
+ // TODO: Make this more stringy, and less ISO 8601-like
+ _strRep.format("%04d-%02d-%02d - %02d:%02d:%02d", _tm.tm_year, _tm.tm_mon, _tm.tm_mday, _tm.tm_hour, _tm.tm_min, _tm.tm_sec);
+ return _strRep.c_str();
+ //return asctime(&_tm);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXDate::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // GetYear
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "GetYear") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_year + 1900);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetMonth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMonth") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_mon + 1);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetDate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetDate") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_mday);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetHours
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetHours") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_hour);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetMinutes
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetMinutes") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_min);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetSeconds
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetSeconds") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_sec);
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // GetWeekday
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetWeekday") == 0) {
+ stack->correctParams(0);
+ stack->pushInt(_tm.tm_wday);
+ return STATUS_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetYear
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetYear") == 0) {
+ stack->correctParams(1);
+ _tm.tm_year = stack->pop()->getInt() - 1900;
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetMonth
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMonth") == 0) {
+ stack->correctParams(1);
+ _tm.tm_mon = stack->pop()->getInt() - 1;
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetDate
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetDate") == 0) {
+ stack->correctParams(1);
+ _tm.tm_mday = stack->pop()->getInt();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetHours
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetHours") == 0) {
+ stack->correctParams(1);
+ _tm.tm_hour = stack->pop()->getInt();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetMinutes
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetMinutes") == 0) {
+ stack->correctParams(1);
+ _tm.tm_min = stack->pop()->getInt();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // SetSeconds
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetSeconds") == 0) {
+ stack->correctParams(1);
+ _tm.tm_sec = stack->pop()->getInt();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetCurrentTime
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetCurrentTime") == 0) {
+ stack->correctParams(0);
+ g_system->getTimeAndDate(_tm);
+ stack->pushNULL();
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXDate::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("date");
+ return _scValue;
+ } else {
+ return _scValue;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXDate::scSetProperty(const char *name, ScValue *value) {
+ /*
+ //////////////////////////////////////////////////////////////////////////
+ // Name
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Name")==0){
+ setName(value->getString());
+ return STATUS_OK;
+ }
+
+ else*/ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXDate::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+ persistMgr->transfer(TMEMBER(_tm.tm_year));
+ persistMgr->transfer(TMEMBER(_tm.tm_mon));
+ persistMgr->transfer(TMEMBER(_tm.tm_mday));
+ persistMgr->transfer(TMEMBER(_tm.tm_hour));
+ persistMgr->transfer(TMEMBER(_tm.tm_min));
+ persistMgr->transfer(TMEMBER(_tm.tm_sec));
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+int SXDate::scCompare(BaseScriptable *Value) {
+ TimeDate time1 = _tm;
+ TimeDate time2 = ((SXDate *)Value)->_tm;
+
+ if (time1.tm_year < time2.tm_year) {
+ return -1;
+ } else if (time1.tm_year == time2.tm_year) {
+ if (time1.tm_mon < time2.tm_mon) {
+ return -1;
+ } else if (time1.tm_mon == time2.tm_mon) {
+ if (time1.tm_mday < time2.tm_mday) {
+ return -1;
+ } else if (time1.tm_mday == time2.tm_mday) {
+ if (time1.tm_hour < time2.tm_hour) {
+ return -1;
+ } else if (time1.tm_hour == time2.tm_hour) {
+ if (time1.tm_min < time2.tm_min) {
+ return -1;
+ } else if (time1.tm_min == time2.tm_min) {
+ if (time1.tm_sec < time2.tm_sec) {
+ return -1;
+ } else if (time1.tm_sec == time2.tm_sec) {
+ return 0; // Equal
+ } else {
+ return 1; // Sec
+ }
+ } else {
+ return 1; // Minute
+ }
+ } else {
+ return 1; // Hour
+ }
+ } else {
+ return 1; // Day
+ }
+ } else {
+ return 1; // Month
+ }
+ } else {
+ return 1; // Year
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_date.h b/engines/wintermute/base/scriptables/script_ext_date.h
new file mode 100644
index 0000000000..f6f04dd7e6
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_date.h
@@ -0,0 +1,54 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXDATE_H
+#define WINTERMUTE_SXDATE_H
+
+#include "common/system.h"
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class SXDate : public BaseScriptable {
+public:
+ int scCompare(BaseScriptable *Value);
+ DECLARE_PERSISTENT(SXDate, BaseScriptable)
+ SXDate(BaseGame *inGame, ScStack *Stack);
+ virtual ~SXDate();
+ ScValue *scGetProperty(const char *name);
+ bool scSetProperty(const char *name, ScValue *value);
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ const char *scToString();
+private:
+ TimeDate _tm;
+ Common::String _strRep;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_file.cpp b/engines/wintermute/base/scriptables/script_ext_file.cpp
new file mode 100644
index 0000000000..ab574d464b
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_file.cpp
@@ -0,0 +1,829 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/system/sys_class_registry.h"
+#include "engines/wintermute/system/sys_class.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/file/base_file.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/scriptables/script_ext_file.h"
+
+// Note: This code is completely untested, as I have yet to find a game that uses SXFile.
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(SXFile, false)
+
+BaseScriptable *makeSXFile(BaseGame *inGame, ScStack *stack) {
+ return new SXFile(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXFile::SXFile(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+
+ _filename = NULL;
+ if (!val->isNULL()) {
+ BaseUtils::setString(&_filename, val->getString());
+ }
+
+ _readFile = NULL;
+ _writeFile = NULL;
+
+ _mode = 0;
+ _textMode = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXFile::~SXFile() {
+ cleanup();
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SXFile::cleanup() {
+ delete[] _filename;
+ _filename = NULL;
+ close();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void SXFile::close() {
+ if (_readFile) {
+ BaseFileManager::getEngineInstance()->closeFile(_readFile);
+ _readFile = NULL;
+ }
+ if (_writeFile) {
+ _writeFile->finalize();
+ delete _writeFile;
+ _writeFile = NULL;
+ }
+ _mode = 0;
+ _textMode = false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *SXFile::scToString() {
+ if (_filename) {
+ return _filename;
+ } else {
+ return "[file object]";
+ }
+}
+
+#define FILE_BUFFER_SIZE 32768
+//////////////////////////////////////////////////////////////////////////
+bool SXFile::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetFilename
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SetFilename") == 0) {
+ stack->correctParams(1);
+ const char *filename = stack->pop()->getString();
+ cleanup();
+ BaseUtils::setString(&_filename, filename);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // OpenAsText / OpenAsBinary
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "OpenAsText") == 0 || strcmp(name, "OpenAsBinary") == 0) {
+ stack->correctParams(1);
+ close();
+ _mode = stack->pop()->getInt(1);
+ if (_mode < 1 || _mode > 3) {
+ script->runtimeError("File.%s: invalid access mode. Setting read mode.", name);
+ _mode = 1;
+ }
+ if (_mode == 1) {
+ _readFile = BaseFileManager::getEngineInstance()->openFile(_filename);
+ if (!_readFile) {
+ //script->runtimeError("File.%s: Error opening file '%s' for reading.", Name, _filename);
+ close();
+ } else {
+ _textMode = strcmp(name, "OpenAsText") == 0;
+ }
+ } else {
+ if (strcmp(name, "OpenAsText") == 0) {
+ if (_mode == 2) {
+ _writeFile = openForWrite(_filename, false);
+ } else {
+ _writeFile = openForAppend(_filename, false);
+ }
+ } else {
+ if (_mode == 2) {
+ _writeFile = openForWrite(_filename, true);
+ } else {
+ _writeFile = openForAppend(_filename, true);
+ }
+ }
+
+ if (!_writeFile) {
+ //script->runtimeError("File.%s: Error opening file '%s' for writing.", Name, _filename);
+ close();
+ } else {
+ _textMode = strcmp(name, "OpenAsText") == 0;
+ }
+ }
+
+ if (_readFile || _writeFile) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Close
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Close") == 0) {
+ stack->correctParams(0);
+ close();
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPosition
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetPosition") == 0) {
+ stack->correctParams(1);
+ if (_mode == 0) {
+ script->runtimeError("File.%s: File is not open", name);
+ stack->pushBool(false);
+ } else {
+ int pos = stack->pop()->getInt();
+ stack->pushBool(setPos(pos));
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Delete
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Delete") == 0) {
+ stack->correctParams(0);
+ close();
+ error("SXFile-Method: \"Delete\" not supported");
+ //stack->pushBool(BasePlatform::deleteFile(_filename) != false);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Copy
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Copy") == 0) {
+ stack->correctParams(2);
+ /* const char *dest = */ stack->pop()->getString();
+ /* bool overwrite = */ stack->pop()->getBool(true);
+
+ close();
+ error("SXFile-Method: Copy not supported");
+ //stack->pushBool(BasePlatform::copyFile(_filename, Dest, !Overwrite) != false);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadLine
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadLine") == 0) {
+ stack->correctParams(0);
+ if (!_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open in text mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ uint32 bufSize = FILE_BUFFER_SIZE;
+ byte *buf = (byte *)malloc(bufSize);
+ uint32 counter = 0;
+ byte b;
+ bool foundNewLine = false;
+ bool ret = STATUS_FAILED;
+ do {
+ ret = _readFile->read(&b, 1);
+ if (ret != 1) {
+ break;
+ }
+
+ if (counter > bufSize) {
+ buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
+ bufSize += FILE_BUFFER_SIZE;
+ }
+ if (b == '\n') {
+ buf[counter] = '\0';
+ foundNewLine = true;
+ break;
+ } else if (b == 0x0D) {
+ continue;
+ } else {
+ buf[counter] = b;
+ counter++;
+ }
+ } while (DID_SUCCEED(ret));
+
+ if (counter > bufSize) {
+ buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
+ bufSize += FILE_BUFFER_SIZE;
+ }
+ buf[counter] = '\0';
+
+ if (!foundNewLine && counter == 0) {
+ stack->pushNULL();
+ } else {
+ stack->pushString((char *)buf);
+ }
+
+ free(buf);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadText
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadText") == 0) {
+ stack->correctParams(1);
+ int textLen = stack->pop()->getInt();
+
+ if (!_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open in text mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ uint32 bufSize = FILE_BUFFER_SIZE;
+ byte *buf = (byte *)malloc(bufSize);
+ uint32 counter = 0;
+ byte b;
+
+ bool ret = STATUS_FAILED;
+ while (counter < (uint32)textLen) {
+ ret = _readFile->read(&b, 1);
+ if (ret != 1) {
+ break;
+ }
+
+ if (counter > bufSize) {
+ buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
+ bufSize += FILE_BUFFER_SIZE;
+ }
+ if (b == 0x0D) {
+ continue;
+ } else {
+ buf[counter] = b;
+ counter++;
+ }
+ }
+
+ if (counter > bufSize) {
+ buf = (byte *)realloc(buf, bufSize + FILE_BUFFER_SIZE);
+ bufSize += FILE_BUFFER_SIZE;
+ }
+ buf[counter] = '\0';
+
+ if (textLen > 0 && counter == 0) {
+ stack->pushNULL();
+ } else {
+ stack->pushString((char *)buf);
+ }
+
+ free(buf);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteLine / WriteText
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteLine") == 0 || strcmp(name, "WriteText") == 0) {
+ stack->correctParams(1);
+ const char *line = stack->pop()->getString();
+ if (!_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in text mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ Common::String writeLine;
+ if (strcmp(name, "WriteLine") == 0) {
+ writeLine = Common::String::format("%s\n", line);
+ } else {
+ writeLine = Common::String::format("%s", line);
+ }
+ _writeFile->writeString(writeLine);
+ _writeFile->writeByte(0);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ //////////////////////////////////////////////////////////////////////////
+ // ReadBool
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadBool") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ bool val;
+ if (_readFile->read(&val, sizeof(bool)) == sizeof(bool)) {
+ stack->pushBool(val);
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadByte
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadByte") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ byte val = _readFile->readByte();
+ if (!_readFile->err()) {
+ stack->pushInt(val);
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadShort
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadShort") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ int16 val = _readFile->readSint16LE();
+ if (!_readFile->err()) {
+ stack->pushInt(65536 + val);
+ } else {
+ stack->pushNULL();
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadInt / ReadLong
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadInt") == 0 || strcmp(name, "ReadLong") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ int32 val = _readFile->readSint32LE();
+ if (!_readFile->err()) {
+ stack->pushInt(val);
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadFloat
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadFloat") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ float val;
+ (*(uint32 *)&val) = _readFile->readUint32LE();
+ if (!_readFile->err()) {
+ stack->pushFloat(val);
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadDouble
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadDouble") == 0) { // TODO: Solve reading a 8 byte double.
+ error("SXFile::ReadDouble - Not endian safe yet");
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ double val;
+ if (_readFile->read(&val, sizeof(double)) == sizeof(double)) {
+ stack->pushFloat(val);
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ReadString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ReadString") == 0) {
+ stack->correctParams(0);
+ if (_textMode || !_readFile) {
+ script->runtimeError("File.%s: File must be open for reading in binary mode.", name);
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+ uint32 size = _readFile->readUint32LE();
+ if (!_readFile->err()) {
+ byte *str = new byte[size + 1];
+ if (str) {
+ if (_readFile->read(str, size) == size) {
+ str[size] = '\0';
+ stack->pushString((char *)str);
+ }
+ delete[] str;
+ } else {
+ stack->pushNULL();
+ }
+ } else {
+ stack->pushNULL();
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteBool
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteBool") == 0) {
+ stack->correctParams(1);
+ bool val = stack->pop()->getBool();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ _writeFile->writeByte(val);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteByte
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteByte") == 0) {
+ stack->correctParams(1);
+ byte val = stack->pop()->getInt();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ _writeFile->writeByte(val);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteShort
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteShort") == 0) {
+ stack->correctParams(1);
+ int16 val = stack->pop()->getInt();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ _writeFile->writeSint16LE(val);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteInt / WriteLong
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteInt") == 0 || strcmp(name, "WriteLong") == 0) {
+ stack->correctParams(1);
+ int32 val = stack->pop()->getInt();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ _writeFile->writeSint32LE(val);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteFloat
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteFloat") == 0) {
+ stack->correctParams(1);
+ float val = stack->pop()->getFloat();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ uint32 *ptr = (uint32 *)&val;
+ _writeFile->writeUint32LE(*ptr);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteDouble
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteDouble") == 0) {
+ error("SXFile::WriteDouble - Not endian safe yet");
+ stack->correctParams(1);
+ /* double val = */ stack->pop()->getFloat();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+ //fwrite(&val, sizeof(val), 1, (FILE *)_writeFile);
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // WriteString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "WriteString") == 0) {
+ stack->correctParams(1);
+ const char *val = stack->pop()->getString();
+
+ if (_textMode || !_writeFile) {
+ script->runtimeError("File.%s: File must be open for writing in binary mode.", name);
+ stack->pushBool(false);
+ return STATUS_OK;
+ }
+
+ uint32 size = strlen(val);
+ _writeFile->writeUint32LE(size);
+ _writeFile->writeString(val);
+
+ stack->pushBool(true);
+
+ return STATUS_OK;
+ } else {
+ return BaseScriptable::scCallMethod(script, stack, thisStack, name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXFile::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("file");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Filename (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Filename") == 0) {
+ _scValue->setString(_filename);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Position (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Position") == 0) {
+ _scValue->setInt(getPos());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Length (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Length") == 0) {
+ _scValue->setInt(getLength());
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // TextMode (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "TextMode") == 0) {
+ _scValue->setBool(_textMode);
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // AccessMode (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "AccessMode") == 0) {
+ _scValue->setInt(_mode);
+ return _scValue;
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXFile::scSetProperty(const char *name, ScValue *value) {
+ /*
+ //////////////////////////////////////////////////////////////////////////
+ // Length
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Length")==0){
+ int origLength = _length;
+ _length = max(value->getInt(0), 0);
+
+ char propName[20];
+ if (_length < OrigLength){
+ for(int i=_length; i<OrigLength; i++){
+ sprintf(PropName, "%d", i);
+ _values->DeleteProp(PropName);
+ }
+ }
+ return STATUS_OK;
+ }
+ else*/ return BaseScriptable::scSetProperty(name, value);
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 SXFile::getPos() {
+ if (_mode == 1 && _readFile) {
+ return _readFile->pos();
+ } else if ((_mode == 2 || _mode == 3) && _writeFile) {
+ error("SXFile - getPos for WriteFile not supported");
+ return 0;
+// return ftell((FILE *)_writeFile);
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SXFile::setPos(uint32 pos, int whence) {
+ if (_mode == 1 && _readFile) {
+ return _readFile->seek(pos, whence);
+ } else if ((_mode == 2 || _mode == 3) && _writeFile) {
+ error("SXFile - seeking in WriteFile not supported");
+ return false;
+// return fseek((FILE *)_writeFile, pos, (int)origin) == 0;
+ } else {
+ return false;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 SXFile::getLength() {
+ if (_mode == 1 && _readFile) {
+ return _readFile->size();
+ } else if ((_mode == 2 || _mode == 3) && _writeFile) {
+ error("SXFile - reading length for WriteFile not supported");
+ return 0;
+ /*
+ uint32 currentPos = ftell((FILE *)_writeFile);
+ fseek((FILE *)_writeFile, 0, SEEK_END);
+ int ret = ftell((FILE *)_writeFile);
+ fseek((FILE *)_writeFile, CurrentPos, SEEK_SET);
+ return Ret;*/
+ } else {
+ return 0;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SXFile::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_filename));
+ persistMgr->transfer(TMEMBER(_mode));
+ persistMgr->transfer(TMEMBER(_textMode));
+
+ uint32 pos = 0;
+ if (persistMgr->getIsSaving()) {
+ pos = getPos();
+ persistMgr->transfer(TMEMBER(pos));
+ } else {
+ persistMgr->transfer(TMEMBER(pos));
+
+ // try to re-open file if needed
+ _writeFile = NULL;
+ _readFile = NULL;
+
+ if (_mode != 0) {
+ // open for reading
+ if (_mode == 1) {
+ _readFile = BaseFileManager::getEngineInstance()->openFile(_filename);
+ if (!_readFile) {
+ close();
+ }
+ }
+ // open for writing / appending
+ else {
+ if (_textMode) {
+ if (_mode == 2) {
+ _writeFile = openForWrite(_filename, false);
+ } else {
+ _writeFile = openForAppend(_filename, false);
+ }
+ } else {
+ if (_mode == 2) {
+ _writeFile = openForWrite(_filename, true);
+ } else {
+ _writeFile = openForAppend(_filename, true);
+ }
+ }
+ if (_writeFile) {
+ close();
+ }
+ }
+ setPos(pos);
+ }
+ }
+
+ return STATUS_OK;
+}
+
+// Should replace fopen(..., "wb+") and fopen(..., "w+")
+Common::WriteStream *SXFile::openForWrite(const Common::String &filename, bool binary) {
+ error("SXFile::openForWrite - WriteFiles not supported");
+}
+
+// Should replace fopen(..., "ab+") and fopen(..., "a+")
+Common::WriteStream *SXFile::openForAppend(const Common::String &filename, bool binary) {
+ error("SXFile::openForAppend - WriteFiles not supported");
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_file.h b/engines/wintermute/base/scriptables/script_ext_file.h
new file mode 100644
index 0000000000..b91a53e695
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_file.h
@@ -0,0 +1,66 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTES_SXFILE_H
+#define WINTERMUTES_SXFILE_H
+
+
+#include "engines/wintermute/base/base_scriptable.h"
+#include "common/stream.h"
+
+namespace Wintermute {
+
+class BaseFile;
+
+class SXFile : public BaseScriptable {
+public:
+ DECLARE_PERSISTENT(SXFile, BaseScriptable)
+ ScValue *scGetProperty(const char *name);
+ bool scSetProperty(const char *name, ScValue *value);
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ const char *scToString();
+ SXFile(BaseGame *inGame, ScStack *Stack);
+ virtual ~SXFile();
+private:
+ Common::SeekableReadStream *_readFile;
+ Common::WriteStream *_writeFile;
+ int _mode; // 0..none, 1..read, 2..write, 3..append
+ bool _textMode;
+ void close();
+ void cleanup();
+ uint32 getPos();
+ uint32 getLength();
+ bool setPos(uint32 pos, int whence = SEEK_SET);
+ char *_filename;
+ Common::WriteStream *openForWrite(const Common::String &filename, bool binary);
+ Common::WriteStream *openForAppend(const Common::String &filename, bool binary);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_math.cpp b/engines/wintermute/base/scriptables/script_ext_math.cpp
new file mode 100644
index 0000000000..598b80cff3
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_math.cpp
@@ -0,0 +1,295 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_ext_math.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/persistent.h"
+#include "common/math.h"
+#include <math.h>
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+
+IMPLEMENT_PERSISTENT(SXMath, true)
+
+BaseScriptable *makeSXMath(BaseGame *inGame) {
+ return new SXMath(inGame);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXMath::SXMath(BaseGame *inGame) : BaseScriptable(inGame) {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXMath::~SXMath() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMath::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // Abs
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Abs") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(fabs(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Acos
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Acos") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(acos(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Asin
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Asin") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(asin(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Atan
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Atan") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(atan(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Atan2
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Atan2") == 0) {
+ stack->correctParams(2);
+ double y = stack->pop()->getFloat();
+ double x = stack->pop()->getFloat();
+ stack->pushFloat(atan2(y, x));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Ceil
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Ceil") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(ceil(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Cos
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Cos") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(cos(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Cosh
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Cosh") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(cosh(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Exp
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Exp") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(exp(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Floor
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Floor") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(floor(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Log
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Log") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(log(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Log10
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Log10") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(log10(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Pow
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Pow") == 0) {
+ stack->correctParams(2);
+ double x = stack->pop()->getFloat();
+ double y = stack->pop()->getFloat();
+
+ stack->pushFloat(pow(x, y));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sin
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Sin") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(sin(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sinh
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Sinh") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(sinh(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Tan
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Tan") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(tan(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Tanh
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Tanh") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(tanh(degreeToRadian(stack->pop()->getFloat())));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sqrt
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Sqrt") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(sqrt(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DegToRad
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DegToRad") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(degreeToRadian(stack->pop()->getFloat()));
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // RadToDeg
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "RadToDeg") == 0) {
+ stack->correctParams(1);
+ stack->pushFloat(radianToDegree(stack->pop()->getFloat()));
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXMath::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("math");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // PI
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "PI") == 0) {
+ _scValue->setFloat(M_PI);
+ return _scValue;
+ } else {
+ return _scValue;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+double SXMath::degreeToRadian(double value) {
+ return value * (M_PI / 180.0f);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+double SXMath::radianToDegree(double value) {
+ return value * (180.0f / M_PI);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMath::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_math.h b/engines/wintermute/base/scriptables/script_ext_math.h
new file mode 100644
index 0000000000..f86d59fe7b
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_math.h
@@ -0,0 +1,53 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXMATH_H
+#define WINTERMUTE_SXMATH_H
+
+
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class SXMath : public BaseScriptable {
+public:
+ DECLARE_PERSISTENT(SXMath, BaseScriptable)
+ SXMath(BaseGame *inGame);
+ virtual ~SXMath();
+ virtual ScValue *scGetProperty(const char *name);
+ virtual bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+
+private:
+ double degreeToRadian(double value);
+ double radianToDegree(double value);
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
new file mode 100644
index 0000000000..5ed9bd5313
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp
@@ -0,0 +1,529 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_scriptable.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_ext_mem_buffer.h"
+#include "common/file.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(SXMemBuffer, false)
+
+BaseScriptable *makeSXMemBuffer(BaseGame *inGame, ScStack *stack) {
+ return new SXMemBuffer(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXMemBuffer::SXMemBuffer(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
+ stack->correctParams(1);
+ _buffer = NULL;
+ _size = 0;
+
+ int newSize = stack->pop()->getInt();
+ resize(MAX(0, newSize));
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXMemBuffer::SXMemBuffer(BaseGame *inGame, void *buffer) : BaseScriptable(inGame) {
+ _size = 0;
+ _buffer = buffer;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXMemBuffer::~SXMemBuffer() {
+ cleanup();
+}
+
+//////////////////////////////////////////////////////////////////////////
+void *SXMemBuffer::scToMemBuffer() {
+ return _buffer;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void SXMemBuffer::cleanup() {
+ if (_size) {
+ free(_buffer);
+ }
+ _buffer = NULL;
+ _size = 0;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMemBuffer::resize(int newSize) {
+ int oldSize = _size;
+
+ if (_size == 0) {
+ _buffer = malloc(newSize);
+ if (_buffer) {
+ _size = newSize;
+ }
+ } else {
+ void *newBuf = realloc(_buffer, newSize);
+ if (!newBuf) {
+ if (newSize == 0) {
+ _buffer = newBuf;
+ _size = newSize;
+ } else {
+ return STATUS_FAILED;
+ }
+ } else {
+ _buffer = newBuf;
+ _size = newSize;
+ }
+ }
+
+ if (_buffer && _size > oldSize) {
+ memset((byte *)_buffer + oldSize, 0, _size - oldSize);
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMemBuffer::checkBounds(ScScript *script, int start, int length) {
+ if (_buffer == NULL) {
+ script->runtimeError("Cannot use Set/Get methods on an uninitialized memory buffer");
+ return false;
+ }
+ if (_size == 0) {
+ return true;
+ }
+
+ if (start < 0 || length == 0 || start + length > _size) {
+ script->runtimeError("Set/Get method call is out of bounds");
+ return false;
+ } else {
+ return true;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+const char *SXMemBuffer::scToString() {
+ return "[membuffer object]";
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMemBuffer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // SetSize
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "SetSize") == 0) {
+ stack->correctParams(1);
+ int newSize = stack->pop()->getInt();
+ newSize = MAX(0, newSize);
+ if (DID_SUCCEED(resize(newSize))) {
+ stack->pushBool(true);
+ } else {
+ stack->pushBool(false);
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetBool
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetBool") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(bool))) {
+ stack->pushNULL();
+ } else {
+ stack->pushBool(*(bool *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetByte
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetByte") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(byte))) {
+ stack->pushNULL();
+ } else {
+ stack->pushInt(*(byte *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetShort
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetShort") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(short))) {
+ stack->pushNULL();
+ } else {
+ stack->pushInt(65536 + * (short *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetInt / GetLong
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetInt") == 0 || strcmp(name, "GetLong") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(int))) {
+ stack->pushNULL();
+ } else {
+ stack->pushInt(*(int *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetFloat
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetFloat") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(float))) {
+ stack->pushNULL();
+ } else {
+ stack->pushFloat(*(float *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetDouble
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetDouble") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(double))) {
+ stack->pushNULL();
+ } else {
+ stack->pushFloat(*(double *)((byte *)_buffer + start));
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetString") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ int length = stack->pop()->getInt();
+
+ // find end of string
+ if (length == 0 && start >= 0 && start < _size) {
+ for (int i = start; i < _size; i++) {
+ if (((char *)_buffer)[i] == '\0') {
+ length = i - start;
+ break;
+ }
+ }
+ }
+
+ if (!checkBounds(script, start, length)) {
+ stack->pushNULL();
+ } else {
+ char *str = new char[length + 1];
+ Common::strlcpy(str, (const char *)_buffer + start, length + 1);
+ stack->pushString(str);
+ delete[] str;
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // GetPointer
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "GetPointer") == 0) {
+ stack->correctParams(1);
+ int start = stack->pop()->getInt();
+ if (!checkBounds(script, start, sizeof(void *))) {
+ stack->pushNULL();
+ } else {
+ void *pointer = *(void **)((byte *)_buffer + start);
+ SXMemBuffer *buf = new SXMemBuffer(_gameRef, pointer);
+ stack->pushNative(buf, false);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetBool
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetBool") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ bool val = stack->pop()->getBool();
+
+ if (!checkBounds(script, start, sizeof(bool))) {
+ stack->pushBool(false);
+ } else {
+ *(bool *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetByte
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetByte") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ byte val = (byte)stack->pop()->getInt();
+
+ if (!checkBounds(script, start, sizeof(byte))) {
+ stack->pushBool(false);
+ } else {
+ *(byte *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetShort
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetShort") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ short val = (short)stack->pop()->getInt();
+
+ if (!checkBounds(script, start, sizeof(short))) {
+ stack->pushBool(false);
+ } else {
+ *(short *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetInt / SetLong
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetInt") == 0 || strcmp(name, "SetLong") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ int val = stack->pop()->getInt();
+
+ if (!checkBounds(script, start, sizeof(int))) {
+ stack->pushBool(false);
+ } else {
+ *(int *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetFloat
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetFloat") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ float val = (float)stack->pop()->getFloat();
+
+ if (!checkBounds(script, start, sizeof(float))) {
+ stack->pushBool(false);
+ } else {
+ *(float *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetDouble
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetDouble") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ double val = stack->pop()->getFloat();
+
+ if (!checkBounds(script, start, sizeof(double))) {
+ stack->pushBool(false);
+ } else {
+ *(double *)((byte *)_buffer + start) = val;
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetString
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetString") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ const char *val = stack->pop()->getString();
+
+ if (!checkBounds(script, start, strlen(val) + 1)) {
+ stack->pushBool(false);
+ } else {
+ memcpy((byte *)_buffer + start, val, strlen(val) + 1);
+ stack->pushBool(true);
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // SetPointer
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "SetPointer") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ /* ScValue *val = */ stack->pop();
+
+ if (!checkBounds(script, start, sizeof(void *))) {
+ stack->pushBool(false);
+ } else {
+ /*
+ int pointer = (int)Val->getMemBuffer();
+ memcpy((byte *)_buffer+Start, &Pointer, sizeof(void*));
+ stack->pushBool(true);
+ */
+ // TODO fix
+ stack->pushBool(false);
+
+ }
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // DEBUG_Dump
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "DEBUG_Dump") == 0) {
+ stack->correctParams(0);
+ if (_buffer && _size) {
+ warning("SXMemBuffer::ScCallMethod - DEBUG_Dump");
+ Common::DumpFile f;
+ f.open("buffer.bin");
+ f.write(_buffer, _size);
+ f.close();
+ }
+ stack->pushNULL();
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXMemBuffer::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("membuffer");
+ return _scValue;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Size (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Size") == 0) {
+ _scValue->setInt(_size);
+ return _scValue;
+ } else {
+ return BaseScriptable::scGetProperty(name);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMemBuffer::scSetProperty(const char *name, ScValue *value) {
+ /*
+ //////////////////////////////////////////////////////////////////////////
+ // Length
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Length")==0){
+ int origLength = _length;
+ _length = max(value->getInt(0), 0);
+
+ char propName[20];
+ if (_length < OrigLength){
+ for(int i=_length; i<OrigLength; i++){
+ sprintf(PropName, "%d", i);
+ _values->DeleteProp(PropName);
+ }
+ }
+ return STATUS_OK;
+ }
+ else*/ return BaseScriptable::scSetProperty(name, value);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXMemBuffer::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_size));
+
+ if (persistMgr->getIsSaving()) {
+ if (_size > 0) {
+ persistMgr->putBytes((byte *)_buffer, _size);
+ }
+ } else {
+ if (_size > 0) {
+ _buffer = malloc(_size);
+ persistMgr->getBytes((byte *)_buffer, _size);
+ } else {
+ _buffer = NULL;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int SXMemBuffer::scCompare(BaseScriptable *val) {
+ if (_buffer == val->scToMemBuffer()) {
+ return 0;
+ } else {
+ return 1;
+ }
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
new file mode 100644
index 0000000000..d2662b3036
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h
@@ -0,0 +1,60 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXMEMBUFFER_H
+#define WINTERMUTE_SXMEMBUFFER_H
+
+
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class SXMemBuffer : public BaseScriptable {
+public:
+ virtual int scCompare(BaseScriptable *Val);
+ DECLARE_PERSISTENT(SXMemBuffer, BaseScriptable)
+ ScValue *scGetProperty(const char *name);
+ bool scSetProperty(const char *name, ScValue *value);
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ const char *scToString();
+ SXMemBuffer(BaseGame *inGame, ScStack *stack);
+ SXMemBuffer(BaseGame *inGame, void *buffer);
+ virtual ~SXMemBuffer();
+ virtual void *scToMemBuffer();
+private:
+ int _size;
+
+ bool resize(int newSize);
+ void *_buffer;
+ void cleanup();
+ bool checkBounds(ScScript *script, int start, int length);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_object.cpp b/engines/wintermute/base/scriptables/script_ext_object.cpp
new file mode 100644
index 0000000000..b87aac81f9
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_object.cpp
@@ -0,0 +1,67 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_ext_object.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(SXObject, false)
+
+BaseScriptable *makeSXObject(BaseGame *inGame, ScStack *stack) {
+ return new SXObject(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXObject::SXObject(BaseGame *inGame, ScStack *stack) : BaseObject(inGame) {
+ int numParams = stack->pop()->getInt(0);
+ for (int i = 0; i < numParams; i++) {
+ addScript(stack->pop()->getString());
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXObject::~SXObject() {
+
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXObject::persist(BasePersistenceManager *persistMgr) {
+ BaseObject::persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_object.h b/engines/wintermute/base/scriptables/script_ext_object.h
new file mode 100644
index 0000000000..c85d16d44e
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_object.h
@@ -0,0 +1,46 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXOBJECT_H
+#define WINTERMUTE_SXOBJECT_H
+
+
+#include "engines/wintermute/base/base_object.h"
+
+namespace Wintermute {
+
+class SXObject : public BaseObject {
+public:
+ DECLARE_PERSISTENT(SXObject, BaseObject)
+ SXObject(BaseGame *inGame, ScStack *Stack);
+ virtual ~SXObject();
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_ext_string.cpp b/engines/wintermute/base/scriptables/script_ext_string.cpp
new file mode 100644
index 0000000000..8d87a92dc1
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_string.cpp
@@ -0,0 +1,436 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/base/scriptables/script_ext_string.h"
+#include "engines/wintermute/base/scriptables/script_ext_array.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "common/tokenizer.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(SXString, false)
+
+BaseScriptable *makeSXString(BaseGame *inGame, ScStack *stack) {
+ return new SXString(inGame, stack);
+}
+
+//////////////////////////////////////////////////////////////////////////
+SXString::SXString(BaseGame *inGame, ScStack *stack) : BaseScriptable(inGame) {
+ _string = NULL;
+ _capacity = 0;
+
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+
+ if (val->isInt()) {
+ _capacity = MAX(0, val->getInt());
+ if (_capacity > 0) {
+ _string = new char[_capacity];
+ memset(_string, 0, _capacity);
+ }
+ } else {
+ setStringVal(val->getString());
+ }
+
+ if (_capacity == 0) {
+ setStringVal("");
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+SXString::~SXString() {
+ if (_string) {
+ delete[] _string;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void SXString::setStringVal(const char *val) {
+ int len = strlen(val);
+ if (len >= _capacity) {
+ _capacity = len + 1;
+ delete[] _string;
+ _string = NULL;
+ _string = new char[_capacity];
+ memset(_string, 0, _capacity);
+ }
+ strcpy(_string, val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *SXString::scToString() {
+ if (_string) {
+ return _string;
+ } else {
+ return "[null string]";
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void SXString::scSetString(const char *val) {
+ setStringVal(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXString::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) {
+ //////////////////////////////////////////////////////////////////////////
+ // Substring
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Substring") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+ int end = stack->pop()->getInt();
+
+ if (end < start) {
+ BaseUtils::swap(&start, &end);
+ }
+
+ //try {
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+ //WideString subStr = str.substr(start, end - start + 1);
+ WideString subStr(str.c_str() + start, end - start + 1);
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
+ } else {
+ stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
+ }
+ // } catch (std::exception &) {
+ // stack->pushNULL();
+ // }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Substr
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Substr") == 0) {
+ stack->correctParams(2);
+ int start = stack->pop()->getInt();
+
+ ScValue *val = stack->pop();
+ int len = val->getInt();
+
+ if (!val->isNULL() && len <= 0) {
+ stack->pushString("");
+ return STATUS_OK;
+ }
+
+ if (val->isNULL()) {
+ len = strlen(_string) - start;
+ }
+
+// try {
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+// WideString subStr = str.substr(start, len);
+ WideString subStr(str.c_str() + start, len);
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ stack->pushString(StringUtil::wideToUtf8(subStr).c_str());
+ } else {
+ stack->pushString(StringUtil::wideToAnsi(subStr).c_str());
+ }
+// } catch (std::exception &) {
+// stack->pushNULL();
+// }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToUpperCase
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToUpperCase") == 0) {
+ stack->correctParams(0);
+
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+ str.toUppercase();
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ stack->pushString(StringUtil::wideToUtf8(str).c_str());
+ } else {
+ stack->pushString(StringUtil::wideToAnsi(str).c_str());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // ToLowerCase
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "ToLowerCase") == 0) {
+ stack->correctParams(0);
+
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+ str.toLowercase();
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ stack->pushString(StringUtil::wideToUtf8(str).c_str());
+ } else {
+ stack->pushString(StringUtil::wideToAnsi(str).c_str());
+ }
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // IndexOf
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "IndexOf") == 0) {
+ stack->correctParams(2);
+
+ const char *strToFind = stack->pop()->getString();
+ int index = stack->pop()->getInt();
+
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+ WideString toFind;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ toFind = StringUtil::utf8ToWide(strToFind);
+ } else {
+ toFind = StringUtil::ansiToWide(strToFind);
+ }
+
+ int indexOf = StringUtil::indexOf(str, toFind, index);
+ stack->pushInt(indexOf);
+
+ return STATUS_OK;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Split
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Split") == 0) {
+ stack->correctParams(1);
+ ScValue *val = stack->pop();
+ char separators[MAX_PATH_LENGTH] = ",";
+ if (!val->isNULL()) {
+ strcpy(separators, val->getString());
+ }
+
+ SXArray *array = new SXArray(_gameRef);
+ if (!array) {
+ stack->pushNULL();
+ return STATUS_OK;
+ }
+
+
+ WideString str;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ str = StringUtil::utf8ToWide(_string);
+ } else {
+ str = StringUtil::ansiToWide(_string);
+ }
+
+ WideString delims;
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ delims = StringUtil::utf8ToWide(separators);
+ } else {
+ delims = StringUtil::ansiToWide(separators);
+ }
+
+ Common::Array<WideString> parts;
+
+
+
+ Common::StringTokenizer tokenizer(str, delims);
+ while (!tokenizer.empty()) {
+ Common::String str2 = tokenizer.nextToken();
+ parts.push_back(str2);
+ }
+ // TODO: Clean this up
+ /*do {
+ pos = StringUtil::IndexOf(Common::String(str.c_str() + start), delims, start);
+ //pos = str.find_first_of(delims, start);
+ if (pos == start) {
+ start = pos + 1;
+ } else if (pos == str.size()) {
+ parts.push_back(Common::String(str.c_str() + start));
+ break;
+ } else {
+ parts.push_back(Common::String(str.c_str() + start, pos - start));
+ start = pos + 1;
+ }
+ //start = str.find_first_not_of(delims, start);
+ start = StringUtil::LastIndexOf(Common::String(str.c_str() + start), delims, start) + 1;
+
+ } while (pos != str.size());*/
+
+ for (Common::Array<WideString>::iterator it = parts.begin(); it != parts.end(); ++it) {
+ WideString &part = (*it);
+
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ val = new ScValue(_gameRef, StringUtil::wideToUtf8(part).c_str());
+ } else {
+ val = new ScValue(_gameRef, StringUtil::wideToAnsi(part).c_str());
+ }
+
+ array->push(val);
+ delete val;
+ val = NULL;
+ }
+
+ stack->pushNative(array, false);
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *SXString::scGetProperty(const char *name) {
+ _scValue->setNULL();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Type (RO)
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Type") == 0) {
+ _scValue->setString("string");
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Length (RO)
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Length") == 0) {
+ if (_gameRef->_textEncoding == TEXT_UTF8) {
+ WideString wstr = StringUtil::utf8ToWide(_string);
+ _scValue->setInt(wstr.size());
+ } else {
+ _scValue->setInt(strlen(_string));
+ }
+
+ return _scValue;
+ }
+ //////////////////////////////////////////////////////////////////////////
+ // Capacity
+ //////////////////////////////////////////////////////////////////////////
+ else if (strcmp(name, "Capacity") == 0) {
+ _scValue->setInt(_capacity);
+ return _scValue;
+ } else {
+ return _scValue;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXString::scSetProperty(const char *name, ScValue *value) {
+ //////////////////////////////////////////////////////////////////////////
+ // Capacity
+ //////////////////////////////////////////////////////////////////////////
+ if (strcmp(name, "Capacity") == 0) {
+ int32 newCap = (uint32)value->getInt();
+ if (newCap < (int32)(strlen(_string) + 1)) {
+ _gameRef->LOG(0, "Warning: cannot lower string capacity");
+ } else if (newCap != _capacity) {
+ char *newStr = new char[newCap];
+ if (newStr) {
+ memset(newStr, 0, newCap);
+ strcpy(newStr, _string);
+ delete[] _string;
+ _string = newStr;
+ _capacity = newCap;
+ }
+ }
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool SXString::persist(BasePersistenceManager *persistMgr) {
+
+ BaseScriptable::persist(persistMgr);
+
+ persistMgr->transfer(TMEMBER(_capacity));
+
+ if (persistMgr->getIsSaving()) {
+ if (_capacity > 0) {
+ persistMgr->putBytes((byte *)_string, _capacity);
+ }
+ } else {
+ if (_capacity > 0) {
+ _string = new char[_capacity];
+ persistMgr->getBytes((byte *)_string, _capacity);
+ } else {
+ _string = NULL;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int SXString::scCompare(BaseScriptable *val) {
+ return strcmp(_string, ((SXString *)val)->_string);
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_ext_string.h b/engines/wintermute/base/scriptables/script_ext_string.h
new file mode 100644
index 0000000000..255b9c57eb
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_ext_string.h
@@ -0,0 +1,58 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SXSTRING_H
+#define WINTERMUTE_SXSTRING_H
+
+
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+class SXString : public BaseScriptable {
+public:
+ virtual int scCompare(BaseScriptable *Val);
+ DECLARE_PERSISTENT(SXString, BaseScriptable)
+ ScValue *scGetProperty(const char *name);
+ bool scSetProperty(const char *name, ScValue *value);
+ bool scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name);
+ void scSetString(const char *val);
+ const char *scToString();
+ void setStringVal(const char *val);
+
+ SXString(BaseGame *inGame, ScStack *Stack);
+ virtual ~SXString();
+
+private:
+ char *_string;
+ int _capacity;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_stack.cpp b/engines/wintermute/base/scriptables/script_stack.cpp
new file mode 100644
index 0000000000..77367045c2
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_stack.cpp
@@ -0,0 +1,232 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/scriptables/script_stack.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/base_game.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(ScStack, false)
+
+//////////////////////////////////////////////////////////////////////////
+ScStack::ScStack(BaseGame *inGame) : BaseClass(inGame) {
+ _sP = -1;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScStack::~ScStack() {
+
+#if _DEBUG
+ //_gameRef->LOG(0, "STAT: Stack size: %d, SP=%d", _values.size(), _sP);
+#endif
+
+ for (uint32 i = 0; i < _values.size(); i++) {
+ delete _values[i];
+ }
+ _values.clear();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScStack::pop() {
+ if (_sP < 0) {
+ _gameRef->LOG(0, "Fatal: Stack underflow");
+ return NULL;
+ }
+
+ return _values[_sP--];
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::push(ScValue *val) {
+ _sP++;
+
+ if (_sP < (int32)_values.size()) {
+ _values[_sP]->cleanup();
+ _values[_sP]->copy(val);
+ } else {
+ ScValue *copyVal = new ScValue(_gameRef);
+ copyVal->copy(val);
+ _values.add(copyVal);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScStack::getPushValue() {
+ _sP++;
+
+ if (_sP >= (int32)_values.size()) {
+ ScValue *val = new ScValue(_gameRef);
+ _values.add(val);
+ }
+ _values[_sP]->cleanup();
+ return _values[_sP];
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScStack::getTop() {
+ if (_sP < 0 || _sP >= (int32)_values.size()) {
+ return NULL;
+ } else {
+ return _values[_sP];
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScStack::getAt(int index) {
+ index = _sP - index;
+ if (index < 0 || index >= (int32)_values.size()) {
+ return NULL;
+ } else {
+ return _values[index];
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::correctParams(uint32 expectedParams) {
+ uint32 nuParams = (uint32)pop()->getInt();
+
+ if (expectedParams < nuParams) { // too many params
+ while (expectedParams < nuParams) {
+ //Pop();
+ delete _values[_sP - expectedParams];
+ _values.remove_at(_sP - expectedParams);
+ nuParams--;
+ _sP--;
+ }
+ } else if (expectedParams > nuParams) { // need more params
+ while (expectedParams > nuParams) {
+ //Push(null_val);
+ ScValue *nullVal = new ScValue(_gameRef);
+ nullVal->setNULL();
+ _values.insert_at(_sP - nuParams + 1, nullVal);
+ nuParams++;
+ _sP++;
+
+ if ((int32)_values.size() > _sP + 1) {
+ delete _values[_values.size() - 1];
+ _values.remove_at(_values.size() - 1);
+ }
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushNULL() {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setNULL();
+ Push(val);
+ delete val;
+ */
+ getPushValue()->setNULL();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushInt(int val) {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setInt(Val);
+ Push(val);
+ delete val;
+ */
+ getPushValue()->setInt(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushFloat(double val) {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setFloat(Val);
+ Push(val);
+ delete val;
+ */
+ getPushValue()->setFloat(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushBool(bool val) {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setBool(Val);
+ Push(val);
+ delete val;
+ */
+ getPushValue()->setBool(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushString(const char *val) {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setString(Val);
+ Push(val);
+ delete val;
+ */
+ getPushValue()->setString(val);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScStack::pushNative(BaseScriptable *val, bool persistent) {
+ /*
+ ScValue* val = new ScValue(_gameRef);
+ val->setNative(Val, Persistent);
+ Push(val);
+ delete val;
+ */
+
+ getPushValue()->setNative(val, persistent);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScStack::persist(BasePersistenceManager *persistMgr) {
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ persistMgr->transfer(TMEMBER(_sP));
+ _values.persist(persistMgr);
+
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_stack.h b/engines/wintermute/base/scriptables/script_stack.h
new file mode 100644
index 0000000000..86d246cf34
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_stack.h
@@ -0,0 +1,66 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SCSTACK_H
+#define WINTERMUTE_SCSTACK_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/persistent.h"
+
+namespace Wintermute {
+
+class ScValue;
+class BaseScriptable;
+
+class ScStack : public BaseClass {
+public:
+ ScValue *getAt(int Index);
+ ScValue *getPushValue();
+ DECLARE_PERSISTENT(ScStack, BaseClass)
+ void pushNative(BaseScriptable *val, bool persistent);
+ void pushString(const char *val);
+ void pushBool(bool val);
+ void pushInt(int val);
+ void pushFloat(double val);
+ void pushNULL();
+ void correctParams(uint32 expectedParams);
+ ScValue *getTop();
+ void push(ScValue *val);
+ ScValue *pop();
+ ScStack(BaseGame *inGame);
+ virtual ~ScStack();
+ BaseArray<ScValue *> _values;
+ int _sP;
+
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/scriptables/script_value.cpp b/engines/wintermute/base/scriptables/script_value.cpp
new file mode 100644
index 0000000000..0bc7ab5807
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_value.cpp
@@ -0,0 +1,995 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/platform_osystem.h"
+#include "engines/wintermute/base/base_dynamic_buffer.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/scriptables/script_value.h"
+#include "engines/wintermute/base/scriptables/script.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "engines/wintermute/base/base_scriptable.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+IMPLEMENT_PERSISTENT(ScValue, false)
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::ScValue(BaseGame *inGame) : BaseClass(inGame) {
+ _type = VAL_NULL;
+
+ _valBool = false;
+ _valInt = 0;
+ _valFloat = 0.0f;
+ _valNative = NULL;
+ _valString = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::ScValue(BaseGame *inGame, bool val) : BaseClass(inGame) {
+ _type = VAL_BOOL;
+ _valBool = val;
+
+ _valInt = 0;
+ _valFloat = 0.0f;
+ _valNative = NULL;
+ _valString = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::ScValue(BaseGame *inGame, int val) : BaseClass(inGame) {
+ _type = VAL_INT;
+ _valInt = val;
+
+ _valFloat = 0.0f;
+ _valBool = false;
+ _valNative = NULL;
+ _valString = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::ScValue(BaseGame *inGame, double val) : BaseClass(inGame) {
+ _type = VAL_FLOAT;
+ _valFloat = val;
+
+ _valInt = 0;
+ _valBool = false;
+ _valNative = NULL;
+ _valString = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::ScValue(BaseGame *inGame, const char *val) : BaseClass(inGame) {
+ _type = VAL_STRING;
+ _valString = NULL;
+ setStringVal(val);
+
+ _valBool = false;
+ _valInt = 0;
+ _valFloat = 0.0f;
+ _valNative = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::cleanup(bool ignoreNatives) {
+ deleteProps();
+
+ if (_valString) {
+ delete[] _valString;
+ }
+
+ if (!ignoreNatives) {
+ if (_valNative && !_persistent) {
+ _valNative->_refCount--;
+ if (_valNative->_refCount <= 0) {
+ delete _valNative;
+ _valNative = NULL;
+ }
+ }
+ }
+
+
+ _type = VAL_NULL;
+
+ _valBool = false;
+ _valInt = 0;
+ _valFloat = 0.0f;
+ _valNative = NULL;
+ _valString = NULL;
+ _valRef = NULL;
+ _persistent = false;
+ _isConstVar = false;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue::~ScValue() {
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+ScValue *ScValue::getProp(const char *name) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getProp(name);
+ }
+
+ if (_type == VAL_STRING && strcmp(name, "Length") == 0) {
+ _gameRef->_scValue->_type = VAL_INT;
+
+ if (_gameRef->_textEncoding == TEXT_ANSI) {
+ _gameRef->_scValue->setInt(strlen(_valString));
+ } else {
+ WideString wstr = StringUtil::utf8ToWide(_valString);
+ _gameRef->_scValue->setInt(wstr.size());
+ }
+
+ return _gameRef->_scValue;
+ }
+
+ ScValue *ret = NULL;
+
+ if (_type == VAL_NATIVE && _valNative) {
+ ret = _valNative->scGetProperty(name);
+ }
+
+ if (ret == NULL) {
+ _valIter = _valObject.find(name);
+ if (_valIter != _valObject.end()) {
+ ret = _valIter->_value;
+ }
+ }
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::deleteProp(const char *name) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->deleteProp(name);
+ }
+
+ _valIter = _valObject.find(name);
+ if (_valIter != _valObject.end()) {
+ delete _valIter->_value;
+ _valIter->_value = NULL;
+ }
+
+ return STATUS_OK;
+}
+
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProp(const char *name, ScValue *val, bool copyWhole, bool setAsConst) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->setProp(name, val);
+ }
+
+ bool ret = STATUS_FAILED;
+ if (_type == VAL_NATIVE && _valNative) {
+ ret = _valNative->scSetProperty(name, val);
+ }
+
+ if (DID_FAIL(ret)) {
+ ScValue *newVal = NULL;
+
+ _valIter = _valObject.find(name);
+ if (_valIter != _valObject.end()) {
+ newVal = _valIter->_value;
+ }
+ if (!newVal) {
+ newVal = new ScValue(_gameRef);
+ } else {
+ newVal->cleanup();
+ }
+
+ newVal->copy(val, copyWhole);
+ newVal->_isConstVar = setAsConst;
+ _valObject[name] = newVal;
+
+ if (_type != VAL_NATIVE) {
+ _type = VAL_OBJECT;
+ }
+
+ /*
+ _valIter = _valObject.find(Name);
+ if (_valIter != _valObject.end()){
+ delete _valIter->_value;
+ _valIter->_value = NULL;
+ }
+ ScValue* val = new ScValue(_gameRef);
+ val->Copy(Val, CopyWhole);
+ val->_isConstVar = SetAsConst;
+ _valObject[Name] = val;
+
+ if (_type!=VAL_NATIVE) _type = VAL_OBJECT;
+ */
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::propExists(const char *name) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->propExists(name);
+ }
+ _valIter = _valObject.find(name);
+
+ return (_valIter != _valObject.end());
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::deleteProps() {
+ _valIter = _valObject.begin();
+ while (_valIter != _valObject.end()) {
+ delete(ScValue *)_valIter->_value;
+ _valIter++;
+ }
+ _valObject.clear();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::CleanProps(bool includingNatives) {
+ _valIter = _valObject.begin();
+ while (_valIter != _valObject.end()) {
+ if (!_valIter->_value->_isConstVar && (!_valIter->_value->isNative() || includingNatives)) {
+ _valIter->_value->setNULL();
+ }
+ _valIter++;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isNULL() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isNULL();
+ }
+
+ return (_type == VAL_NULL);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isNative() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isNative();
+ }
+
+ return (_type == VAL_NATIVE);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isString() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isString();
+ }
+
+ return (_type == VAL_STRING);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isFloat() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isFloat();
+ }
+
+ return (_type == VAL_FLOAT);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isInt() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isInt();
+ }
+
+ return (_type == VAL_INT);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isBool() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isBool();
+ }
+
+ return (_type == VAL_BOOL);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::isObject() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->isObject();
+ }
+
+ return (_type == VAL_OBJECT);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+TValType ScValue::getTypeTolerant() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getType();
+ }
+
+ return _type;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setBool(bool val) {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setBool(val);
+ return;
+ }
+
+ if (_type == VAL_NATIVE) {
+ _valNative->scSetBool(val);
+ return;
+ }
+
+ _valBool = val;
+ _type = VAL_BOOL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setInt(int val) {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setInt(val);
+ return;
+ }
+
+ if (_type == VAL_NATIVE) {
+ _valNative->scSetInt(val);
+ return;
+ }
+
+ _valInt = val;
+ _type = VAL_INT;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setFloat(double val) {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setFloat(val);
+ return;
+ }
+
+ if (_type == VAL_NATIVE) {
+ _valNative->scSetFloat(val);
+ return;
+ }
+
+ _valFloat = val;
+ _type = VAL_FLOAT;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setString(const char *val) {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setString(val);
+ return;
+ }
+
+ if (_type == VAL_NATIVE) {
+ _valNative->scSetString(val);
+ return;
+ }
+
+ setStringVal(val);
+ if (_valString) {
+ _type = VAL_STRING;
+ } else {
+ _type = VAL_NULL;
+ }
+}
+
+void ScValue::setString(const Common::String &val) {
+ setString(val.c_str());
+}
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setStringVal(const char *val) {
+ if (_valString) {
+ delete[] _valString;
+ _valString = NULL;
+ }
+
+ if (val == NULL) {
+ _valString = NULL;
+ return;
+ }
+
+ _valString = new char [strlen(val) + 1];
+ if (_valString) {
+ strcpy(_valString, val);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setNULL() {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setNULL();
+ return;
+ }
+
+ if (_valNative && !_persistent) {
+ _valNative->_refCount--;
+ if (_valNative->_refCount <= 0) {
+ delete _valNative;
+ }
+ }
+ _valNative = NULL;
+ deleteProps();
+
+ _type = VAL_NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setNative(BaseScriptable *val, bool persistent) {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setNative(val, persistent);
+ return;
+ }
+
+ if (val == NULL) {
+ setNULL();
+ } else {
+ if (_valNative && !_persistent) {
+ _valNative->_refCount--;
+ if (_valNative->_refCount <= 0) {
+ if (_valNative != val) {
+ delete _valNative;
+ }
+ _valNative = NULL;
+ }
+ }
+
+ _type = VAL_NATIVE;
+ _persistent = persistent;
+
+ _valNative = val;
+ if (_valNative && !_persistent) {
+ _valNative->_refCount++;
+ }
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setObject() {
+ if (_type == VAL_VARIABLE_REF) {
+ _valRef->setObject();
+ return;
+ }
+
+ deleteProps();
+ _type = VAL_OBJECT;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setReference(ScValue *val) {
+ _valRef = val;
+ _type = VAL_VARIABLE_REF;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::getBool(bool defaultVal) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getBool();
+ }
+
+ switch (_type) {
+ case VAL_BOOL:
+ return _valBool;
+
+ case VAL_NATIVE:
+ return _valNative->scToBool();
+
+ case VAL_INT:
+ return (_valInt != 0);
+
+ case VAL_FLOAT:
+ return (_valFloat != 0.0f);
+
+ case VAL_STRING:
+ return (scumm_stricmp(_valString, "1") == 0 || scumm_stricmp(_valString, "yes") == 0 || scumm_stricmp(_valString, "true") == 0);
+
+ default:
+ return defaultVal;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int ScValue::getInt(int defaultVal) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getInt();
+ }
+
+ switch (_type) {
+ case VAL_BOOL:
+ return _valBool ? 1 : 0;
+
+ case VAL_NATIVE:
+ return _valNative->scToInt();
+
+ case VAL_INT:
+ return _valInt;
+
+ case VAL_FLOAT:
+ return (int)_valFloat;
+
+ case VAL_STRING:
+ return atoi(_valString);
+
+ default:
+ return defaultVal;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+double ScValue::getFloat(double defaultVal) {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getFloat();
+ }
+
+ switch (_type) {
+ case VAL_BOOL:
+ return _valBool ? 1.0f : 0.0f;
+
+ case VAL_NATIVE:
+ return _valNative->scToFloat();
+
+ case VAL_INT:
+ return (double)_valInt;
+
+ case VAL_FLOAT:
+ return _valFloat;
+
+ case VAL_STRING:
+ return atof(_valString);
+
+ default:
+ return defaultVal;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+void *ScValue::getMemBuffer() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getMemBuffer();
+ }
+
+ if (_type == VAL_NATIVE) {
+ return _valNative->scToMemBuffer();
+ } else {
+ return (void *)NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+const char *ScValue::getString() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getString();
+ }
+
+ switch (_type) {
+ case VAL_OBJECT:
+ setStringVal("[object]");
+ break;
+
+ case VAL_NULL:
+ setStringVal("[null]");
+ break;
+
+ case VAL_NATIVE: {
+ const char *strVal = _valNative->scToString();
+ setStringVal(strVal);
+ return strVal;
+ break;
+ }
+
+ case VAL_BOOL:
+ setStringVal(_valBool ? "yes" : "no");
+ break;
+
+ case VAL_INT: {
+ char dummy[50];
+ sprintf(dummy, "%d", _valInt);
+ setStringVal(dummy);
+ break;
+ }
+
+ case VAL_FLOAT: {
+ char dummy[50];
+ sprintf(dummy, "%f", _valFloat);
+ setStringVal(dummy);
+ break;
+ }
+
+ case VAL_STRING:
+ break;
+
+ default:
+ setStringVal("");
+ }
+
+ return _valString;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseScriptable *ScValue::getNative() {
+ if (_type == VAL_VARIABLE_REF) {
+ return _valRef->getNative();
+ }
+
+ if (_type == VAL_NATIVE) {
+ return _valNative;
+ } else {
+ return NULL;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+TValType ScValue::getType() {
+ return _type;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::copy(ScValue *orig, bool copyWhole) {
+ _gameRef = orig->_gameRef;
+
+ if (_valNative && !_persistent) {
+ _valNative->_refCount--;
+ if (_valNative->_refCount <= 0) {
+ if (_valNative != orig->_valNative) {
+ delete _valNative;
+ }
+ _valNative = NULL;
+ }
+ }
+
+ if (orig->_type == VAL_VARIABLE_REF && orig->_valRef && copyWhole) {
+ orig = orig->_valRef;
+ }
+
+ cleanup(true);
+
+ _type = orig->_type;
+ _valBool = orig->_valBool;
+ _valInt = orig->_valInt;
+ _valFloat = orig->_valFloat;
+ setStringVal(orig->_valString);
+
+ _valRef = orig->_valRef;
+ _persistent = orig->_persistent;
+
+ _valNative = orig->_valNative;
+ if (_valNative && !_persistent) {
+ _valNative->_refCount++;
+ }
+//!!!! ref->native++
+
+ // copy properties
+ if (orig->_type == VAL_OBJECT && orig->_valObject.size() > 0) {
+ orig->_valIter = orig->_valObject.begin();
+ while (orig->_valIter != orig->_valObject.end()) {
+ _valObject[orig->_valIter->_key] = new ScValue(_gameRef);
+ _valObject[orig->_valIter->_key]->copy(orig->_valIter->_value);
+ orig->_valIter++;
+ }
+ } else {
+ _valObject.clear();
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void ScValue::setValue(ScValue *val) {
+ if (val->_type == VAL_VARIABLE_REF) {
+ setValue(val->_valRef);
+ return;
+ }
+
+ // if being assigned a simple type, preserve native state
+ if (_type == VAL_NATIVE && (val->_type == VAL_INT || val->_type == VAL_STRING || val->_type == VAL_BOOL)) {
+ switch (val->_type) {
+ case VAL_INT:
+ _valNative->scSetInt(val->getInt());
+ break;
+ case VAL_FLOAT:
+ _valNative->scSetFloat(val->getFloat());
+ break;
+ case VAL_BOOL:
+ _valNative->scSetBool(val->getBool());
+ break;
+ case VAL_STRING:
+ _valNative->scSetString(val->getString());
+ break;
+ default:
+ warning("ScValue::setValue - unhandled enum");
+ break;
+ }
+ }
+ // otherwise just copy everything
+ else {
+ copy(val);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::persist(BasePersistenceManager *persistMgr) {
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ persistMgr->transfer(TMEMBER(_persistent));
+ persistMgr->transfer(TMEMBER(_isConstVar));
+ persistMgr->transfer(TMEMBER_INT(_type));
+ persistMgr->transfer(TMEMBER(_valBool));
+ persistMgr->transfer(TMEMBER(_valFloat));
+ persistMgr->transfer(TMEMBER(_valInt));
+ persistMgr->transfer(TMEMBER(_valNative));
+
+ int size;
+ const char *str;
+ if (persistMgr->getIsSaving()) {
+ size = _valObject.size();
+ persistMgr->transfer("", &size);
+ _valIter = _valObject.begin();
+ while (_valIter != _valObject.end()) {
+ str = _valIter->_key.c_str();
+ persistMgr->transfer("", &str);
+ persistMgr->transfer("", &_valIter->_value);
+
+ _valIter++;
+ }
+ } else {
+ ScValue *val;
+ persistMgr->transfer("", &size);
+ for (int i = 0; i < size; i++) {
+ persistMgr->transfer("", &str);
+ persistMgr->transfer("", &val);
+
+ _valObject[str] = val;
+ delete[] str;
+ }
+ }
+
+ persistMgr->transfer(TMEMBER(_valRef));
+ persistMgr->transfer(TMEMBER(_valString));
+
+ /*
+ FILE* f = fopen("c:\\val.log", "a+");
+ switch(_type)
+ {
+ case VAL_STRING:
+ fprintf(f, "str %s\n", _valString);
+ break;
+
+ case VAL_INT:
+ fprintf(f, "int %d\n", _valInt);
+ break;
+
+ case VAL_BOOL:
+ fprintf(f, "bool %d\n", _valBool);
+ break;
+
+ case VAL_NULL:
+ fprintf(f, "null\n");
+ break;
+
+ case VAL_NATIVE:
+ fprintf(f, "native\n");
+ break;
+
+ case VAL_VARIABLE_REF:
+ fprintf(f, "ref\n");
+ break;
+
+ case VAL_OBJECT:
+ fprintf(f, "obj\n");
+ break;
+
+ case VAL_FLOAT:
+ fprintf(f, "float\n");
+ break;
+
+ }
+ fclose(f);
+ */
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::saveAsText(BaseDynamicBuffer *buffer, int indent) {
+ _valIter = _valObject.begin();
+ while (_valIter != _valObject.end()) {
+ buffer->putTextIndent(indent, "PROPERTY {\n");
+ buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", _valIter->_key.c_str());
+ buffer->putTextIndent(indent + 2, "VALUE=\"%s\"\n", _valIter->_value->getString());
+ buffer->putTextIndent(indent, "}\n\n");
+
+ _valIter++;
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// -1 ... left is less, 0 ... equals, 1 ... left is greater
+int ScValue::compare(ScValue *val1, ScValue *val2) {
+ // both natives?
+ if (val1->isNative() && val2->isNative()) {
+ // same class?
+ if (strcmp(val1->getNative()->getClassName(), val2->getNative()->getClassName()) == 0) {
+ return val1->getNative()->scCompare(val2->getNative());
+ } else {
+ return strcmp(val1->getString(), val2->getString());
+ }
+ }
+
+ // both objects?
+ if (val1->isObject() && val2->isObject()) {
+ return -1;
+ }
+
+
+ // null states
+ if (val1->isNULL() && !val2->isNULL()) {
+ return -1;
+ } else if (!val1->isNULL() && val2->isNULL()) {
+ return 1;
+ } else if (val1->isNULL() && val2->isNULL()) {
+ return 0;
+ }
+
+ // one of them is string? convert both to string
+ if (val1->isString() || val2->isString()) {
+ return strcmp(val1->getString(), val2->getString());
+ }
+
+ // one of them is float?
+ if (val1->isFloat() || val2->isFloat()) {
+ if (val1->getFloat() < val2->getFloat()) {
+ return -1;
+ } else if (val1->getFloat() > val2->getFloat()) {
+ return 1;
+ } else {
+ return 0;
+ }
+ }
+
+ // otherwise compare as int's
+ if (val1->getInt() < val2->getInt()) {
+ return -1;
+ } else if (val1->getInt() > val2->getInt()) {
+ return 1;
+ } else {
+ return 0;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+int ScValue::compareStrict(ScValue *val1, ScValue *val2) {
+ if (val1->getTypeTolerant() != val2->getTypeTolerant()) {
+ return -1;
+ } else {
+ return ScValue::compare(val1, val2);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProperty(const char *propName, int value) {
+ ScValue *val = new ScValue(_gameRef, value);
+ bool ret = DID_SUCCEED(setProp(propName, val));
+ delete val;
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProperty(const char *propName, const char *value) {
+ ScValue *val = new ScValue(_gameRef, value);
+ bool ret = DID_SUCCEED(setProp(propName, val));
+ delete val;
+ return ret;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProperty(const char *propName, double value) {
+ ScValue *val = new ScValue(_gameRef, value);
+ bool ret = DID_SUCCEED(setProp(propName, val));
+ delete val;
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProperty(const char *propName, bool value) {
+ ScValue *val = new ScValue(_gameRef, value);
+ bool ret = DID_SUCCEED(setProp(propName, val));
+ delete val;
+ return ret;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool ScValue::setProperty(const char *propName) {
+ ScValue *val = new ScValue(_gameRef);
+ bool ret = DID_SUCCEED(setProp(propName, val));
+ delete val;
+ return ret;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/scriptables/script_value.h b/engines/wintermute/base/scriptables/script_value.h
new file mode 100644
index 0000000000..bf7d9cd8a1
--- /dev/null
+++ b/engines/wintermute/base/scriptables/script_value.h
@@ -0,0 +1,113 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_SCVALUE_H
+#define WINTERMUTE_SCVALUE_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/persistent.h"
+#include "engines/wintermute/base/scriptables/dcscript.h" // Added by ClassView
+#include "common/str.h"
+
+namespace Wintermute {
+
+class ScScript;
+class BaseScriptable;
+
+class ScValue : public BaseClass {
+public:
+ static int compare(ScValue *val1, ScValue *val2);
+ static int compareStrict(ScValue *val1, ScValue *val2);
+ TValType getTypeTolerant();
+ void cleanup(bool ignoreNatives = false);
+ DECLARE_PERSISTENT(ScValue, BaseClass)
+
+ bool _isConstVar;
+ bool saveAsText(BaseDynamicBuffer *buffer, int indent);
+ void setValue(ScValue *val);
+ bool _persistent;
+ bool propExists(const char *name);
+ void copy(ScValue *orig, bool copyWhole = false);
+ void setStringVal(const char *val);
+ TValType getType();
+ bool getBool(bool defaultVal = false);
+ int getInt(int defaultVal = 0);
+ double getFloat(double defaultVal = 0.0f);
+ const char *getString();
+ void *getMemBuffer();
+ BaseScriptable *getNative();
+ bool deleteProp(const char *name);
+ void deleteProps();
+ void CleanProps(bool includingNatives);
+ void setBool(bool val);
+ void setInt(int val);
+ void setFloat(double val);
+ void setString(const char *val);
+ void setString(const Common::String &val);
+ void setNULL();
+ void setNative(BaseScriptable *val, bool persistent = false);
+ void setObject();
+ void setReference(ScValue *val);
+ bool isNULL();
+ bool isNative();
+ bool isString();
+ bool isBool();
+ bool isFloat();
+ bool isInt();
+ bool isObject();
+ bool setProp(const char *name, ScValue *val, bool copyWhole = false, bool setAsConst = false);
+ ScValue *getProp(const char *name);
+ BaseScriptable *_valNative;
+ ScValue *_valRef;
+private:
+ bool _valBool;
+ int _valInt;
+ double _valFloat;
+ char *_valString;
+public:
+ TValType _type;
+ ScValue(BaseGame *inGame);
+ ScValue(BaseGame *inGame, bool Val);
+ ScValue(BaseGame *inGame, int Val);
+ ScValue(BaseGame *inGame, double Val);
+ ScValue(BaseGame *inGame, const char *Val);
+ virtual ~ScValue();
+ Common::HashMap<Common::String, ScValue *> _valObject;
+ Common::HashMap<Common::String, ScValue *>::iterator _valIter;
+
+ bool setProperty(const char *propName, int value);
+ bool setProperty(const char *propName, const char *value);
+ bool setProperty(const char *propName, double value);
+ bool setProperty(const char *propName, bool value);
+ bool setProperty(const char *propName);
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/sound/base_sound.cpp b/engines/wintermute/base/sound/base_sound.cpp
new file mode 100644
index 0000000000..00d07cd3c2
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound.cpp
@@ -0,0 +1,292 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/sound/base_sound.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/sound/base_sound_buffer.h"
+
+namespace Wintermute {
+
+IMPLEMENT_PERSISTENT(BaseSound, false)
+
+BaseSound::BaseSound(BaseGame *inGame) : BaseClass(inGame) {
+ _sound = NULL;
+ _soundFilename = "";
+
+ _soundType = Audio::Mixer::kSFXSoundType;
+ _soundStreamed = false;
+ _soundLooping = false;
+ _soundPlaying = false;
+ _soundPaused = false;
+ _soundFreezePaused = false;
+ _soundPosition = 0;
+ _soundPrivateVolume = 0;
+ _soundLoopStart = 0;
+
+ _sFXType = SFX_NONE;
+ _sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0;
+}
+
+BaseSound::~BaseSound() {
+ if (_sound) {
+ _gameRef->_soundMgr->removeSound(_sound);
+ }
+ _sound = NULL;
+}
+
+bool BaseSound::setSound(const Common::String &filename, Audio::Mixer::SoundType type, bool streamed) {
+ if (_sound) {
+ _gameRef->_soundMgr->removeSound(_sound);
+ _sound = NULL;
+ }
+ _soundFilename = Common::String(); // Set empty
+
+ _sound = _gameRef->_soundMgr->addSound(filename, type, streamed);
+ if (_sound) {
+ _soundFilename = filename;
+
+ _soundType = type;
+ _soundStreamed = streamed;
+
+ return STATUS_OK;
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::setSoundSimple() {
+ _sound = _gameRef->_soundMgr->addSound(_soundFilename, _soundType, _soundStreamed);
+ if (_sound) {
+ if (_soundPosition) {
+ _sound->setPosition(_soundPosition);
+ }
+ _sound->setLooping(_soundLooping);
+ _sound->setPrivateVolume(_soundPrivateVolume);
+ _sound->setLoopStart(_soundLoopStart);
+ _sound->_freezePaused = _soundFreezePaused;
+ if (_soundPlaying) {
+ return _sound->resume();
+ } else {
+ return STATUS_OK;
+ }
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+uint32 BaseSound::getLength() {
+ if (_sound) {
+ return _sound->getLength();
+ } else {
+ return 0;
+ }
+}
+
+bool BaseSound::play(bool looping) {
+ if (_sound) {
+ _soundPaused = false;
+ return _sound->play(looping, _soundPosition);
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::stop() {
+ if (_sound) {
+ _soundPaused = false;
+ return _sound->stop();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::pause(bool freezePaused) {
+ if (_sound) {
+ _soundPaused = true;
+ if (freezePaused) {
+ _sound->_freezePaused = true;
+ }
+ return _sound->pause();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::resume() {
+ if (_sound && _soundPaused) {
+ _soundPaused = false;
+ return _sound->resume();
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::persist(BasePersistenceManager *persistMgr) {
+ if (persistMgr->getIsSaving() && _sound) {
+ _soundPlaying = _sound->isPlaying();
+ _soundLooping = _sound->_looping;
+ _soundPrivateVolume = _sound->_privateVolume;
+ if (_soundPlaying) {
+ _soundPosition = _sound->getPosition();
+ }
+ _soundLoopStart = _sound->_loopStart;
+ _soundFreezePaused = _sound->_freezePaused;
+ }
+
+ if (persistMgr->getIsSaving()) {
+ _sFXType = SFX_NONE;
+ _sFXParam1 = _sFXParam2 = _sFXParam3 = _sFXParam4 = 0;
+ }
+
+ persistMgr->transfer(TMEMBER(_gameRef));
+
+ persistMgr->transfer(TMEMBER(_soundFilename));
+ persistMgr->transfer(TMEMBER(_soundLooping));
+ persistMgr->transfer(TMEMBER(_soundPaused));
+ persistMgr->transfer(TMEMBER(_soundFreezePaused));
+ persistMgr->transfer(TMEMBER(_soundPlaying));
+ persistMgr->transfer(TMEMBER(_soundPosition));
+ persistMgr->transfer(TMEMBER(_soundPrivateVolume));
+ persistMgr->transfer(TMEMBER(_soundStreamed));
+ persistMgr->transfer(TMEMBER_INT(_soundType));
+ persistMgr->transfer(TMEMBER(_soundLoopStart));
+
+ return STATUS_OK;
+}
+
+bool BaseSound::isPlaying() {
+ return _sound && _sound->isPlaying();
+}
+
+bool BaseSound::isPaused() {
+ return _sound && _soundPaused;
+}
+
+bool BaseSound::setPositionTime(uint32 time) {
+ if (!_sound) {
+ return STATUS_FAILED;
+ }
+ _soundPosition = time;
+ bool ret = _sound->setPosition(_soundPosition);
+ if (_sound->isPlaying()) {
+ _soundPosition = 0;
+ }
+ return ret;
+}
+
+uint32 BaseSound::getPositionTime() {
+ if (!_sound) {
+ return 0;
+ }
+
+ if (!_sound->isPlaying()) {
+ return 0;
+ } else {
+ return _sound->getPosition();
+ }
+}
+
+bool BaseSound::setVolumePercent(int percent) {
+ if (!_sound) {
+ return STATUS_FAILED;
+ } else {
+ return _sound->setPrivateVolume(percent * 255 / 100);
+ }
+}
+
+bool BaseSound::setVolume(int volume) {
+ if (!_sound) {
+ return STATUS_FAILED;
+ } else {
+ return _sound->setPrivateVolume(volume);
+ }
+}
+
+bool BaseSound::setPrivateVolume(int volume) {
+ if (!_sound) {
+ return STATUS_FAILED;
+ } else {
+ _sound->_privateVolume = volume;
+ return STATUS_OK;
+ }
+}
+
+int BaseSound::getVolumePercent() {
+ if (!_sound) {
+ return 0;
+ } else {
+ return _sound->_privateVolume * 100 / 255;
+ }
+}
+
+int BaseSound::getVolume() {
+ if (!_sound) {
+ return 0;
+ } else {
+ return _sound->_privateVolume;
+ }
+}
+
+bool BaseSound::setLoopStart(uint32 pos) {
+ if (!_sound) {
+ return STATUS_FAILED;
+ } else {
+ _sound->setLoopStart(pos);
+ return STATUS_OK;
+ }
+}
+
+bool BaseSound::setPan(float pan) {
+ if (_sound) {
+ return _sound->setPan(pan);
+ } else {
+ return STATUS_FAILED;
+ }
+}
+
+bool BaseSound::applyFX(TSFXType type, float param1, float param2, float param3, float param4) {
+ if (!_sound) {
+ return STATUS_OK;
+ }
+
+ if (type != _sFXType || param1 != _sFXParam1 || param2 != _sFXParam2 || param3 != _sFXParam3 || param4 != _sFXParam4) {
+ bool ret = _sound->applyFX(type, param1, param2, param3, param4);
+
+ _sFXType = type;
+ _sFXParam1 = param1;
+ _sFXParam2 = param2;
+ _sFXParam3 = param3;
+ _sFXParam4 = param4;
+
+ return ret;
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound.h b/engines/wintermute/base/sound/base_sound.h
new file mode 100644
index 0000000000..637061b7cc
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound.h
@@ -0,0 +1,87 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SOUND_H
+#define WINTERMUTE_BASE_SOUND_H
+
+#include "engines/wintermute/base/base.h"
+#include "engines/wintermute/dctypes.h" // Added by ClassView
+#include "engines/wintermute/persistent.h"
+#include "audio/mixer.h"
+
+namespace Wintermute {
+
+class BaseSoundBuffer;
+class BaseSound : public BaseClass {
+public:
+ bool setPan(float pan);
+ int getVolume();
+ int getVolumePercent();
+ bool setVolumePercent(int percent);
+ bool setVolume(int volume);
+ bool setPrivateVolume(int volume);
+ bool setLoopStart(uint32 pos);
+ uint32 getPositionTime();
+ bool setPositionTime(uint32 time);
+ bool isPlaying();
+ bool isPaused();
+ DECLARE_PERSISTENT(BaseSound, BaseClass)
+ bool resume();
+ bool pause(bool freezePaused = false);
+ bool stop();
+ bool play(bool looping = false);
+ uint32 getLength();
+ const char *getFilename() { return _soundFilename.c_str(); }
+ bool setSoundSimple();
+ bool setSound(const Common::String &filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false);
+ BaseSound(BaseGame *inGame);
+ virtual ~BaseSound();
+
+ bool applyFX(TSFXType type = SFX_NONE, float param1 = 0, float param2 = 0, float param3 = 0, float param4 = 0);
+private:
+ Common::String _soundFilename;
+ bool _soundStreamed;
+ Audio::Mixer::SoundType _soundType;
+ int _soundPrivateVolume;
+ uint32 _soundLoopStart;
+ uint32 _soundPosition;
+ bool _soundPlaying;
+ bool _soundLooping;
+ bool _soundPaused;
+ bool _soundFreezePaused;
+ TSFXType _sFXType;
+ float _sFXParam1;
+ float _sFXParam2;
+ float _sFXParam3;
+ float _sFXParam4;
+ BaseSoundBuffer *_sound;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/sound/base_sound_buffer.cpp b/engines/wintermute/base/sound/base_sound_buffer.cpp
new file mode 100644
index 0000000000..3fd6c4d5f2
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound_buffer.cpp
@@ -0,0 +1,297 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/file/base_file.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/sound/base_sound_buffer.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/utils/utils.h"
+#include "engines/wintermute/wintermute.h"
+#include "audio/audiostream.h"
+#include "audio/mixer.h"
+#include "audio/decoders/vorbis.h"
+#include "audio/decoders/wave.h"
+#include "audio/decoders/raw.h"
+#include "common/system.h"
+#include "common/substream.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+#define MAX_NONSTREAMED_FILE_SIZE 1024*1024
+
+//////////////////////////////////////////////////////////////////////////
+BaseSoundBuffer::BaseSoundBuffer(BaseGame *inGame) : BaseClass(inGame) {
+ _stream = NULL;
+ _handle = NULL;
+// _sync = NULL;
+
+ _streamed = false;
+ _filename = "";
+ _file = NULL;
+ _privateVolume = 255;
+ _volume = 255;
+
+ _looping = false;
+ _loopStart = 0;
+ _startPos = 0;
+
+ _type = Audio::Mixer::kSFXSoundType;
+
+ _freezePaused = false;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSoundBuffer::~BaseSoundBuffer() {
+ stop();
+
+ if (_handle) {
+ g_system->getMixer()->stopHandle(*_handle);
+ delete _handle;
+ _handle = NULL;
+ }
+ delete _stream;
+ _stream = NULL;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSoundBuffer::setStreaming(bool streamed, uint32 numBlocks, uint32 blockSize) {
+ _streamed = streamed;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::loadFromFile(const Common::String &filename, bool forceReload) {
+ debugC(kWintermuteDebugAudio, "BSoundBuffer::LoadFromFile(%s,%d)", filename.c_str(), forceReload);
+
+ // Load a file, but avoid having the File-manager handle the disposal of it.
+ _file = BaseFileManager::getEngineInstance()->openFile(filename, true, false);
+ if (!_file) {
+ _gameRef->LOG(0, "Error opening sound file '%s'", filename.c_str());
+ return STATUS_FAILED;
+ }
+ Common::String strFilename(filename);
+ strFilename.toLowercase();
+ if (strFilename.hasSuffix(".ogg")) {
+ _stream = Audio::makeVorbisStream(_file, DisposeAfterUse::YES);
+ } else if (strFilename.hasSuffix(".wav")) {
+ int waveSize, waveRate;
+ byte waveFlags;
+ uint16 waveType;
+
+ if (Audio::loadWAVFromStream(*_file, waveSize, waveRate, waveFlags, &waveType)) {
+ if (waveType == 1) {
+ // We need to wrap the file in a substream to make sure the size is right.
+ _file = new Common::SeekableSubReadStream(_file, 0, waveSize);
+ _stream = Audio::makeRawStream(_file, waveRate, waveFlags, DisposeAfterUse::YES);
+ } else {
+ error("BSoundBuffer::LoadFromFile - WAVE not supported yet for %s with type %d", filename.c_str(), waveType);
+ }
+ }
+ } else {
+ error("BSoundBuffer::LoadFromFile - Unknown filetype for %s", filename.c_str());
+ }
+ if (!_stream) {
+ return STATUS_FAILED;
+ }
+ _filename = filename;
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::play(bool looping, uint32 startSample) {
+ if (_handle) {
+ g_system->getMixer()->stopHandle(*_handle);
+ delete _handle;
+ _handle = NULL;
+ }
+ // Store the loop-value for save-games.
+ setLooping(looping);
+ if (_stream) {
+ _stream->seek(startSample);
+ _handle = new Audio::SoundHandle;
+ if (_looping) {
+ Audio::AudioStream *loopStream = new Audio::LoopingAudioStream(_stream, 0, DisposeAfterUse::NO);
+ g_system->getMixer()->playStream(_type, _handle, loopStream, -1, _volume, 0, DisposeAfterUse::YES);
+ } else {
+ g_system->getMixer()->playStream(_type, _handle, _stream, -1, _volume, 0, DisposeAfterUse::NO);
+ }
+ }
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSoundBuffer::setLooping(bool looping) {
+ if (isPlaying()) {
+ // This warning is here, to see if this is ever the case.
+ warning("BSoundBuffer::SetLooping(%d) - won't change a playing sound", looping); // TODO
+ }
+ _looping = looping;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::resume() {
+ // If the sound was paused while active:
+ if (_stream && _handle) {
+ g_system->getMixer()->pauseHandle(*_handle, false);
+ } else if (_stream) { // Otherwise we come from a savegame, and thus have no handle
+ play(_looping, _startPos);
+ } else {
+ warning("BaseSoundBuffer::resume - Called without a handle or a stream");
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::stop() {
+ if (_stream && _handle) {
+ g_system->getMixer()->stopHandle(*_handle);
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::pause() {
+ if (_stream && _handle) {
+ g_system->getMixer()->pauseHandle(*_handle, true);
+ }
+ return STATUS_OK;
+
+}
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseSoundBuffer::getLength() {
+ if (_stream) {
+ uint32 len = _stream->getLength().msecs();
+ return len * 1000;
+ }
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSoundBuffer::setType(Audio::Mixer::SoundType type) {
+ _type = type;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSoundBuffer::updateVolume() {
+ setVolume(_privateVolume);
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::setVolume(int volume) {
+ _volume = volume * _gameRef->_soundMgr->getMasterVolume() / 255;
+ if (_stream && _handle) {
+ byte vol = (byte)(_volume);
+ g_system->getMixer()->setChannelVolume(*_handle, vol);
+ }
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::setPrivateVolume(int volume) {
+ _privateVolume = volume;
+ return setVolume(_privateVolume);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::isPlaying() {
+ if (_stream && _handle) {
+ return _freezePaused || g_system->getMixer()->isSoundHandleActive(*_handle);
+ } else {
+ return false;
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+uint32 BaseSoundBuffer::getPosition() {
+ if (_stream && _handle) {
+ uint32 pos = g_system->getMixer()->getSoundElapsedTime(*_handle);
+ return pos;
+ }
+ return 0;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::setPosition(uint32 pos) {
+ if (isPlaying()) {
+ warning("BaseSoundBuffer::SetPosition - not implemented for playing sounds yet.");
+ }
+ _startPos = pos;
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::setLoopStart(uint32 pos) {
+ _loopStart = pos;
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::setPan(float pan) {
+ if (_handle) {
+ g_system->getMixer()->setChannelBalance(*_handle, (int8)(pan * 127));
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundBuffer::applyFX(TSFXType type, float param1, float param2, float param3, float param4) {
+ // This function was already stubbed out in WME Lite, and thus isn't reimplemented here either.
+ switch (type) {
+ case SFX_ECHO:
+ //warning("BaseSoundBuffer::ApplyFX(SFX_ECHO, %f, %f, %f, %f) - not implemented yet", param1, param2, param3, param4);
+ break;
+
+ case SFX_REVERB:
+ //warning("BaseSoundBuffer::ApplyFX(SFX_REVERB, %f, %f, %f, %f) - not implemented yet", param1, param2, param3, param4);
+ break;
+
+ default:
+ break;
+ }
+ return STATUS_OK;
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_buffer.h b/engines/wintermute/base/sound/base_sound_buffer.h
new file mode 100644
index 0000000000..9c39f4c34b
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound_buffer.h
@@ -0,0 +1,100 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SOUNDBUFFER_H
+#define WINTERMUTE_BASE_SOUNDBUFFER_H
+
+
+#include "engines/wintermute/base/base.h"
+#include "audio/mixer.h"
+#include "common/stream.h"
+
+namespace Audio {
+class SeekableAudioStream;
+class SoundHandle;
+}
+
+namespace Wintermute {
+
+class BaseFile;
+class BaseSoundBuffer : public BaseClass {
+public:
+
+ BaseSoundBuffer(BaseGame *inGame);
+ virtual ~BaseSoundBuffer();
+
+ bool pause();
+ bool play(bool looping = false, uint32 startSample = 0);
+ bool resume();
+ bool stop();
+ bool isPlaying();
+
+ void setLooping(bool looping);
+
+ uint32 getPosition();
+ bool setPosition(uint32 pos);
+ uint32 getLength();
+
+ bool setLoopStart(uint32 pos);
+ uint32 getLoopStart() const {
+ return _loopStart;
+ }
+
+ bool setPan(float pan);
+ bool setPrivateVolume(int colume);
+ bool setVolume(int colume);
+ void updateVolume();
+
+ void setType(Audio::Mixer::SoundType Type);
+
+ bool loadFromFile(const Common::String &filename, bool forceReload = false);
+ void setStreaming(bool streamed, uint32 numBlocks = 0, uint32 blockSize = 0);
+ bool applyFX(TSFXType type, float param1, float param2, float param3, float param4);
+
+ //HSTREAM _stream;
+ //HSYNC _sync;
+ Audio::SeekableAudioStream *_stream;
+ Audio::SoundHandle *_handle;
+
+ bool _freezePaused;
+ uint32 _loopStart;
+ Audio::Mixer::SoundType _type;
+ bool _looping;
+
+ int _privateVolume;
+private:
+ uint32 _startPos;
+ Common::String _filename;
+ bool _streamed;
+ Common::SeekableReadStream *_file;
+ int _volume;
+};
+
+} // end of namespace Wintermute
+
+#endif
diff --git a/engines/wintermute/base/sound/base_sound_manager.cpp b/engines/wintermute/base/sound/base_sound_manager.cpp
new file mode 100644
index 0000000000..f7788cd255
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound_manager.cpp
@@ -0,0 +1,282 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#include "engines/wintermute/base/sound/base_sound_manager.h"
+#include "engines/wintermute/base/base_engine.h"
+#include "engines/wintermute/utils/path_util.h"
+#include "engines/wintermute/utils/string_util.h"
+#include "engines/wintermute/base/base_game.h"
+#include "engines/wintermute/base/base_file_manager.h"
+#include "engines/wintermute/base/sound/base_sound_buffer.h"
+#include "engines/wintermute/wintermute.h"
+#include "common/config-manager.h"
+#include "audio/mixer.h"
+
+namespace Wintermute {
+
+//////////////////////////////////////////////////////////////////////
+// Construction/Destruction
+//////////////////////////////////////////////////////////////////////
+
+//IMPLEMENT_PERSISTENT(BaseSoundMgr, true);
+
+//////////////////////////////////////////////////////////////////////////
+BaseSoundMgr::BaseSoundMgr(BaseGame *inGame) : BaseClass(inGame) {
+ _soundAvailable = false;
+ _volumeMaster = 255;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+BaseSoundMgr::~BaseSoundMgr() {
+ saveSettings();
+ cleanup();
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::cleanup() {
+ for (uint32 i = 0; i < _sounds.size(); i++) {
+ delete _sounds[i];
+ }
+ _sounds.clear();
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+void BaseSoundMgr::saveSettings() {
+ if (_soundAvailable) {
+ ConfMan.setInt("master_volume", _volumeMaster);
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::initialize() {
+ _soundAvailable = false;
+
+ if (!g_system->getMixer()->isReady()) {
+ return STATUS_FAILED;
+ }
+ _volumeMaster = (ConfMan.hasKey("master_volume") ? ConfMan.getInt("master_volume") : 255);
+ _soundAvailable = true;
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+BaseSoundBuffer *BaseSoundMgr::addSound(const Common::String &filename, Audio::Mixer::SoundType type, bool streamed) {
+ if (!_soundAvailable) {
+ return NULL;
+ }
+
+ BaseSoundBuffer *sound;
+
+ Common::String useFilename = filename;
+ // try to switch WAV to OGG file (if available)
+ AnsiString ext = PathUtil::getExtension(filename);
+ if (StringUtil::compareNoCase(ext, "wav")) {
+ AnsiString path = PathUtil::getDirectoryName(filename);
+ AnsiString name = PathUtil::getFileNameWithoutExtension(filename);
+
+ AnsiString newFile = PathUtil::combine(path, name + "ogg");
+ if (BaseFileManager::getEngineInstance()->hasFile(newFile)) {
+ useFilename = newFile;
+ }
+ }
+
+ sound = new BaseSoundBuffer(_gameRef);
+ if (!sound) {
+ return NULL;
+ }
+
+ sound->setStreaming(streamed);
+ sound->setType(type);
+
+
+ bool res = sound->loadFromFile(useFilename);
+ if (DID_FAIL(res)) {
+ _gameRef->LOG(res, "Error loading sound '%s'", useFilename.c_str());
+ delete sound;
+ return NULL;
+ }
+
+ // Make sure the master-volume is applied to the sound.
+ sound->updateVolume();
+
+ // register sound
+ _sounds.push_back(sound);
+
+ return sound;
+
+ return NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::addSound(BaseSoundBuffer *sound, Audio::Mixer::SoundType type) {
+ if (!sound) {
+ return STATUS_FAILED;
+ }
+
+ // Make sure the master-volume is applied to the sound.
+ sound->updateVolume();
+
+ // register sound
+ _sounds.push_back(sound);
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::removeSound(BaseSoundBuffer *sound) {
+ for (uint32 i = 0; i < _sounds.size(); i++) {
+ if (_sounds[i] == sound) {
+ delete _sounds[i];
+ _sounds.remove_at(i);
+ return STATUS_OK;
+ }
+ }
+
+ return STATUS_FAILED;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::setVolume(Audio::Mixer::SoundType type, int volume) {
+ if (!_soundAvailable) {
+ return STATUS_OK;
+ }
+
+ switch (type) {
+ case Audio::Mixer::kSFXSoundType:
+ ConfMan.setInt("sfx_volume", volume);
+ break;
+ case Audio::Mixer::kSpeechSoundType:
+ ConfMan.setInt("speech_volume", volume);
+ break;
+ case Audio::Mixer::kMusicSoundType:
+ ConfMan.setInt("music_volume", volume);
+ break;
+ case Audio::Mixer::kPlainSoundType:
+ error("Plain sound type shouldn't be used in WME");
+ }
+ g_engine->syncSoundSettings();
+
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::setVolumePercent(Audio::Mixer::SoundType type, byte percent) {
+ return setVolume(type, percent * 255 / 100);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+byte BaseSoundMgr::getVolumePercent(Audio::Mixer::SoundType type) {
+ int volume = 0;
+
+ switch (type) {
+ case Audio::Mixer::kSFXSoundType:
+ case Audio::Mixer::kSpeechSoundType:
+ case Audio::Mixer::kMusicSoundType:
+ volume = g_system->getMixer()->getVolumeForSoundType(type);
+ break;
+ default:
+ error("Sound-type not set");
+ break;
+ }
+
+ return (byte)(volume * 100 / 255);
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::setMasterVolume(byte value) {
+ _volumeMaster = value;
+ for (uint32 i = 0; i < _sounds.size(); i++) {
+ _sounds[i]->updateVolume();
+ }
+ return STATUS_OK;
+}
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::setMasterVolumePercent(byte percent) {
+ setMasterVolume(percent * 255 / 100);
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+byte BaseSoundMgr::getMasterVolumePercent() {
+ return getMasterVolume() * 100 / 255;
+}
+
+//////////////////////////////////////////////////////////////////////////
+byte BaseSoundMgr::getMasterVolume() {
+ return (byte)_volumeMaster;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::pauseAll(bool includingMusic) {
+
+ for (uint32 i = 0; i < _sounds.size(); i++) {
+ if (_sounds[i]->isPlaying() && (_sounds[i]->_type != Audio::Mixer::kMusicSoundType || includingMusic)) {
+ _sounds[i]->pause();
+ _sounds[i]->_freezePaused = true;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+bool BaseSoundMgr::resumeAll() {
+
+ for (uint32 i = 0; i < _sounds.size(); i++) {
+ if (_sounds[i]->_freezePaused) {
+ _sounds[i]->resume();
+ _sounds[i]->_freezePaused = false;
+ }
+ }
+
+ return STATUS_OK;
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+float BaseSoundMgr::posToPan(int x, int y) {
+ float relPos = (float)x / ((float)_gameRef->_renderer->_width);
+
+ float minPan = -0.7f;
+ float maxPan = 0.7f;
+
+ return minPan + relPos * (maxPan - minPan);
+}
+
+} // end of namespace Wintermute
diff --git a/engines/wintermute/base/sound/base_sound_manager.h b/engines/wintermute/base/sound/base_sound_manager.h
new file mode 100644
index 0000000000..36a729b5ae
--- /dev/null
+++ b/engines/wintermute/base/sound/base_sound_manager.h
@@ -0,0 +1,68 @@
+/* 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.
+ *
+ */
+
+/*
+ * This file is based on WME Lite.
+ * http://dead-code.org/redir.php?target=wmelite
+ * Copyright (c) 2011 Jan Nedoma
+ */
+
+#ifndef WINTERMUTE_BASE_SOUNDMGR_H
+#define WINTERMUTE_BASE_SOUNDMGR_H
+
+#include "engines/wintermute/coll_templ.h"
+#include "engines/wintermute/base/base.h"
+#include "audio/mixer.h"
+#include "common/array.h"
+
+namespace Wintermute {
+class BaseSoundBuffer;
+class BaseSoundMgr : public BaseClass {
+public:
+ float posToPan(int x, int y);
+ bool resumeAll();
+ bool pauseAll(bool includingMusic = true);
+ bool cleanup();
+ //DECLARE_PERSISTENT(BaseSoundMgr, BaseClass);
+ byte getMasterVolumePercent();
+ byte getMasterVolume();
+ bool setMasterVolume(byte percent);
+ bool setMasterVolumePercent(byte percent);
+ byte getVolumePercent(Audio::Mixer::SoundType type);
+ bool setVolumePercent(Audio::Mixer::SoundType type, byte percent);
+ bool setVolume(Audio::Mixer::SoundType type, int volume);
+ uint32 _volumeOriginal;
+ int _volumeMaster;
+ bool removeSound(BaseSoundBuffer *sound);
+ BaseSoundBuffer *addSound(const Common::String &filename, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType, bool streamed = false);
+ bool addSound(BaseSoundBuffer *sound, Audio::Mixer::SoundType type = Audio::Mixer::kSFXSoundType);
+ bool initialize();
+ bool _soundAvailable;
+ BaseSoundMgr(BaseGame *inGame);
+ virtual ~BaseSoundMgr();
+ Common::Array<BaseSoundBuffer *> _sounds;
+ void saveSettings();
+};
+
+} // end of namespace Wintermute
+
+#endif