From b4090ead4d4334e08725323ff72fd355c93b63d5 Mon Sep 17 00:00:00 2001 From: Willem Jan Palenstijn Date: Tue, 4 Sep 2012 22:17:23 +0200 Subject: [PATCH] WINTERMUTE: Convert CRLF to LF --- engines/wintermute/ad/ad_actor.cpp | 2920 +++--- engines/wintermute/ad/ad_actor.h | 216 +- engines/wintermute/ad/ad_entity.cpp | 2242 ++--- engines/wintermute/ad/ad_entity.h | 136 +- engines/wintermute/ad/ad_game.cpp | 4560 ++++----- engines/wintermute/ad/ad_game.h | 326 +- engines/wintermute/ad/ad_inventory.cpp | 272 +- engines/wintermute/ad/ad_inventory.h | 104 +- engines/wintermute/ad/ad_inventory_box.cpp | 776 +- engines/wintermute/ad/ad_inventory_box.h | 130 +- engines/wintermute/ad/ad_item.cpp | 1626 +-- engines/wintermute/ad/ad_item.h | 138 +- engines/wintermute/ad/ad_layer.cpp | 1128 +-- engines/wintermute/ad/ad_layer.h | 116 +- engines/wintermute/ad/ad_node_state.cpp | 392 +- engines/wintermute/ad/ad_node_state.h | 120 +- engines/wintermute/ad/ad_object.cpp | 2598 ++--- engines/wintermute/ad/ad_object.h | 248 +- engines/wintermute/ad/ad_path.cpp | 240 +- engines/wintermute/ad/ad_path.h | 112 +- engines/wintermute/ad/ad_path_point.cpp | 150 +- engines/wintermute/ad/ad_path_point.h | 100 +- engines/wintermute/ad/ad_region.cpp | 794 +- engines/wintermute/ad/ad_region.h | 116 +- engines/wintermute/ad/ad_response.cpp | 292 +- engines/wintermute/ad/ad_response.h | 122 +- engines/wintermute/ad/ad_response_box.cpp | 1424 +-- engines/wintermute/ad/ad_response_box.h | 174 +- engines/wintermute/ad/ad_response_context.cpp | 142 +- engines/wintermute/ad/ad_response_context.h | 100 +- engines/wintermute/ad/ad_rot_level.cpp | 322 +- engines/wintermute/ad/ad_rot_level.h | 98 +- engines/wintermute/ad/ad_scale_level.cpp | 318 +- engines/wintermute/ad/ad_scale_level.h | 100 +- engines/wintermute/ad/ad_scene.cpp | 5972 +++++------ engines/wintermute/ad/ad_scene.h | 362 +- engines/wintermute/ad/ad_scene_node.cpp | 164 +- engines/wintermute/ad/ad_scene_node.h | 108 +- engines/wintermute/ad/ad_scene_state.cpp | 190 +- engines/wintermute/ad/ad_scene_state.h | 102 +- engines/wintermute/ad/ad_sentence.cpp | 720 +- engines/wintermute/ad/ad_sentence.h | 170 +- engines/wintermute/ad/ad_sprite_set.cpp | 712 +- engines/wintermute/ad/ad_sprite_set.h | 106 +- engines/wintermute/ad/ad_talk_def.cpp | 570 +- engines/wintermute/ad/ad_talk_def.h | 116 +- engines/wintermute/ad/ad_talk_holder.cpp | 804 +- engines/wintermute/ad/ad_talk_holder.h | 114 +- engines/wintermute/ad/ad_talk_node.cpp | 590 +- engines/wintermute/ad/ad_talk_node.h | 126 +- engines/wintermute/ad/ad_types.h | 214 +- engines/wintermute/ad/ad_waypoint_group.cpp | 540 +- engines/wintermute/ad/ad_waypoint_group.h | 116 +- engines/wintermute/base/base.cpp | 370 +- engines/wintermute/base/base.h | 124 +- engines/wintermute/base/base_active_rect.cpp | 220 +- engines/wintermute/base/base_active_rect.h | 120 +- .../wintermute/base/base_dynamic_buffer.cpp | 408 +- engines/wintermute/base/base_dynamic_buffer.h | 132 +- engines/wintermute/base/base_fader.cpp | 388 +- engines/wintermute/base/base_fader.h | 126 +- engines/wintermute/base/base_file_manager.cpp | 680 +- engines/wintermute/base/base_file_manager.h | 152 +- engines/wintermute/base/base_frame.cpp | 1520 +-- engines/wintermute/base/base_frame.h | 146 +- engines/wintermute/base/base_game.cpp | 8966 ++++++++--------- engines/wintermute/base/base_game.h | 724 +- .../wintermute/base/base_keyboard_state.cpp | 618 +- engines/wintermute/base/base_keyboard_state.h | 150 +- engines/wintermute/base/base_named_object.cpp | 142 +- engines/wintermute/base/base_named_object.h | 102 +- engines/wintermute/base/base_object.cpp | 2492 ++--- engines/wintermute/base/base_object.h | 294 +- engines/wintermute/base/base_parser.cpp | 934 +- engines/wintermute/base/base_parser.h | 176 +- .../base/base_persistence_manager.cpp | 1656 +-- .../base/base_persistence_manager.h | 236 +- engines/wintermute/base/base_point.cpp | 126 +- engines/wintermute/base/base_point.h | 100 +- engines/wintermute/base/base_quick_msg.cpp | 114 +- engines/wintermute/base/base_quick_msg.h | 96 +- engines/wintermute/base/base_region.cpp | 1070 +- engines/wintermute/base/base_region.h | 138 +- .../base/base_save_thumb_helper.cpp | 160 +- .../wintermute/base/base_save_thumb_helper.h | 102 +- .../wintermute/base/base_script_holder.cpp | 1004 +- engines/wintermute/base/base_script_holder.h | 152 +- engines/wintermute/base/base_scriptable.cpp | 382 +- engines/wintermute/base/base_scriptable.h | 166 +- engines/wintermute/base/base_sprite.cpp | 1628 +-- engines/wintermute/base/base_sprite.h | 180 +- engines/wintermute/base/base_string_table.cpp | 510 +- engines/wintermute/base/base_string_table.h | 110 +- engines/wintermute/base/base_sub_frame.cpp | 1310 +-- engines/wintermute/base/base_sub_frame.h | 184 +- .../wintermute/base/base_surface_storage.cpp | 414 +- .../wintermute/base/base_surface_storage.h | 114 +- .../base/base_transition_manager.cpp | 272 +- .../wintermute/base/base_transition_manager.h | 108 +- engines/wintermute/base/base_viewport.cpp | 196 +- engines/wintermute/base/base_viewport.h | 110 +- .../wintermute/base/file/base_disk_file.cpp | 392 +- engines/wintermute/base/file/base_disk_file.h | 82 +- engines/wintermute/base/file/base_file.cpp | 136 +- engines/wintermute/base/file/base_file.h | 134 +- .../wintermute/base/file/base_file_entry.cpp | 146 +- .../wintermute/base/file/base_file_entry.h | 120 +- engines/wintermute/base/file/base_package.cpp | 552 +- engines/wintermute/base/file/base_package.h | 180 +- .../wintermute/base/file/base_resources.cpp | 5660 +++++------ engines/wintermute/base/file/base_resources.h | 90 +- .../base/file/base_save_thumb_file.cpp | 308 +- .../base/file/base_save_thumb_file.h | 104 +- engines/wintermute/base/file/dcpackage.h | 160 +- engines/wintermute/base/font/base_font.cpp | 280 +- engines/wintermute/base/font/base_font.h | 122 +- .../wintermute/base/font/base_font_bitmap.cpp | 1178 +-- .../wintermute/base/font/base_font_bitmap.h | 142 +- .../base/font/base_font_storage.cpp | 284 +- .../wintermute/base/font/base_font_storage.h | 110 +- .../base/font/base_font_truetype.cpp | 1210 +-- .../wintermute/base/font/base_font_truetype.h | 304 +- engines/wintermute/base/gfx/base_image.cpp | 462 +- engines/wintermute/base/gfx/base_image.h | 144 +- engines/wintermute/base/gfx/base_renderer.cpp | 762 +- engines/wintermute/base/gfx/base_renderer.h | 442 +- engines/wintermute/base/gfx/base_surface.cpp | 298 +- engines/wintermute/base/gfx/base_surface.h | 198 +- .../base/gfx/osystem/base_render_osystem.cpp | 1208 +-- .../base/gfx/osystem/base_render_osystem.h | 262 +- .../base/gfx/osystem/base_surface_osystem.cpp | 858 +- .../base/gfx/osystem/base_surface_osystem.h | 198 +- .../base/particles/part_emitter.cpp | 2512 ++--- .../wintermute/base/particles/part_emitter.h | 280 +- .../wintermute/base/particles/part_force.cpp | 130 +- .../wintermute/base/particles/part_force.h | 114 +- .../base/particles/part_particle.cpp | 538 +- .../wintermute/base/particles/part_particle.h | 180 +- .../wintermute/base/scriptables/dcscript.h | 282 +- .../wintermute/base/scriptables/script.cpp | 2934 +++--- engines/wintermute/base/scriptables/script.h | 348 +- .../base/scriptables/script_engine.cpp | 1220 +-- .../base/scriptables/script_engine.h | 270 +- .../base/scriptables/script_ext_array.cpp | 504 +- .../base/scriptables/script_ext_array.h | 112 +- .../base/scriptables/script_ext_date.cpp | 586 +- .../base/scriptables/script_ext_date.h | 108 +- .../base/scriptables/script_ext_file.cpp | 1658 +-- .../base/scriptables/script_ext_file.h | 132 +- .../base/scriptables/script_ext_math.cpp | 590 +- .../base/scriptables/script_ext_math.h | 106 +- .../scriptables/script_ext_mem_buffer.cpp | 1058 +- .../base/scriptables/script_ext_mem_buffer.h | 120 +- .../base/scriptables/script_ext_object.cpp | 134 +- .../base/scriptables/script_ext_object.h | 92 +- .../base/scriptables/script_ext_string.cpp | 872 +- .../base/scriptables/script_ext_string.h | 116 +- .../base/scriptables/script_stack.cpp | 464 +- .../base/scriptables/script_stack.h | 132 +- .../base/scriptables/script_value.cpp | 1990 ++-- .../base/scriptables/script_value.h | 226 +- engines/wintermute/base/sound/base_sound.cpp | 584 +- engines/wintermute/base/sound/base_sound.h | 174 +- .../base/sound/base_sound_buffer.cpp | 594 +- .../wintermute/base/sound/base_sound_buffer.h | 200 +- .../base/sound/base_sound_manager.cpp | 564 +- .../base/sound/base_sound_manager.h | 136 +- engines/wintermute/coll_templ.h | 172 +- engines/wintermute/dcgf.h | 102 +- engines/wintermute/dctypes.h | 450 +- engines/wintermute/math/math_util.cpp | 104 +- engines/wintermute/math/math_util.h | 84 +- engines/wintermute/math/matrix4.cpp | 172 +- engines/wintermute/math/matrix4.h | 100 +- engines/wintermute/math/vector2.cpp | 110 +- engines/wintermute/math/vector2.h | 150 +- engines/wintermute/platform_osystem.cpp | 524 +- engines/wintermute/platform_osystem.h | 146 +- engines/wintermute/system/sys_class.cpp | 440 +- engines/wintermute/system/sys_class.h | 260 +- .../wintermute/system/sys_class_registry.cpp | 670 +- .../wintermute/system/sys_class_registry.h | 212 +- engines/wintermute/system/sys_instance.cpp | 98 +- engines/wintermute/system/sys_instance.h | 136 +- engines/wintermute/ui/ui_button.cpp | 2416 ++--- engines/wintermute/ui/ui_button.h | 160 +- engines/wintermute/ui/ui_edit.cpp | 1902 ++-- engines/wintermute/ui/ui_edit.h | 144 +- engines/wintermute/ui/ui_entity.cpp | 732 +- engines/wintermute/ui/ui_entity.h | 118 +- engines/wintermute/ui/ui_object.cpp | 1300 +-- engines/wintermute/ui/ui_object.h | 170 +- engines/wintermute/ui/ui_text.cpp | 1044 +- engines/wintermute/ui/ui_text.h | 120 +- engines/wintermute/ui/ui_tiled_image.cpp | 786 +- engines/wintermute/ui/ui_tiled_image.h | 126 +- engines/wintermute/ui/ui_window.cpp | 2888 +++--- engines/wintermute/ui/ui_window.h | 188 +- engines/wintermute/utils/crc.cpp | 474 +- engines/wintermute/utils/crc.h | 170 +- engines/wintermute/utils/path_util.cpp | 202 +- engines/wintermute/utils/path_util.h | 98 +- engines/wintermute/utils/string_util.cpp | 464 +- engines/wintermute/utils/string_util.h | 112 +- engines/wintermute/utils/utils.cpp | 522 +- engines/wintermute/utils/utils.h | 128 +- engines/wintermute/wintypes.h | 106 +- 207 files changed, 59478 insertions(+), 59478 deletions(-) diff --git a/engines/wintermute/ad/ad_actor.cpp b/engines/wintermute/ad/ad_actor.cpp index 63b153241637..9087d6684499 100644 --- a/engines/wintermute/ad/ad_actor.cpp +++ b/engines/wintermute/ad/ad_actor.cpp @@ -1,1460 +1,1460 @@ -/* 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_actor.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_scene.h" -#include "engines/wintermute/ad/ad_entity.h" -#include "engines/wintermute/ad/ad_sprite_set.h" -#include "engines/wintermute/ad/ad_waypoint_group.h" -#include "engines/wintermute/ad/ad_path.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/base/base_region.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/particles/part_emitter.h" -#include "engines/wintermute/base/base_engine.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdActor, false) - - -////////////////////////////////////////////////////////////////////////// -AdActor::AdActor(BaseGame *inGame) : AdTalkHolder(inGame) { - _path = new AdPath(_gameRef); - - _type = OBJECT_ACTOR; - _dir = DI_LEFT; - - _walkSprite = NULL; - _standSprite = NULL; - _turnLeftSprite = NULL; - _turnRightSprite = NULL; - - _targetPoint = new BasePoint; - _afterWalkDir = DI_NONE; - - _animSprite2 = NULL; - - setDefaultAnimNames(); -} - -////////////////////////////////////////////////////////////////////////// -bool AdActor::setDefaultAnimNames() { - _talkAnimName = "talk"; - _idleAnimName = "idle"; - _walkAnimName = "walk"; - _turnLeftAnimName = "turnleft"; - _turnRightAnimName = "turnright"; - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -AdActor::~AdActor() { - delete _path; - delete _targetPoint; - _path = NULL; - _targetPoint = NULL; - - delete _walkSprite; - delete _standSprite; - delete _turnLeftSprite; - delete _turnRightSprite; - _walkSprite = NULL; - _standSprite = NULL; - _turnLeftSprite = NULL; - _turnRightSprite = NULL; - - _animSprite2 = NULL; // ref only - - for (uint32 i = 0; i < _talkSprites.size(); i++) { - delete _talkSprites[i]; - } - _talkSprites.clear(); - - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - delete _talkSpritesEx[i]; - } - _talkSpritesEx.clear(); - - for (uint32 i = 0; i < _anims.size(); i++) { - delete _anims[i]; - _anims[i] = NULL; - } - _anims.clear(); - -} - - -////////////////////////////////////////////////////////////////////////// -bool AdActor::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdActor::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 ACTOR file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(ACTOR) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(NAME) -TOKEN_DEF(SCALABLE) -TOKEN_DEF(REGISTRABLE) -TOKEN_DEF(INTERACTIVE) -TOKEN_DEF(SHADOWABLE) -TOKEN_DEF(COLORABLE) -TOKEN_DEF(ACTIVE) -TOKEN_DEF(WALK) -TOKEN_DEF(STAND) -TOKEN_DEF(TALK_SPECIAL) -TOKEN_DEF(TALK) -TOKEN_DEF(TURN_LEFT) -TOKEN_DEF(TURN_RIGHT) -TOKEN_DEF(EVENTS) -TOKEN_DEF(FONT) -TOKEN_DEF(CURSOR) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(SOUND_VOLUME) -TOKEN_DEF(SOUND_PANNING) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(BLOCKED_REGION) -TOKEN_DEF(WAYPOINTS) -TOKEN_DEF(IGNORE_ITEMS) -TOKEN_DEF(ROTABLE) -TOKEN_DEF(ROTATABLE) -TOKEN_DEF(ALPHA_COLOR) -TOKEN_DEF(SCALE) -TOKEN_DEF(RELATIVE_SCALE) -TOKEN_DEF(ALPHA) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(ANIMATION) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdActor::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ACTOR) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(SCALABLE) - TOKEN_TABLE(REGISTRABLE) - TOKEN_TABLE(INTERACTIVE) - TOKEN_TABLE(SHADOWABLE) - TOKEN_TABLE(COLORABLE) - TOKEN_TABLE(ACTIVE) - TOKEN_TABLE(WALK) - TOKEN_TABLE(STAND) - TOKEN_TABLE(TALK_SPECIAL) - TOKEN_TABLE(TALK) - TOKEN_TABLE(TURN_LEFT) - TOKEN_TABLE(TURN_RIGHT) - TOKEN_TABLE(EVENTS) - TOKEN_TABLE(FONT) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(SOUND_VOLUME) - TOKEN_TABLE(SOUND_PANNING) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(BLOCKED_REGION) - TOKEN_TABLE(WAYPOINTS) - TOKEN_TABLE(IGNORE_ITEMS) - TOKEN_TABLE(ROTABLE) - TOKEN_TABLE(ROTATABLE) - TOKEN_TABLE(ALPHA_COLOR) - TOKEN_TABLE(SCALE) - TOKEN_TABLE(RELATIVE_SCALE) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(ANIMATION) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTOR) { - _gameRef->LOG(0, "'ACTOR' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - AdGame *adGame = (AdGame *)_gameRef; - AdSpriteSet *spr = NULL; - int ar = 0, ag = 0, ab = 0, alpha = 0; - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_NAME: - setName((char *)params); - break; - - case TOKEN_CAPTION: - setCaption((char *)params); - break; - - case TOKEN_FONT: - setFont((char *)params); - break; - - case TOKEN_SCALABLE: - parser.scanStr((char *)params, "%b", &_zoomable); - break; - - case TOKEN_ROTABLE: - case TOKEN_ROTATABLE: - parser.scanStr((char *)params, "%b", &_rotatable); - break; - - case TOKEN_REGISTRABLE: - case TOKEN_INTERACTIVE: - parser.scanStr((char *)params, "%b", &_registrable); - break; - - case TOKEN_SHADOWABLE: - case TOKEN_COLORABLE: - parser.scanStr((char *)params, "%b", &_shadowable); - break; - - case TOKEN_ACTIVE: - parser.scanStr((char *)params, "%b", &_active); - break; - - case TOKEN_WALK: - delete _walkSprite; - _walkSprite = NULL; - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texWalkLifeTime, CACHE_HALF))) { - cmd = PARSERR_GENERIC; - } else { - _walkSprite = spr; - } - break; - - case TOKEN_TALK: - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSprites.add(spr); - } - break; - - case TOKEN_TALK_SPECIAL: - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSpritesEx.add(spr); - } - break; - - case TOKEN_STAND: - delete _standSprite; - _standSprite = NULL; - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texStandLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _standSprite = spr; - } - break; - - case TOKEN_TURN_LEFT: - delete _turnLeftSprite; - _turnLeftSprite = NULL; - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { - cmd = PARSERR_GENERIC; - } else { - _turnLeftSprite = spr; - } - break; - - case TOKEN_TURN_RIGHT: - delete _turnRightSprite; - _turnRightSprite = NULL; - spr = new AdSpriteSet(_gameRef, this); - if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { - cmd = PARSERR_GENERIC; - } else { - _turnRightSprite = spr; - } - break; - - case TOKEN_SCRIPT: - addScript((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_SOUND_VOLUME: - parser.scanStr((char *)params, "%d", &_sFXVolume); - break; - - case TOKEN_SCALE: { - int s; - parser.scanStr((char *)params, "%d", &s); - _scale = (float)s; - - } - break; - - case TOKEN_RELATIVE_SCALE: { - int s; - parser.scanStr((char *)params, "%d", &s); - _relativeScale = (float)s; - - } - break; - - case TOKEN_SOUND_PANNING: - parser.scanStr((char *)params, "%b", &_autoSoundPanning); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_BLOCKED_REGION: { - delete _blockRegion; - delete _currentBlockRegion; - _blockRegion = NULL; - _currentBlockRegion = NULL; - BaseRegion *rgn = new BaseRegion(_gameRef); - BaseRegion *crgn = new BaseRegion(_gameRef); - if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { - delete _blockRegion; - delete _currentBlockRegion; - _blockRegion = NULL; - _currentBlockRegion = NULL; - cmd = PARSERR_GENERIC; - } else { - _blockRegion = rgn; - _currentBlockRegion = crgn; - _currentBlockRegion->mimic(_blockRegion); - } - } - break; - - case TOKEN_WAYPOINTS: { - delete _wptGroup; - delete _currentWptGroup; - _wptGroup = NULL; - _currentWptGroup = NULL; - AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); - AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); - if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { - delete _wptGroup; - delete _currentWptGroup; - _wptGroup = NULL; - _currentWptGroup = NULL; - cmd = PARSERR_GENERIC; - } else { - _wptGroup = wpt; - _currentWptGroup = cwpt; - _currentWptGroup->mimic(_wptGroup); - } - } - break; - - case TOKEN_IGNORE_ITEMS: - parser.scanStr((char *)params, "%b", &_ignoreItems); - break; - - case TOKEN_ALPHA_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); - break; - - case TOKEN_ALPHA: - parser.scanStr((char *)params, "%d", &alpha); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - - case TOKEN_ANIMATION: { - AdSpriteSet *anim = new AdSpriteSet(_gameRef, this); - if (!anim || DID_FAIL(anim->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - } else { - _anims.add(anim); - } - } - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ACTOR definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - if (spr) { - delete spr; - } - _gameRef->LOG(0, "Error loading ACTOR definition"); - return STATUS_FAILED; - } - - if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { - ar = ag = ab = 255; - } - _alphaColor = BYTETORGBA(ar, ag, ab, alpha); - _state = _nextState = STATE_READY; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdActor::turnTo(TDirection dir) { - int delta1, delta2, delta3, delta; - - delta1 = dir - _dir; - delta2 = dir + NUM_DIRECTIONS - _dir; - delta3 = dir - NUM_DIRECTIONS - _dir; - - delta1 = (abs(delta1) <= abs(delta2)) ? delta1 : delta2; - delta = (abs(delta1) <= abs(delta3)) ? delta1 : delta3; - - // already there? - if (abs(delta) < 2) { - _dir = dir; - _state = _nextState; - _nextState = STATE_READY; - return; - } - - _targetDir = dir; - _state = delta < 0 ? STATE_TURNING_LEFT : STATE_TURNING_RIGHT; - - _tempSprite2 = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void AdActor::goTo(int x, int y, TDirection afterWalkDir) { - _afterWalkDir = afterWalkDir; - if (x == _targetPoint->x && y == _targetPoint->y && _state == STATE_FOLLOWING_PATH) { - return; - } - - _path->reset(); - _path->setReady(false); - - _targetPoint->x = x; - _targetPoint->y = y; - - ((AdGame *)_gameRef)->_scene->correctTargetPoint(_posX, _posY, &_targetPoint->x, &_targetPoint->y, true, this); - - _state = STATE_SEARCHING_PATH; - -} - - -////////////////////////////////////////////////////////////////////////// -bool AdActor::display() { - if (_active) { - updateSounds(); - } - - uint32 alpha; - if (_alphaColor != 0) { - alpha = _alphaColor; - } else { - alpha = _shadowable ? ((AdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY, true) : 0xFFFFFFFF; - } - - float scaleX, scaleY; - getScale(&scaleX, &scaleY); - - - float rotate; - if (_rotatable) { - if (_rotateValid) { - rotate = _rotate; - } else { - rotate = ((AdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; - } - } else { - rotate = 0.0f; - } - - if (_active) { - displaySpriteAttachments(true); - } - - if (_currentSprite && _active) { - bool reg = _registrable; - if (_ignoreItems && ((AdGame *)_gameRef)->_selectedItem) { - reg = false; - } - - _currentSprite->display(_posX, - _posY, - reg ? _registerAlias : NULL, - scaleX, - scaleY, - alpha, - rotate, - _blendMode); - - } - - if (_active) { - displaySpriteAttachments(false); - } - if (_active && _partEmitter) { - _partEmitter->display(); - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdActor::update() { - _currentSprite = NULL; - - if (_state == STATE_READY) { - if (_animSprite) { - delete _animSprite; - _animSprite = NULL; - } - if (_animSprite2) { - _animSprite2 = NULL; - } - } - - // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { - _state = _nextState; - _nextState = STATE_READY; - _currentSprite = _animSprite; - } - - if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != NULL && _animSprite2->_finished) { - _state = _nextState; - _nextState = STATE_READY; - _currentSprite = _animSprite2; - } - - if (_sentence && _state != STATE_TALKING) { - _sentence->finish(); - } - - // default: stand animation - if (!_currentSprite) { - if (_sprite) { - _currentSprite = _sprite; - } else { - if (_standSprite) { - _currentSprite = _standSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_idleAnimName); - if (anim) { - _currentSprite = anim->getSprite(_dir); - } - } - } - } - - bool already_moved = false; - - switch (_state) { - ////////////////////////////////////////////////////////////////////////// - case STATE_PLAYING_ANIM: - _currentSprite = _animSprite; - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_PLAYING_ANIM_SET: - _currentSprite = _animSprite2; - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_TURNING_LEFT: - if (_tempSprite2 == NULL || _tempSprite2->_finished) { - if (_dir > 0) { - _dir = (TDirection)(_dir - 1); - } else { - _dir = (TDirection)(NUM_DIRECTIONS - 1); - } - - if (_dir == _targetDir) { - _tempSprite2 = NULL; - _state = _nextState; - _nextState = STATE_READY; - } else { - if (_turnLeftSprite) { - _tempSprite2 = _turnLeftSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_turnLeftAnimName); - if (anim) { - _tempSprite2 = anim->getSprite(_dir); - } - } - - if (_tempSprite2) { - _tempSprite2->reset(); - if (_tempSprite2->_looping) { - _tempSprite2->_looping = false; - } - } - _currentSprite = _tempSprite2; - } - } else { - _currentSprite = _tempSprite2; - } - break; - - - ////////////////////////////////////////////////////////////////////////// - case STATE_TURNING_RIGHT: - if (_tempSprite2 == NULL || _tempSprite2->_finished) { - _dir = (TDirection)(_dir + 1); - - if ((int)_dir >= (int)NUM_DIRECTIONS) { - _dir = (TDirection)(0); - } - - if (_dir == _targetDir) { - _tempSprite2 = NULL; - _state = _nextState; - _nextState = STATE_READY; - } else { - if (_turnRightSprite) { - _tempSprite2 = _turnRightSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_turnRightAnimName); - if (anim) { - _tempSprite2 = anim->getSprite(_dir); - } - } - - if (_tempSprite2) { - _tempSprite2->reset(); - if (_tempSprite2->_looping) { - _tempSprite2->_looping = false; - } - } - _currentSprite = _tempSprite2; - } - } else { - _currentSprite = _tempSprite2; - } - break; - - - ////////////////////////////////////////////////////////////////////////// - case STATE_SEARCHING_PATH: - // keep asking scene for the path - if (((AdGame *)_gameRef)->_scene->getPath(BasePoint(_posX, _posY), *_targetPoint, _path, this)) { - _state = STATE_WAITING_PATH; - } - break; - - - ////////////////////////////////////////////////////////////////////////// - case STATE_WAITING_PATH: - // wait until the scene finished the path - if (_path->_ready) { - followPath(); - } - break; - - - ////////////////////////////////////////////////////////////////////////// - case STATE_FOLLOWING_PATH: - getNextStep(); - already_moved = true; - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_TALKING: { - _sentence->update(_dir); - if (_sentence->_currentSprite) { - _tempSprite2 = _sentence->_currentSprite; - } - - bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { - if (timeIsUp) { - _sentence->finish(); - _tempSprite2 = NULL; - _state = _nextState; - _nextState = STATE_READY; - } else { - _tempSprite2 = getTalkStance(_sentence->getNextStance()); - if (_tempSprite2) { - _tempSprite2->reset(); - _currentSprite = _tempSprite2; - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } - } else { - _currentSprite = _tempSprite2; - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_READY: - if (!_animSprite && !_animSprite2) { - if (_sprite) { - _currentSprite = _sprite; - } else { - if (_standSprite) { - _currentSprite = _standSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_idleAnimName); - if (anim) { - _currentSprite = anim->getSprite(_dir); - } - } - } - } - break; - default: - error("AdActor::Update - Unhandled enum"); - } - - - if (_currentSprite && !already_moved) { - _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); - if (_currentSprite->_changed) { - _posX += _currentSprite->_moveX; - _posY += _currentSprite->_moveY; - afterMove(); - } - } - - //_gameRef->QuickMessageForm("%s", _currentSprite->_filename); - - updateBlockRegion(); - _ready = (_state == STATE_READY); - - updatePartEmitter(); - updateSpriteAttachments(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdActor::followPath() { - // skip current position - _path->getFirst(); - while (_path->getCurrent() != NULL) { - if (_path->getCurrent()->x != _posX || _path->getCurrent()->y != _posY) { - break; - } - _path->getNext(); - } - - // are there points to follow? - if (_path->getCurrent() != NULL) { - _state = STATE_FOLLOWING_PATH;; - initLine(BasePoint(_posX, _posY), *_path->getCurrent()); - } else { - if (_afterWalkDir != DI_NONE) { - turnTo(_afterWalkDir); - } else { - _state = STATE_READY; - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdActor::getNextStep() { - if (_walkSprite) { - _currentSprite = _walkSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_walkAnimName); - if (anim) { - _currentSprite = anim->getSprite(_dir); - } - } - - if (!_currentSprite) { - return; - } - - _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); - if (!_currentSprite->_changed) { - return; - } - - - int maxStepX, maxStepY; - maxStepX = abs(_currentSprite->_moveX); - maxStepY = abs(_currentSprite->_moveY); - - maxStepX = MAX(maxStepX, maxStepY); - maxStepX = MAX(maxStepX, 1); - - while (_pFCount > 0 && maxStepX >= 0) { - _pFX += _pFStepX; - _pFY += _pFStepY; - - _pFCount--; - maxStepX--; - } - - if (((AdGame *)_gameRef)->_scene->isBlockedAt((int)_pFX, (int) _pFY, true, this)) { - if (_pFCount == 0) { - _state = _nextState; - _nextState = STATE_READY; - return; - } - goTo(_targetPoint->x, _targetPoint->y); - return; - } - - - _posX = (int)_pFX; - _posY = (int)_pFY; - - afterMove(); - - - if (_pFCount == 0) { - if (_path->getNext() == NULL) { - _posX = _targetPoint->x; - _posY = _targetPoint->y; - - _path->reset(); - if (_afterWalkDir != DI_NONE) { - turnTo(_afterWalkDir); - } else { - _state = _nextState; - _nextState = STATE_READY; - } - } else { - initLine(BasePoint(_posX, _posY), *_path->getCurrent()); - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdActor::initLine(BasePoint startPt, BasePoint endPt) { - _pFCount = MAX((abs(endPt.x - startPt.x)) , (abs(endPt.y - startPt.y))); - - _pFStepX = (double)(endPt.x - startPt.x) / _pFCount; - _pFStepY = (double)(endPt.y - startPt.y) / _pFCount; - - _pFX = startPt.x; - _pFY = startPt.y; - - int angle = (int)(atan2((double)(endPt.y - startPt.y), (double)(endPt.x - startPt.x)) * (180 / 3.14)); - - _nextState = STATE_FOLLOWING_PATH; - - turnTo(angleToDirection(angle)); -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GoTo / GoToAsync - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GoTo") == 0 || strcmp(name, "GoToAsync") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - goTo(x, y); - if (strcmp(name, "GoToAsync") != 0) { - script->waitForExclusive(this); - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GoToObject / GoToObjectAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GoToObject") == 0 || strcmp(name, "GoToObjectAsync") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - if (!val->isNative()) { - script->runtimeError("actor.%s method accepts an entity refrence only", name); - stack->pushNULL(); - return STATUS_OK; - } - AdObject *obj = (AdObject *)val->getNative(); - if (!obj || obj->_type != OBJECT_ENTITY) { - script->runtimeError("actor.%s method accepts an entity refrence only", name); - stack->pushNULL(); - return STATUS_OK; - } - AdEntity *ent = (AdEntity *)obj; - if (ent->_walkToX == 0 && ent->_walkToY == 0) { - goTo(ent->_posX, ent->_posY); - } else { - goTo(ent->_walkToX, ent->_walkToY, ent->_walkToDir); - } - if (strcmp(name, "GoToObjectAsync") != 0) { - script->waitForExclusive(this); - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TurnTo / TurnToAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TurnTo") == 0 || strcmp(name, "TurnToAsync") == 0) { - stack->correctParams(1); - int dir; - ScValue *val = stack->pop(); - - // turn to object? - if (val->isNative() && _gameRef->validObject((BaseObject *)val->getNative())) { - BaseObject *obj = (BaseObject *)val->getNative(); - int angle = (int)(atan2((double)(obj->_posY - _posY), (double)(obj->_posX - _posX)) * (180 / 3.14)); - dir = (int)angleToDirection(angle); - } - // otherwise turn to direction - else { - dir = val->getInt(); - } - - if (dir >= 0 && dir < NUM_DIRECTIONS) { - turnTo((TDirection)dir); - if (strcmp(name, "TurnToAsync") != 0) { - script->waitForExclusive(this); - } - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsWalking - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsWalking") == 0) { - stack->correctParams(0); - stack->pushBool(_state == STATE_FOLLOWING_PATH); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MergeAnims - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MergeAnims") == 0) { - stack->correctParams(1); - stack->pushBool(DID_SUCCEED(mergeAnims(stack->pop()->getString()))); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // UnloadAnim - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "UnloadAnim") == 0) { - stack->correctParams(1); - const char *animName = stack->pop()->getString(); - - bool found = false; - for (uint32 i = 0; i < _anims.size(); i++) { - if (scumm_stricmp(_anims[i]->getName(), animName) == 0) { - // invalidate sprites in use - if (_anims[i]->containsSprite(_tempSprite2)) { - _tempSprite2 = NULL; - } - if (_anims[i]->containsSprite(_currentSprite)) { - _currentSprite = NULL; - } - if (_anims[i]->containsSprite(_animSprite2)) { - _animSprite2 = NULL; - } - - delete _anims[i]; - _anims[i] = NULL; - _anims.remove_at(i); - i--; - found = true; - } - } - stack->pushBool(found); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // HasAnim - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "HasAnim") == 0) { - stack->correctParams(1); - const char *animName = stack->pop()->getString(); - stack->pushBool(getAnimByName(animName) != NULL); - return STATUS_OK; - } else { - return AdTalkHolder::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdActor::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Direction - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Direction") == 0) { - _scValue->setInt(_dir); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Type") == 0) { - _scValue->setString("actor"); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // TalkAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TalkAnimName") == 0) { - _scValue->setString(_talkAnimName); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkAnimName") == 0) { - _scValue->setString(_walkAnimName); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // IdleAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IdleAnimName") == 0) { - _scValue->setString(_idleAnimName); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TurnLeftAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TurnLeftAnimName") == 0) { - _scValue->setString(_turnLeftAnimName); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TurnRightAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TurnRightAnimName") == 0) { - _scValue->setString(_turnRightAnimName); - return _scValue; - } else { - return AdTalkHolder::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdActor::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Direction - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Direction") == 0) { - int dir = value->getInt(); - if (dir >= 0 && dir < NUM_DIRECTIONS) { - _dir = (TDirection)dir; - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TalkAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TalkAnimName") == 0) { - if (value->isNULL()) { - _talkAnimName = "talk"; - } else { - _talkAnimName = value->getString(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkAnimName") == 0) { - if (value->isNULL()) { - _walkAnimName = "walk"; - } else { - _walkAnimName = value->getString(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IdleAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IdleAnimName") == 0) { - if (value->isNULL()) { - _idleAnimName = "idle"; - } else { - _idleAnimName = value->getString(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TurnLeftAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TurnLeftAnimName") == 0) { - if (value->isNULL()) { - _turnLeftAnimName = "turnleft"; - } else { - _turnLeftAnimName = value->getString(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TurnRightAnimName - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TurnRightAnimName") == 0) { - if (value->isNULL()) { - _turnRightAnimName = "turnright"; - } else { - _turnRightAnimName = value->getString(); - } - return STATUS_OK; - } else { - return AdTalkHolder::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdActor::scToString() { - return "[actor object]"; -} - - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdActor::getTalkStance(const char *stance) { - // forced stance? - if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { - _forcedTalkAnimUsed = true; - delete _animSprite; - _animSprite = new BaseSprite(_gameRef, this); - if (_animSprite) { - bool res = _animSprite->loadFile(_forcedTalkAnimName); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "AdActor::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); - delete _animSprite; - _animSprite = NULL; - } else { - return _animSprite; - } - } - } - - // old way - if (_talkSprites.size() > 0 || _talkSpritesEx.size() > 0) { - return getTalkStanceOld(stance); - } - - // new way - BaseSprite *ret = NULL; - - // do we have an animation with this name? - AdSpriteSet *anim = getAnimByName(stance); - if (anim) { - ret = anim->getSprite(_dir); - } - - // not - get a random talk - if (!ret) { - BaseArray talkAnims; - for (uint32 i = 0; i < _anims.size(); i++) { - if (_talkAnimName.compareToIgnoreCase(_anims[i]->getName()) == 0) { - talkAnims.add(_anims[i]); - } - } - - if (talkAnims.size() > 0) { - int rnd = BaseEngine::instance().randInt(0, talkAnims.size() - 1); - ret = talkAnims[rnd]->getSprite(_dir); - } else { - if (_standSprite) { - ret = _standSprite->getSprite(_dir); - } else { - anim = getAnimByName(_idleAnimName); - if (anim) { - ret = anim->getSprite(_dir); - } - } - } - } - return ret; -} - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdActor::getTalkStanceOld(const char *stance) { - BaseSprite *ret = NULL; - - if (stance != NULL) { - // search special stances - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { - ret = _talkSpritesEx[i]->getSprite(_dir); - break; - } - } - if (ret == NULL) { - // search generic stances - for (uint32 i = 0; i < _talkSprites.size(); i++) { - if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { - ret = _talkSprites[i]->getSprite(_dir); - break; - } - } - } - } - - // not a valid stance? get a random one - if (ret == NULL) { - if (_talkSprites.size() < 1) { - ret = _standSprite->getSprite(_dir); - } else { - // TODO: remember last - int rnd = BaseEngine::instance().randInt(0, _talkSprites.size() - 1); - ret = _talkSprites[rnd]->getSprite(_dir); - } - } - - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool AdActor::persist(BasePersistenceManager *persistMgr) { - AdTalkHolder::persist(persistMgr); - - persistMgr->transfer(TMEMBER_INT(_dir)); - persistMgr->transfer(TMEMBER(_path)); - persistMgr->transfer(TMEMBER(_pFCount)); - persistMgr->transfer(TMEMBER(_pFStepX)); - persistMgr->transfer(TMEMBER(_pFStepY)); - persistMgr->transfer(TMEMBER(_pFX)); - persistMgr->transfer(TMEMBER(_pFY)); - persistMgr->transfer(TMEMBER(_standSprite)); - _talkSprites.persist(persistMgr); - _talkSpritesEx.persist(persistMgr); - persistMgr->transfer(TMEMBER_INT(_targetDir)); - persistMgr->transfer(TMEMBER_INT(_afterWalkDir)); - persistMgr->transfer(TMEMBER(_targetPoint)); - persistMgr->transfer(TMEMBER(_turnLeftSprite)); - persistMgr->transfer(TMEMBER(_turnRightSprite)); - persistMgr->transfer(TMEMBER(_walkSprite)); - - persistMgr->transfer(TMEMBER(_animSprite2)); - persistMgr->transfer(TMEMBER(_talkAnimName)); - persistMgr->transfer(TMEMBER(_idleAnimName)); - persistMgr->transfer(TMEMBER(_walkAnimName)); - persistMgr->transfer(TMEMBER(_turnLeftAnimName)); - persistMgr->transfer(TMEMBER(_turnRightAnimName)); - - _anims.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -TDirection AdActor::angleToDirection(int angle) { - TDirection ret = DI_DOWN;; - - if (angle > -112 && angle <= -67) { - ret = DI_UP; - } else if (angle > -67 && angle <= -22) { - ret = DI_UPRIGHT; - } else if (angle > -22 && angle <= 22) { - ret = DI_RIGHT; - } else if (angle > 22 && angle <= 67) { - ret = DI_DOWNRIGHT; - } else if (angle > 67 && angle <= 112) { - ret = DI_DOWN; - } else if (angle > 112 && angle <= 157) { - ret = DI_DOWNLEFT; - } else if ((angle > 157 && angle <= 180) || (angle >= -180 && angle <= -157)) { - ret = DI_LEFT; - } else if (angle > -157 && angle <= -112) { - ret = DI_UPLEFT; - } - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -int AdActor::getHeight() { - // if no current sprite is set, set some - if (_currentSprite == NULL) { - if (_standSprite) { - _currentSprite = _standSprite->getSprite(_dir); - } else { - AdSpriteSet *anim = getAnimByName(_idleAnimName); - if (anim) { - _currentSprite = anim->getSprite(_dir); - } - } - } - // and get height - return AdTalkHolder::getHeight(); -} - - -////////////////////////////////////////////////////////////////////////// -AdSpriteSet *AdActor::getAnimByName(const Common::String &animName) { - for (uint32 i = 0; i < _anims.size(); i++) { - if (animName.compareToIgnoreCase(_anims[i]->getName()) == 0) { - return _anims[i]; - } - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool AdActor::mergeAnims(const char *animsFilename) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ANIMATION) - TOKEN_TABLE_END - - - byte *fileBuffer = BaseFileManager::getEngineInstance()->readWholeFile(animsFilename); - if (fileBuffer == NULL) { - _gameRef->LOG(0, "AdActor::MergeAnims failed for file '%s'", animsFilename); - return STATUS_FAILED; - } - - byte *buffer = fileBuffer; - byte *params; - int cmd; - BaseParser parser; - - bool ret = STATUS_OK; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_ANIMATION: { - AdSpriteSet *anim = new AdSpriteSet(_gameRef, this); - if (!anim || DID_FAIL(anim->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - ret = STATUS_FAILED; - } else { - _anims.add(anim); - } - } - break; - } - } - delete[] fileBuffer; - return ret; -} - -////////////////////////////////////////////////////////////////////////// -bool AdActor::playAnim(const char *filename) { - // if we have an anim with this name, use it - AdSpriteSet *anim = getAnimByName(filename); - if (anim) { - _animSprite2 = anim->getSprite(_dir); - if (_animSprite2) { - _animSprite2->reset(); - _state = STATE_PLAYING_ANIM_SET; - return STATUS_OK; - } - } - // otherwise call the standard handler - return AdTalkHolder::playAnim(filename); -} - -} // end of namespace Wintermute +/* 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_actor.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_scene.h" +#include "engines/wintermute/ad/ad_entity.h" +#include "engines/wintermute/ad/ad_sprite_set.h" +#include "engines/wintermute/ad/ad_waypoint_group.h" +#include "engines/wintermute/ad/ad_path.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/particles/part_emitter.h" +#include "engines/wintermute/base/base_engine.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdActor, false) + + +////////////////////////////////////////////////////////////////////////// +AdActor::AdActor(BaseGame *inGame) : AdTalkHolder(inGame) { + _path = new AdPath(_gameRef); + + _type = OBJECT_ACTOR; + _dir = DI_LEFT; + + _walkSprite = NULL; + _standSprite = NULL; + _turnLeftSprite = NULL; + _turnRightSprite = NULL; + + _targetPoint = new BasePoint; + _afterWalkDir = DI_NONE; + + _animSprite2 = NULL; + + setDefaultAnimNames(); +} + +////////////////////////////////////////////////////////////////////////// +bool AdActor::setDefaultAnimNames() { + _talkAnimName = "talk"; + _idleAnimName = "idle"; + _walkAnimName = "walk"; + _turnLeftAnimName = "turnleft"; + _turnRightAnimName = "turnright"; + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +AdActor::~AdActor() { + delete _path; + delete _targetPoint; + _path = NULL; + _targetPoint = NULL; + + delete _walkSprite; + delete _standSprite; + delete _turnLeftSprite; + delete _turnRightSprite; + _walkSprite = NULL; + _standSprite = NULL; + _turnLeftSprite = NULL; + _turnRightSprite = NULL; + + _animSprite2 = NULL; // ref only + + for (uint32 i = 0; i < _talkSprites.size(); i++) { + delete _talkSprites[i]; + } + _talkSprites.clear(); + + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + delete _talkSpritesEx[i]; + } + _talkSpritesEx.clear(); + + for (uint32 i = 0; i < _anims.size(); i++) { + delete _anims[i]; + _anims[i] = NULL; + } + _anims.clear(); + +} + + +////////////////////////////////////////////////////////////////////////// +bool AdActor::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdActor::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 ACTOR file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(ACTOR) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(SCALABLE) +TOKEN_DEF(REGISTRABLE) +TOKEN_DEF(INTERACTIVE) +TOKEN_DEF(SHADOWABLE) +TOKEN_DEF(COLORABLE) +TOKEN_DEF(ACTIVE) +TOKEN_DEF(WALK) +TOKEN_DEF(STAND) +TOKEN_DEF(TALK_SPECIAL) +TOKEN_DEF(TALK) +TOKEN_DEF(TURN_LEFT) +TOKEN_DEF(TURN_RIGHT) +TOKEN_DEF(EVENTS) +TOKEN_DEF(FONT) +TOKEN_DEF(CURSOR) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(SOUND_VOLUME) +TOKEN_DEF(SOUND_PANNING) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(BLOCKED_REGION) +TOKEN_DEF(WAYPOINTS) +TOKEN_DEF(IGNORE_ITEMS) +TOKEN_DEF(ROTABLE) +TOKEN_DEF(ROTATABLE) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(SCALE) +TOKEN_DEF(RELATIVE_SCALE) +TOKEN_DEF(ALPHA) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(ANIMATION) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdActor::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ACTOR) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SCALABLE) + TOKEN_TABLE(REGISTRABLE) + TOKEN_TABLE(INTERACTIVE) + TOKEN_TABLE(SHADOWABLE) + TOKEN_TABLE(COLORABLE) + TOKEN_TABLE(ACTIVE) + TOKEN_TABLE(WALK) + TOKEN_TABLE(STAND) + TOKEN_TABLE(TALK_SPECIAL) + TOKEN_TABLE(TALK) + TOKEN_TABLE(TURN_LEFT) + TOKEN_TABLE(TURN_RIGHT) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(FONT) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(SOUND_VOLUME) + TOKEN_TABLE(SOUND_PANNING) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(BLOCKED_REGION) + TOKEN_TABLE(WAYPOINTS) + TOKEN_TABLE(IGNORE_ITEMS) + TOKEN_TABLE(ROTABLE) + TOKEN_TABLE(ROTATABLE) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(SCALE) + TOKEN_TABLE(RELATIVE_SCALE) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(ANIMATION) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTOR) { + _gameRef->LOG(0, "'ACTOR' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + AdGame *adGame = (AdGame *)_gameRef; + AdSpriteSet *spr = NULL; + int ar = 0, ag = 0, ab = 0, alpha = 0; + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_NAME: + setName((char *)params); + break; + + case TOKEN_CAPTION: + setCaption((char *)params); + break; + + case TOKEN_FONT: + setFont((char *)params); + break; + + case TOKEN_SCALABLE: + parser.scanStr((char *)params, "%b", &_zoomable); + break; + + case TOKEN_ROTABLE: + case TOKEN_ROTATABLE: + parser.scanStr((char *)params, "%b", &_rotatable); + break; + + case TOKEN_REGISTRABLE: + case TOKEN_INTERACTIVE: + parser.scanStr((char *)params, "%b", &_registrable); + break; + + case TOKEN_SHADOWABLE: + case TOKEN_COLORABLE: + parser.scanStr((char *)params, "%b", &_shadowable); + break; + + case TOKEN_ACTIVE: + parser.scanStr((char *)params, "%b", &_active); + break; + + case TOKEN_WALK: + delete _walkSprite; + _walkSprite = NULL; + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texWalkLifeTime, CACHE_HALF))) { + cmd = PARSERR_GENERIC; + } else { + _walkSprite = spr; + } + break; + + case TOKEN_TALK: + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSprites.add(spr); + } + break; + + case TOKEN_TALK_SPECIAL: + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSpritesEx.add(spr); + } + break; + + case TOKEN_STAND: + delete _standSprite; + _standSprite = NULL; + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true, adGame->_texStandLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _standSprite = spr; + } + break; + + case TOKEN_TURN_LEFT: + delete _turnLeftSprite; + _turnLeftSprite = NULL; + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { + cmd = PARSERR_GENERIC; + } else { + _turnLeftSprite = spr; + } + break; + + case TOKEN_TURN_RIGHT: + delete _turnRightSprite; + _turnRightSprite = NULL; + spr = new AdSpriteSet(_gameRef, this); + if (!spr || DID_FAIL(spr->loadBuffer(params, true))) { + cmd = PARSERR_GENERIC; + } else { + _turnRightSprite = spr; + } + break; + + case TOKEN_SCRIPT: + addScript((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_SOUND_VOLUME: + parser.scanStr((char *)params, "%d", &_sFXVolume); + break; + + case TOKEN_SCALE: { + int s; + parser.scanStr((char *)params, "%d", &s); + _scale = (float)s; + + } + break; + + case TOKEN_RELATIVE_SCALE: { + int s; + parser.scanStr((char *)params, "%d", &s); + _relativeScale = (float)s; + + } + break; + + case TOKEN_SOUND_PANNING: + parser.scanStr((char *)params, "%b", &_autoSoundPanning); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_BLOCKED_REGION: { + delete _blockRegion; + delete _currentBlockRegion; + _blockRegion = NULL; + _currentBlockRegion = NULL; + BaseRegion *rgn = new BaseRegion(_gameRef); + BaseRegion *crgn = new BaseRegion(_gameRef); + if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { + delete _blockRegion; + delete _currentBlockRegion; + _blockRegion = NULL; + _currentBlockRegion = NULL; + cmd = PARSERR_GENERIC; + } else { + _blockRegion = rgn; + _currentBlockRegion = crgn; + _currentBlockRegion->mimic(_blockRegion); + } + } + break; + + case TOKEN_WAYPOINTS: { + delete _wptGroup; + delete _currentWptGroup; + _wptGroup = NULL; + _currentWptGroup = NULL; + AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); + AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); + if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { + delete _wptGroup; + delete _currentWptGroup; + _wptGroup = NULL; + _currentWptGroup = NULL; + cmd = PARSERR_GENERIC; + } else { + _wptGroup = wpt; + _currentWptGroup = cwpt; + _currentWptGroup->mimic(_wptGroup); + } + } + break; + + case TOKEN_IGNORE_ITEMS: + parser.scanStr((char *)params, "%b", &_ignoreItems); + break; + + case TOKEN_ALPHA_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.scanStr((char *)params, "%d", &alpha); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + + case TOKEN_ANIMATION: { + AdSpriteSet *anim = new AdSpriteSet(_gameRef, this); + if (!anim || DID_FAIL(anim->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + } else { + _anims.add(anim); + } + } + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ACTOR definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + if (spr) { + delete spr; + } + _gameRef->LOG(0, "Error loading ACTOR definition"); + return STATUS_FAILED; + } + + if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { + ar = ag = ab = 255; + } + _alphaColor = BYTETORGBA(ar, ag, ab, alpha); + _state = _nextState = STATE_READY; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdActor::turnTo(TDirection dir) { + int delta1, delta2, delta3, delta; + + delta1 = dir - _dir; + delta2 = dir + NUM_DIRECTIONS - _dir; + delta3 = dir - NUM_DIRECTIONS - _dir; + + delta1 = (abs(delta1) <= abs(delta2)) ? delta1 : delta2; + delta = (abs(delta1) <= abs(delta3)) ? delta1 : delta3; + + // already there? + if (abs(delta) < 2) { + _dir = dir; + _state = _nextState; + _nextState = STATE_READY; + return; + } + + _targetDir = dir; + _state = delta < 0 ? STATE_TURNING_LEFT : STATE_TURNING_RIGHT; + + _tempSprite2 = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void AdActor::goTo(int x, int y, TDirection afterWalkDir) { + _afterWalkDir = afterWalkDir; + if (x == _targetPoint->x && y == _targetPoint->y && _state == STATE_FOLLOWING_PATH) { + return; + } + + _path->reset(); + _path->setReady(false); + + _targetPoint->x = x; + _targetPoint->y = y; + + ((AdGame *)_gameRef)->_scene->correctTargetPoint(_posX, _posY, &_targetPoint->x, &_targetPoint->y, true, this); + + _state = STATE_SEARCHING_PATH; + +} + + +////////////////////////////////////////////////////////////////////////// +bool AdActor::display() { + if (_active) { + updateSounds(); + } + + uint32 alpha; + if (_alphaColor != 0) { + alpha = _alphaColor; + } else { + alpha = _shadowable ? ((AdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY, true) : 0xFFFFFFFF; + } + + float scaleX, scaleY; + getScale(&scaleX, &scaleY); + + + float rotate; + if (_rotatable) { + if (_rotateValid) { + rotate = _rotate; + } else { + rotate = ((AdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; + } + } else { + rotate = 0.0f; + } + + if (_active) { + displaySpriteAttachments(true); + } + + if (_currentSprite && _active) { + bool reg = _registrable; + if (_ignoreItems && ((AdGame *)_gameRef)->_selectedItem) { + reg = false; + } + + _currentSprite->display(_posX, + _posY, + reg ? _registerAlias : NULL, + scaleX, + scaleY, + alpha, + rotate, + _blendMode); + + } + + if (_active) { + displaySpriteAttachments(false); + } + if (_active && _partEmitter) { + _partEmitter->display(); + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdActor::update() { + _currentSprite = NULL; + + if (_state == STATE_READY) { + if (_animSprite) { + delete _animSprite; + _animSprite = NULL; + } + if (_animSprite2) { + _animSprite2 = NULL; + } + } + + // finished playing animation? + if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { + _state = _nextState; + _nextState = STATE_READY; + _currentSprite = _animSprite; + } + + if (_state == STATE_PLAYING_ANIM_SET && _animSprite2 != NULL && _animSprite2->_finished) { + _state = _nextState; + _nextState = STATE_READY; + _currentSprite = _animSprite2; + } + + if (_sentence && _state != STATE_TALKING) { + _sentence->finish(); + } + + // default: stand animation + if (!_currentSprite) { + if (_sprite) { + _currentSprite = _sprite; + } else { + if (_standSprite) { + _currentSprite = _standSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_idleAnimName); + if (anim) { + _currentSprite = anim->getSprite(_dir); + } + } + } + } + + bool already_moved = false; + + switch (_state) { + ////////////////////////////////////////////////////////////////////////// + case STATE_PLAYING_ANIM: + _currentSprite = _animSprite; + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_PLAYING_ANIM_SET: + _currentSprite = _animSprite2; + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_TURNING_LEFT: + if (_tempSprite2 == NULL || _tempSprite2->_finished) { + if (_dir > 0) { + _dir = (TDirection)(_dir - 1); + } else { + _dir = (TDirection)(NUM_DIRECTIONS - 1); + } + + if (_dir == _targetDir) { + _tempSprite2 = NULL; + _state = _nextState; + _nextState = STATE_READY; + } else { + if (_turnLeftSprite) { + _tempSprite2 = _turnLeftSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_turnLeftAnimName); + if (anim) { + _tempSprite2 = anim->getSprite(_dir); + } + } + + if (_tempSprite2) { + _tempSprite2->reset(); + if (_tempSprite2->_looping) { + _tempSprite2->_looping = false; + } + } + _currentSprite = _tempSprite2; + } + } else { + _currentSprite = _tempSprite2; + } + break; + + + ////////////////////////////////////////////////////////////////////////// + case STATE_TURNING_RIGHT: + if (_tempSprite2 == NULL || _tempSprite2->_finished) { + _dir = (TDirection)(_dir + 1); + + if ((int)_dir >= (int)NUM_DIRECTIONS) { + _dir = (TDirection)(0); + } + + if (_dir == _targetDir) { + _tempSprite2 = NULL; + _state = _nextState; + _nextState = STATE_READY; + } else { + if (_turnRightSprite) { + _tempSprite2 = _turnRightSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_turnRightAnimName); + if (anim) { + _tempSprite2 = anim->getSprite(_dir); + } + } + + if (_tempSprite2) { + _tempSprite2->reset(); + if (_tempSprite2->_looping) { + _tempSprite2->_looping = false; + } + } + _currentSprite = _tempSprite2; + } + } else { + _currentSprite = _tempSprite2; + } + break; + + + ////////////////////////////////////////////////////////////////////////// + case STATE_SEARCHING_PATH: + // keep asking scene for the path + if (((AdGame *)_gameRef)->_scene->getPath(BasePoint(_posX, _posY), *_targetPoint, _path, this)) { + _state = STATE_WAITING_PATH; + } + break; + + + ////////////////////////////////////////////////////////////////////////// + case STATE_WAITING_PATH: + // wait until the scene finished the path + if (_path->_ready) { + followPath(); + } + break; + + + ////////////////////////////////////////////////////////////////////////// + case STATE_FOLLOWING_PATH: + getNextStep(); + already_moved = true; + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_TALKING: { + _sentence->update(_dir); + if (_sentence->_currentSprite) { + _tempSprite2 = _sentence->_currentSprite; + } + + bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); + if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (timeIsUp) { + _sentence->finish(); + _tempSprite2 = NULL; + _state = _nextState; + _nextState = STATE_READY; + } else { + _tempSprite2 = getTalkStance(_sentence->getNextStance()); + if (_tempSprite2) { + _tempSprite2->reset(); + _currentSprite = _tempSprite2; + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } + } else { + _currentSprite = _tempSprite2; + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_READY: + if (!_animSprite && !_animSprite2) { + if (_sprite) { + _currentSprite = _sprite; + } else { + if (_standSprite) { + _currentSprite = _standSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_idleAnimName); + if (anim) { + _currentSprite = anim->getSprite(_dir); + } + } + } + } + break; + default: + error("AdActor::Update - Unhandled enum"); + } + + + if (_currentSprite && !already_moved) { + _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); + if (_currentSprite->_changed) { + _posX += _currentSprite->_moveX; + _posY += _currentSprite->_moveY; + afterMove(); + } + } + + //_gameRef->QuickMessageForm("%s", _currentSprite->_filename); + + updateBlockRegion(); + _ready = (_state == STATE_READY); + + updatePartEmitter(); + updateSpriteAttachments(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdActor::followPath() { + // skip current position + _path->getFirst(); + while (_path->getCurrent() != NULL) { + if (_path->getCurrent()->x != _posX || _path->getCurrent()->y != _posY) { + break; + } + _path->getNext(); + } + + // are there points to follow? + if (_path->getCurrent() != NULL) { + _state = STATE_FOLLOWING_PATH;; + initLine(BasePoint(_posX, _posY), *_path->getCurrent()); + } else { + if (_afterWalkDir != DI_NONE) { + turnTo(_afterWalkDir); + } else { + _state = STATE_READY; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdActor::getNextStep() { + if (_walkSprite) { + _currentSprite = _walkSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_walkAnimName); + if (anim) { + _currentSprite = anim->getSprite(_dir); + } + } + + if (!_currentSprite) { + return; + } + + _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100, _zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); + if (!_currentSprite->_changed) { + return; + } + + + int maxStepX, maxStepY; + maxStepX = abs(_currentSprite->_moveX); + maxStepY = abs(_currentSprite->_moveY); + + maxStepX = MAX(maxStepX, maxStepY); + maxStepX = MAX(maxStepX, 1); + + while (_pFCount > 0 && maxStepX >= 0) { + _pFX += _pFStepX; + _pFY += _pFStepY; + + _pFCount--; + maxStepX--; + } + + if (((AdGame *)_gameRef)->_scene->isBlockedAt((int)_pFX, (int) _pFY, true, this)) { + if (_pFCount == 0) { + _state = _nextState; + _nextState = STATE_READY; + return; + } + goTo(_targetPoint->x, _targetPoint->y); + return; + } + + + _posX = (int)_pFX; + _posY = (int)_pFY; + + afterMove(); + + + if (_pFCount == 0) { + if (_path->getNext() == NULL) { + _posX = _targetPoint->x; + _posY = _targetPoint->y; + + _path->reset(); + if (_afterWalkDir != DI_NONE) { + turnTo(_afterWalkDir); + } else { + _state = _nextState; + _nextState = STATE_READY; + } + } else { + initLine(BasePoint(_posX, _posY), *_path->getCurrent()); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdActor::initLine(BasePoint startPt, BasePoint endPt) { + _pFCount = MAX((abs(endPt.x - startPt.x)) , (abs(endPt.y - startPt.y))); + + _pFStepX = (double)(endPt.x - startPt.x) / _pFCount; + _pFStepY = (double)(endPt.y - startPt.y) / _pFCount; + + _pFX = startPt.x; + _pFY = startPt.y; + + int angle = (int)(atan2((double)(endPt.y - startPt.y), (double)(endPt.x - startPt.x)) * (180 / 3.14)); + + _nextState = STATE_FOLLOWING_PATH; + + turnTo(angleToDirection(angle)); +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdActor::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GoTo / GoToAsync + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GoTo") == 0 || strcmp(name, "GoToAsync") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + goTo(x, y); + if (strcmp(name, "GoToAsync") != 0) { + script->waitForExclusive(this); + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GoToObject / GoToObjectAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GoToObject") == 0 || strcmp(name, "GoToObjectAsync") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + if (!val->isNative()) { + script->runtimeError("actor.%s method accepts an entity refrence only", name); + stack->pushNULL(); + return STATUS_OK; + } + AdObject *obj = (AdObject *)val->getNative(); + if (!obj || obj->_type != OBJECT_ENTITY) { + script->runtimeError("actor.%s method accepts an entity refrence only", name); + stack->pushNULL(); + return STATUS_OK; + } + AdEntity *ent = (AdEntity *)obj; + if (ent->_walkToX == 0 && ent->_walkToY == 0) { + goTo(ent->_posX, ent->_posY); + } else { + goTo(ent->_walkToX, ent->_walkToY, ent->_walkToDir); + } + if (strcmp(name, "GoToObjectAsync") != 0) { + script->waitForExclusive(this); + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TurnTo / TurnToAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TurnTo") == 0 || strcmp(name, "TurnToAsync") == 0) { + stack->correctParams(1); + int dir; + ScValue *val = stack->pop(); + + // turn to object? + if (val->isNative() && _gameRef->validObject((BaseObject *)val->getNative())) { + BaseObject *obj = (BaseObject *)val->getNative(); + int angle = (int)(atan2((double)(obj->_posY - _posY), (double)(obj->_posX - _posX)) * (180 / 3.14)); + dir = (int)angleToDirection(angle); + } + // otherwise turn to direction + else { + dir = val->getInt(); + } + + if (dir >= 0 && dir < NUM_DIRECTIONS) { + turnTo((TDirection)dir); + if (strcmp(name, "TurnToAsync") != 0) { + script->waitForExclusive(this); + } + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsWalking + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsWalking") == 0) { + stack->correctParams(0); + stack->pushBool(_state == STATE_FOLLOWING_PATH); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MergeAnims + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MergeAnims") == 0) { + stack->correctParams(1); + stack->pushBool(DID_SUCCEED(mergeAnims(stack->pop()->getString()))); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // UnloadAnim + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "UnloadAnim") == 0) { + stack->correctParams(1); + const char *animName = stack->pop()->getString(); + + bool found = false; + for (uint32 i = 0; i < _anims.size(); i++) { + if (scumm_stricmp(_anims[i]->getName(), animName) == 0) { + // invalidate sprites in use + if (_anims[i]->containsSprite(_tempSprite2)) { + _tempSprite2 = NULL; + } + if (_anims[i]->containsSprite(_currentSprite)) { + _currentSprite = NULL; + } + if (_anims[i]->containsSprite(_animSprite2)) { + _animSprite2 = NULL; + } + + delete _anims[i]; + _anims[i] = NULL; + _anims.remove_at(i); + i--; + found = true; + } + } + stack->pushBool(found); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HasAnim + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HasAnim") == 0) { + stack->correctParams(1); + const char *animName = stack->pop()->getString(); + stack->pushBool(getAnimByName(animName) != NULL); + return STATUS_OK; + } else { + return AdTalkHolder::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdActor::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Direction + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Direction") == 0) { + _scValue->setInt(_dir); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Type") == 0) { + _scValue->setString("actor"); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // TalkAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TalkAnimName") == 0) { + _scValue->setString(_talkAnimName); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkAnimName") == 0) { + _scValue->setString(_walkAnimName); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // IdleAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IdleAnimName") == 0) { + _scValue->setString(_idleAnimName); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TurnLeftAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TurnLeftAnimName") == 0) { + _scValue->setString(_turnLeftAnimName); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TurnRightAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TurnRightAnimName") == 0) { + _scValue->setString(_turnRightAnimName); + return _scValue; + } else { + return AdTalkHolder::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdActor::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Direction + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Direction") == 0) { + int dir = value->getInt(); + if (dir >= 0 && dir < NUM_DIRECTIONS) { + _dir = (TDirection)dir; + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TalkAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TalkAnimName") == 0) { + if (value->isNULL()) { + _talkAnimName = "talk"; + } else { + _talkAnimName = value->getString(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkAnimName") == 0) { + if (value->isNULL()) { + _walkAnimName = "walk"; + } else { + _walkAnimName = value->getString(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IdleAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IdleAnimName") == 0) { + if (value->isNULL()) { + _idleAnimName = "idle"; + } else { + _idleAnimName = value->getString(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TurnLeftAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TurnLeftAnimName") == 0) { + if (value->isNULL()) { + _turnLeftAnimName = "turnleft"; + } else { + _turnLeftAnimName = value->getString(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TurnRightAnimName + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TurnRightAnimName") == 0) { + if (value->isNULL()) { + _turnRightAnimName = "turnright"; + } else { + _turnRightAnimName = value->getString(); + } + return STATUS_OK; + } else { + return AdTalkHolder::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdActor::scToString() { + return "[actor object]"; +} + + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdActor::getTalkStance(const char *stance) { + // forced stance? + if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { + _forcedTalkAnimUsed = true; + delete _animSprite; + _animSprite = new BaseSprite(_gameRef, this); + if (_animSprite) { + bool res = _animSprite->loadFile(_forcedTalkAnimName); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "AdActor::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); + delete _animSprite; + _animSprite = NULL; + } else { + return _animSprite; + } + } + } + + // old way + if (_talkSprites.size() > 0 || _talkSpritesEx.size() > 0) { + return getTalkStanceOld(stance); + } + + // new way + BaseSprite *ret = NULL; + + // do we have an animation with this name? + AdSpriteSet *anim = getAnimByName(stance); + if (anim) { + ret = anim->getSprite(_dir); + } + + // not - get a random talk + if (!ret) { + BaseArray talkAnims; + for (uint32 i = 0; i < _anims.size(); i++) { + if (_talkAnimName.compareToIgnoreCase(_anims[i]->getName()) == 0) { + talkAnims.add(_anims[i]); + } + } + + if (talkAnims.size() > 0) { + int rnd = BaseEngine::instance().randInt(0, talkAnims.size() - 1); + ret = talkAnims[rnd]->getSprite(_dir); + } else { + if (_standSprite) { + ret = _standSprite->getSprite(_dir); + } else { + anim = getAnimByName(_idleAnimName); + if (anim) { + ret = anim->getSprite(_dir); + } + } + } + } + return ret; +} + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdActor::getTalkStanceOld(const char *stance) { + BaseSprite *ret = NULL; + + if (stance != NULL) { + // search special stances + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { + ret = _talkSpritesEx[i]->getSprite(_dir); + break; + } + } + if (ret == NULL) { + // search generic stances + for (uint32 i = 0; i < _talkSprites.size(); i++) { + if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { + ret = _talkSprites[i]->getSprite(_dir); + break; + } + } + } + } + + // not a valid stance? get a random one + if (ret == NULL) { + if (_talkSprites.size() < 1) { + ret = _standSprite->getSprite(_dir); + } else { + // TODO: remember last + int rnd = BaseEngine::instance().randInt(0, _talkSprites.size() - 1); + ret = _talkSprites[rnd]->getSprite(_dir); + } + } + + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool AdActor::persist(BasePersistenceManager *persistMgr) { + AdTalkHolder::persist(persistMgr); + + persistMgr->transfer(TMEMBER_INT(_dir)); + persistMgr->transfer(TMEMBER(_path)); + persistMgr->transfer(TMEMBER(_pFCount)); + persistMgr->transfer(TMEMBER(_pFStepX)); + persistMgr->transfer(TMEMBER(_pFStepY)); + persistMgr->transfer(TMEMBER(_pFX)); + persistMgr->transfer(TMEMBER(_pFY)); + persistMgr->transfer(TMEMBER(_standSprite)); + _talkSprites.persist(persistMgr); + _talkSpritesEx.persist(persistMgr); + persistMgr->transfer(TMEMBER_INT(_targetDir)); + persistMgr->transfer(TMEMBER_INT(_afterWalkDir)); + persistMgr->transfer(TMEMBER(_targetPoint)); + persistMgr->transfer(TMEMBER(_turnLeftSprite)); + persistMgr->transfer(TMEMBER(_turnRightSprite)); + persistMgr->transfer(TMEMBER(_walkSprite)); + + persistMgr->transfer(TMEMBER(_animSprite2)); + persistMgr->transfer(TMEMBER(_talkAnimName)); + persistMgr->transfer(TMEMBER(_idleAnimName)); + persistMgr->transfer(TMEMBER(_walkAnimName)); + persistMgr->transfer(TMEMBER(_turnLeftAnimName)); + persistMgr->transfer(TMEMBER(_turnRightAnimName)); + + _anims.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +TDirection AdActor::angleToDirection(int angle) { + TDirection ret = DI_DOWN;; + + if (angle > -112 && angle <= -67) { + ret = DI_UP; + } else if (angle > -67 && angle <= -22) { + ret = DI_UPRIGHT; + } else if (angle > -22 && angle <= 22) { + ret = DI_RIGHT; + } else if (angle > 22 && angle <= 67) { + ret = DI_DOWNRIGHT; + } else if (angle > 67 && angle <= 112) { + ret = DI_DOWN; + } else if (angle > 112 && angle <= 157) { + ret = DI_DOWNLEFT; + } else if ((angle > 157 && angle <= 180) || (angle >= -180 && angle <= -157)) { + ret = DI_LEFT; + } else if (angle > -157 && angle <= -112) { + ret = DI_UPLEFT; + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +int AdActor::getHeight() { + // if no current sprite is set, set some + if (_currentSprite == NULL) { + if (_standSprite) { + _currentSprite = _standSprite->getSprite(_dir); + } else { + AdSpriteSet *anim = getAnimByName(_idleAnimName); + if (anim) { + _currentSprite = anim->getSprite(_dir); + } + } + } + // and get height + return AdTalkHolder::getHeight(); +} + + +////////////////////////////////////////////////////////////////////////// +AdSpriteSet *AdActor::getAnimByName(const Common::String &animName) { + for (uint32 i = 0; i < _anims.size(); i++) { + if (animName.compareToIgnoreCase(_anims[i]->getName()) == 0) { + return _anims[i]; + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool AdActor::mergeAnims(const char *animsFilename) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ANIMATION) + TOKEN_TABLE_END + + + byte *fileBuffer = BaseFileManager::getEngineInstance()->readWholeFile(animsFilename); + if (fileBuffer == NULL) { + _gameRef->LOG(0, "AdActor::MergeAnims failed for file '%s'", animsFilename); + return STATUS_FAILED; + } + + byte *buffer = fileBuffer; + byte *params; + int cmd; + BaseParser parser; + + bool ret = STATUS_OK; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_ANIMATION: { + AdSpriteSet *anim = new AdSpriteSet(_gameRef, this); + if (!anim || DID_FAIL(anim->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + ret = STATUS_FAILED; + } else { + _anims.add(anim); + } + } + break; + } + } + delete[] fileBuffer; + return ret; +} + +////////////////////////////////////////////////////////////////////////// +bool AdActor::playAnim(const char *filename) { + // if we have an anim with this name, use it + AdSpriteSet *anim = getAnimByName(filename); + if (anim) { + _animSprite2 = anim->getSprite(_dir); + if (_animSprite2) { + _animSprite2->reset(); + _state = STATE_PLAYING_ANIM_SET; + return STATUS_OK; + } + } + // otherwise call the standard handler + return AdTalkHolder::playAnim(filename); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_actor.h b/engines/wintermute/ad/ad_actor.h index 370a91cc2287..271e57cb85bb 100644 --- a/engines/wintermute/ad/ad_actor.h +++ b/engines/wintermute/ad/ad_actor.h @@ -1,108 +1,108 @@ -/* 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_ADACTOR_H -#define WINTERMUTE_ADACTOR_H - - -#include "engines/wintermute/dctypes.h" // Added by ClassView -#include "engines/wintermute/ad/ad_types.h" // Added by ClassView -#include "engines/wintermute/ad/ad_talk_holder.h" -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/base_point.h" // Added by ClassView -#include "engines/wintermute/persistent.h" -#include "common/str.h" - -namespace Wintermute { - -class AdSpriteSet; -class AdPath; -class BaseSprite; -class AdActor : public AdTalkHolder { -public: - TDirection angleToDirection(int angle); - DECLARE_PERSISTENT(AdActor, AdTalkHolder) - virtual int getHeight(); - BaseSprite *getTalkStance(const char *stance); - virtual void goTo(int x, int y, TDirection afterWalkDir = DI_NONE); - BasePoint *_targetPoint; - virtual bool update(); - virtual bool display(); - virtual void turnTo(TDirection dir); - AdActor(BaseGame *inGame/*=NULL*/); - virtual ~AdActor(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - - -private: - TDirection _targetDir; - TDirection _afterWalkDir; - - AdPath *_path; - AdSpriteSet *_walkSprite; - AdSpriteSet *_standSprite; - AdSpriteSet *_turnLeftSprite; - AdSpriteSet *_turnRightSprite; - BaseArray _talkSprites; - BaseArray _talkSpritesEx; - TDirection _dir; - // new anim system - Common::String _talkAnimName; - Common::String _idleAnimName; - Common::String _walkAnimName; - Common::String _turnLeftAnimName; - Common::String _turnRightAnimName; - BaseArray _anims; - virtual bool playAnim(const char *filename); - AdSpriteSet *getAnimByName(const Common::String &animName); - - // 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(); - - bool setDefaultAnimNames(); - BaseSprite *getTalkStanceOld(const char *stance); - bool mergeAnims(const char *animsFilename); - BaseSprite *_animSprite2; - - void initLine(BasePoint startPt, BasePoint endPt); - void getNextStep(); - void followPath(); - double _pFStepX; - double _pFStepY; - double _pFX; - double _pFY; - int _pFCount; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADACTOR_H +#define WINTERMUTE_ADACTOR_H + + +#include "engines/wintermute/dctypes.h" // Added by ClassView +#include "engines/wintermute/ad/ad_types.h" // Added by ClassView +#include "engines/wintermute/ad/ad_talk_holder.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base_point.h" // Added by ClassView +#include "engines/wintermute/persistent.h" +#include "common/str.h" + +namespace Wintermute { + +class AdSpriteSet; +class AdPath; +class BaseSprite; +class AdActor : public AdTalkHolder { +public: + TDirection angleToDirection(int angle); + DECLARE_PERSISTENT(AdActor, AdTalkHolder) + virtual int getHeight(); + BaseSprite *getTalkStance(const char *stance); + virtual void goTo(int x, int y, TDirection afterWalkDir = DI_NONE); + BasePoint *_targetPoint; + virtual bool update(); + virtual bool display(); + virtual void turnTo(TDirection dir); + AdActor(BaseGame *inGame/*=NULL*/); + virtual ~AdActor(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + + +private: + TDirection _targetDir; + TDirection _afterWalkDir; + + AdPath *_path; + AdSpriteSet *_walkSprite; + AdSpriteSet *_standSprite; + AdSpriteSet *_turnLeftSprite; + AdSpriteSet *_turnRightSprite; + BaseArray _talkSprites; + BaseArray _talkSpritesEx; + TDirection _dir; + // new anim system + Common::String _talkAnimName; + Common::String _idleAnimName; + Common::String _walkAnimName; + Common::String _turnLeftAnimName; + Common::String _turnRightAnimName; + BaseArray _anims; + virtual bool playAnim(const char *filename); + AdSpriteSet *getAnimByName(const Common::String &animName); + + // 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(); + + bool setDefaultAnimNames(); + BaseSprite *getTalkStanceOld(const char *stance); + bool mergeAnims(const char *animsFilename); + BaseSprite *_animSprite2; + + void initLine(BasePoint startPt, BasePoint endPt); + void getNextStep(); + void followPath(); + double _pFStepX; + double _pFStepY; + double _pFX; + double _pFY; + int _pFCount; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_entity.cpp b/engines/wintermute/ad/ad_entity.cpp index 67a919dd6bf6..234af1fffa9b 100644 --- a/engines/wintermute/ad/ad_entity.cpp +++ b/engines/wintermute/ad/ad_entity.cpp @@ -1,1121 +1,1121 @@ -/* 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_entity.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_active_rect.h" -#include "engines/wintermute/base/base_surface_storage.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_scene.h" -#include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/ad/ad_waypoint_group.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/base/base_region.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/utils/utils.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/video/video_theora_player.h" -#include "engines/wintermute/base/particles/part_emitter.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdEntity, false) - -////////////////////////////////////////////////////////////////////////// -AdEntity::AdEntity(BaseGame *inGame) : AdTalkHolder(inGame) { - _type = OBJECT_ENTITY; - _subtype = ENTITY_NORMAL; - _region = NULL; - _item = NULL; - - _walkToX = _walkToY = 0; - _walkToDir = DI_NONE; - - _theora = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdEntity::~AdEntity() { - _gameRef->unregisterObject(_region); - - delete _theora; - _theora = NULL; - - delete[] _item; - _item = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdEntity::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 ENTITY file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(ENTITY) -TOKEN_DEF(SPRITE) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(NAME) -TOKEN_DEF(SCALABLE) -TOKEN_DEF(REGISTRABLE) -TOKEN_DEF(INTERACTIVE) -TOKEN_DEF(SHADOWABLE) -TOKEN_DEF(COLORABLE) -TOKEN_DEF(ACTIVE) -TOKEN_DEF(EVENTS) -TOKEN_DEF(FONT) -TOKEN_DEF(TALK_SPECIAL) -TOKEN_DEF(TALK) -TOKEN_DEF(CURSOR) -TOKEN_DEF(REGION) -TOKEN_DEF(BLOCKED_REGION) -TOKEN_DEF(EDITOR_SELECTED) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(SOUND_START_TIME) -TOKEN_DEF(SOUND_VOLUME) -TOKEN_DEF(SOUND_PANNING) -TOKEN_DEF(SOUND) -TOKEN_DEF(SUBTYPE) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(WAYPOINTS) -TOKEN_DEF(IGNORE_ITEMS) -TOKEN_DEF(ROTABLE) -TOKEN_DEF(ROTATABLE) -TOKEN_DEF(ALPHA_COLOR) -TOKEN_DEF(SCALE) -TOKEN_DEF(RELATIVE_SCALE) -TOKEN_DEF(ALPHA) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(ITEM) -TOKEN_DEF(WALK_TO_X) -TOKEN_DEF(WALK_TO_Y) -TOKEN_DEF(WALK_TO_DIR) -TOKEN_DEF(SAVE_STATE) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdEntity::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ENTITY) - TOKEN_TABLE(SPRITE) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(SCALABLE) - TOKEN_TABLE(REGISTRABLE) - TOKEN_TABLE(INTERACTIVE) - TOKEN_TABLE(SHADOWABLE) - TOKEN_TABLE(COLORABLE) - TOKEN_TABLE(ACTIVE) - TOKEN_TABLE(EVENTS) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TALK_SPECIAL) - TOKEN_TABLE(TALK) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(REGION) - TOKEN_TABLE(BLOCKED_REGION) - TOKEN_TABLE(EDITOR_SELECTED) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(SOUND_START_TIME) - TOKEN_TABLE(SOUND_VOLUME) - TOKEN_TABLE(SOUND_PANNING) - TOKEN_TABLE(SOUND) - TOKEN_TABLE(SUBTYPE) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(WAYPOINTS) - TOKEN_TABLE(IGNORE_ITEMS) - TOKEN_TABLE(ROTABLE) - TOKEN_TABLE(ROTATABLE) - TOKEN_TABLE(ALPHA_COLOR) - TOKEN_TABLE(SCALE) - TOKEN_TABLE(RELATIVE_SCALE) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(ITEM) - TOKEN_TABLE(WALK_TO_X) - TOKEN_TABLE(WALK_TO_Y) - TOKEN_TABLE(WALK_TO_DIR) - TOKEN_TABLE(SAVE_STATE) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY) { - _gameRef->LOG(0, "'ENTITY' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - AdGame *adGame = (AdGame *)_gameRef; - BaseSprite *spr = NULL; - int ar = 0, ag = 0, ab = 0, alpha = 0; - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_SPRITE: { - delete _sprite; - _sprite = NULL; - spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } else { - _sprite = spr; - } - } - break; - - case TOKEN_TALK: { - spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSprites.add(spr); - } - } - break; - - case TOKEN_TALK_SPECIAL: { - spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSpritesEx.add(spr); - } - } - break; - - case TOKEN_NAME: - setName((char *)params); - break; - - case TOKEN_ITEM: - setItem((char *)params); - break; - - case TOKEN_CAPTION: - setCaption((char *)params); - break; - - case TOKEN_FONT: - setFont((char *)params); - break; - - case TOKEN_SCALABLE: - parser.scanStr((char *)params, "%b", &_zoomable); - break; - - case TOKEN_SCALE: { - int s; - parser.scanStr((char *)params, "%d", &s); - _scale = (float)s; - - } - break; - - case TOKEN_RELATIVE_SCALE: { - int s; - parser.scanStr((char *)params, "%d", &s); - _relativeScale = (float)s; - - } - break; - - case TOKEN_ROTABLE: - case TOKEN_ROTATABLE: - parser.scanStr((char *)params, "%b", &_rotatable); - break; - - case TOKEN_REGISTRABLE: - case TOKEN_INTERACTIVE: - parser.scanStr((char *)params, "%b", &_registrable); - break; - - case TOKEN_SHADOWABLE: - case TOKEN_COLORABLE: - parser.scanStr((char *)params, "%b", &_shadowable); - break; - - case TOKEN_ACTIVE: - parser.scanStr((char *)params, "%b", &_active); - 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_EDITOR_SELECTED: - parser.scanStr((char *)params, "%b", &_editorSelected); - break; - - case TOKEN_REGION: { - if (_region) { - _gameRef->unregisterObject(_region); - } - _region = NULL; - BaseRegion *rgn = new BaseRegion(_gameRef); - if (!rgn || DID_FAIL(rgn->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - } else { - _region = rgn; - _gameRef->registerObject(_region); - } - } - break; - - case TOKEN_BLOCKED_REGION: { - delete _blockRegion; - _blockRegion = NULL; - delete _currentBlockRegion; - _currentBlockRegion = NULL; - BaseRegion *rgn = new BaseRegion(_gameRef); - BaseRegion *crgn = new BaseRegion(_gameRef); - if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { - delete _blockRegion; - _blockRegion = NULL; - delete _currentBlockRegion; - _currentBlockRegion = NULL; - cmd = PARSERR_GENERIC; - } else { - _blockRegion = rgn; - _currentBlockRegion = crgn; - _currentBlockRegion->mimic(_blockRegion); - } - } - break; - - case TOKEN_WAYPOINTS: { - delete _wptGroup; - _wptGroup = NULL; - delete _currentWptGroup; - _currentWptGroup = NULL; - AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); - AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); - if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { - delete _wptGroup; - _wptGroup = NULL; - delete _currentWptGroup; - _currentWptGroup = NULL; - cmd = PARSERR_GENERIC; - } else { - _wptGroup = wpt; - _currentWptGroup = cwpt; - _currentWptGroup->mimic(_wptGroup); - } - } - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_SUBTYPE: { - if (scumm_stricmp((char *)params, "sound") == 0) { - delete _sprite; - _sprite = NULL; - if (_gameRef->_editorMode) { - spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile("entity_sound.sprite"))) { - cmd = PARSERR_GENERIC; - } else { - _sprite = spr; - } - } - if (_gameRef->_editorMode) { - _editorOnly = true; - } - _zoomable = false; - _rotatable = false; - _registrable = _gameRef->_editorMode; - _shadowable = false; - _subtype = ENTITY_SOUND; - } - } - break; - - case TOKEN_SOUND: - playSFX((char *)params, false, false); - break; - - case TOKEN_SOUND_START_TIME: - parser.scanStr((char *)params, "%d", &_sFXStart); - break; - - case TOKEN_SOUND_VOLUME: - parser.scanStr((char *)params, "%d", &_sFXVolume); - break; - - case TOKEN_SOUND_PANNING: - parser.scanStr((char *)params, "%b", &_autoSoundPanning); - break; - - case TOKEN_SAVE_STATE: - parser.scanStr((char *)params, "%b", &_saveState); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_IGNORE_ITEMS: - parser.scanStr((char *)params, "%b", &_ignoreItems); - break; - - case TOKEN_ALPHA_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); - break; - - case TOKEN_ALPHA: - parser.scanStr((char *)params, "%d", &alpha); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - - case TOKEN_WALK_TO_X: - parser.scanStr((char *)params, "%d", &_walkToX); - break; - - case TOKEN_WALK_TO_Y: - parser.scanStr((char *)params, "%d", &_walkToY); - break; - - case TOKEN_WALK_TO_DIR: { - int i; - parser.scanStr((char *)params, "%d", &i); - if (i < 0) { - i = 0; - } - if (i >= NUM_DIRECTIONS) { - i = DI_NONE; - } - _walkToDir = (TDirection)i; - } - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ENTITY definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading ENTITY definition"); - if (spr) { - delete spr; - } - return STATUS_FAILED; - } - - if (_region && _sprite) { - _gameRef->LOG(0, "Warning: Entity '%s' has both sprite and region.", getName()); - } - - updatePosition(); - - if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { - ar = ag = ab = 255; - } - _alphaColor = BYTETORGBA(ar, ag, ab, alpha); - _state = STATE_READY; - - if (_item && ((AdGame *)_gameRef)->isItemTaken(_item)) { - _active = false; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::display() { - if (_active) { - updateSounds(); - - uint32 alpha; - if (_alphaColor != 0) { - alpha = _alphaColor; - } else { - alpha = _shadowable ? ((AdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY) : 0xFFFFFFFF; - } - - float scaleX, scaleY; - getScale(&scaleX, &scaleY); - - float rotate; - if (_rotatable) { - if (_rotateValid) { - rotate = _rotate; - } else { - rotate = ((AdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; - } - } else { - rotate = 0.0f; - } - - - bool reg = _registrable; - if (_ignoreItems && ((AdGame *)_gameRef)->_selectedItem) { - reg = false; - } - - if (_region && (reg || _editorAlwaysRegister)) { - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, _registerAlias, _region, _gameRef->_offsetX, _gameRef->_offsetY)); - } - - displaySpriteAttachments(true); - if (_theora && (_theora->isPlaying() || _theora->isPaused())) { - _theora->display(alpha); - } else if (_currentSprite) { - _currentSprite->display(_posX, - _posY, - (reg || _editorAlwaysRegister) ? _registerAlias : NULL, - scaleX, - scaleY, - alpha, - rotate, - _blendMode); - } - displaySpriteAttachments(false); - - if (_partEmitter) { - _partEmitter->display(_region); - } - - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::update() { - _currentSprite = NULL; - - if (_state == STATE_READY && _animSprite) { - delete _animSprite; - _animSprite = NULL; - } - - // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { - _state = STATE_READY; - _currentSprite = _animSprite; - } - - if (_sentence && _state != STATE_TALKING) { - _sentence->finish(); - } - - // default: stand animation - if (!_currentSprite) { - _currentSprite = _sprite; - } - - switch (_state) { - ////////////////////////////////////////////////////////////////////////// - case STATE_PLAYING_ANIM: - _currentSprite = _animSprite; - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_READY: - if (!_animSprite) { - _currentSprite = _sprite; - } - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_TALKING: { - _sentence->update(); - if (_sentence->_currentSprite) { - _tempSprite2 = _sentence->_currentSprite; - } - - bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { - if (timeIsUp) { - _sentence->finish(); - _tempSprite2 = NULL; - _state = STATE_READY; - } else { - _tempSprite2 = getTalkStance(_sentence->getNextStance()); - if (_tempSprite2) { - _tempSprite2->reset(); - _currentSprite = _tempSprite2; - } - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } else { - _currentSprite = _tempSprite2; - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } - break; - default: // Silence unhandled enum-warning - break; - } - - - if (_currentSprite) { - _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); - if (_currentSprite->_changed) { - _posX += _currentSprite->_moveX; - _posY += _currentSprite->_moveY; - } - } - - updateBlockRegion(); - _ready = (_state == STATE_READY); - - if (_theora) { - int offsetX, offsetY; - _gameRef->getOffset(&offsetX, &offsetY); - _theora->_posX = _posX - offsetX; - _theora->_posY = _posY - offsetY; - - _theora->update(); - if (_theora->isFinished()) { - _theora->stop(); - delete _theora; - _theora = NULL; - } - } - - updatePartEmitter(); - updateSpriteAttachments(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // StopSound - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "StopSound") == 0 && _subtype == ENTITY_SOUND) { - stack->correctParams(0); - - if (DID_FAIL(stopSFX(false))) { - stack->pushBool(false); - } else { - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PlayTheora - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PlayTheora") == 0) { - stack->correctParams(4); - const char *filename = stack->pop()->getString(); - bool looping = stack->pop()->getBool(false); - ScValue *valAlpha = stack->pop(); - int startTime = stack->pop()->getInt(); - - delete _theora; - _theora = new VideoTheoraPlayer(_gameRef); - if (_theora && DID_SUCCEED(_theora->initialize(filename))) { - if (!valAlpha->isNULL()) { - _theora->setAlphaImage(valAlpha->getString()); - } - _theora->play(VID_PLAY_POS, 0, 0, false, false, looping, startTime, _scale >= 0.0f ? _scale : -1.0f, _sFXVolume); - //if (_scale>=0) _theora->_playZoom = _scale; - stack->pushBool(true); - } else { - script->runtimeError("Entity.PlayTheora - error playing video '%s'", filename); - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // StopTheora - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StopTheora") == 0) { - stack->correctParams(0); - if (_theora) { - _theora->stop(); - delete _theora; - _theora = NULL; - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsTheoraPlaying - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsTheoraPlaying") == 0) { - stack->correctParams(0); - if (_theora && _theora->isPlaying()) { - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PauseTheora - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PauseTheora") == 0) { - stack->correctParams(0); - if (_theora && _theora->isPlaying()) { - _theora->pause(); - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ResumeTheora - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ResumeTheora") == 0) { - stack->correctParams(0); - if (_theora && _theora->isPaused()) { - _theora->resume(); - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsTheoraPaused - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsTheoraPaused") == 0) { - stack->correctParams(0); - if (_theora && _theora->isPaused()) { - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // CreateRegion - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateRegion") == 0) { - stack->correctParams(0); - if (!_region) { - _region = new BaseRegion(_gameRef); - _gameRef->registerObject(_region); - } - if (_region) { - stack->pushNative(_region, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteRegion - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteRegion") == 0) { - stack->correctParams(0); - if (_region) { - _gameRef->unregisterObject(_region); - _region = NULL; - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } else { - return AdTalkHolder::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdEntity::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type (RO) - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("entity"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Item - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Item") == 0) { - if (_item) { - _scValue->setString(_item); - } else { - _scValue->setNULL(); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Subtype (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Subtype") == 0) { - if (_subtype == ENTITY_SOUND) { - _scValue->setString("sound"); - } else { - _scValue->setString("normal"); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToX") == 0) { - _scValue->setInt(_walkToX); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToY") == 0) { - _scValue->setInt(_walkToY); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToDirection - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToDirection") == 0) { - _scValue->setInt((int)_walkToDir); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Region (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Region") == 0) { - if (_region) { - _scValue->setNative(_region, true); - } else { - _scValue->setNULL(); - } - return _scValue; - } else { - return AdTalkHolder::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::scSetProperty(const char *name, ScValue *value) { - - ////////////////////////////////////////////////////////////////////////// - // Item - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Item") == 0) { - setItem(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToX") == 0) { - _walkToX = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToY") == 0) { - _walkToY = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // WalkToDirection - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "WalkToDirection") == 0) { - int dir = value->getInt(); - if (dir >= 0 && dir < NUM_DIRECTIONS) { - _walkToDir = (TDirection)dir; - } - return STATUS_OK; - } else { - return AdTalkHolder::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdEntity::scToString() { - return "[entity object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ENTITY {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - if (_subtype == ENTITY_SOUND) { - buffer->putTextIndent(indent + 2, "SUBTYPE=\"SOUND\"\n"); - } - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "SCALABLE=%s\n", _zoomable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "INTERACTIVE=%s\n", _registrable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "COLORABLE=%s\n", _shadowable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); - if (_ignoreItems) { - buffer->putTextIndent(indent + 2, "IGNORE_ITEMS=%s\n", _ignoreItems ? "TRUE" : "FALSE"); - } - if (_rotatable) { - buffer->putTextIndent(indent + 2, "ROTATABLE=%s\n", _rotatable ? "TRUE" : "FALSE"); - } - - if (!_autoSoundPanning) { - buffer->putTextIndent(indent + 2, "SOUND_PANNING=%s\n", _autoSoundPanning ? "TRUE" : "FALSE"); - } - - if (!_saveState) { - buffer->putTextIndent(indent + 2, "SAVE_STATE=%s\n", _saveState ? "TRUE" : "FALSE"); - } - - if (_item && _item[0] != '\0') { - buffer->putTextIndent(indent + 2, "ITEM=\"%s\"\n", _item); - } - - buffer->putTextIndent(indent + 2, "WALK_TO_X=%d\n", _walkToX); - buffer->putTextIndent(indent + 2, "WALK_TO_Y=%d\n", _walkToY); - if (_walkToDir != DI_NONE) { - buffer->putTextIndent(indent + 2, "WALK_TO_DIR=%d\n", (int)_walkToDir); - } - - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_subtype == ENTITY_NORMAL && _sprite && _sprite->getFilename()) { - buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _sprite->getFilename()); - } - - if (_subtype == ENTITY_SOUND && _sFX && _sFX->getFilename()) { - buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sFX->getFilename()); - buffer->putTextIndent(indent + 2, "SOUND_START_TIME=%d\n", _sFXStart); - buffer->putTextIndent(indent + 2, "SOUND_VOLUME=%d\n", _sFXVolume); - } - - - if (RGBCOLGetR(_alphaColor) != 0 || RGBCOLGetG(_alphaColor) != 0 || RGBCOLGetB(_alphaColor) != 0) { - buffer->putTextIndent(indent + 2, "ALPHA_COLOR { %d,%d,%d }\n", RGBCOLGetR(_alphaColor), RGBCOLGetG(_alphaColor), RGBCOLGetB(_alphaColor)); - } - - if (RGBCOLGetA(_alphaColor) != 0) { - buffer->putTextIndent(indent + 2, "ALPHA = %d\n", RGBCOLGetA(_alphaColor)); - } - - if (_scale >= 0) { - buffer->putTextIndent(indent + 2, "SCALE = %d\n", (int)_scale); - } - - if (_relativeScale != 0) { - buffer->putTextIndent(indent + 2, "RELATIVE_SCALE = %d\n", (int)_relativeScale); - } - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - AdTalkHolder::saveAsText(buffer, indent + 2); - - if (_region) { - _region->saveAsText(buffer, indent + 2); - } - - if (_scProp) { - _scProp->saveAsText(buffer, indent + 2); - } - - AdObject::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int AdEntity::getHeight() { - if (_region && !_sprite) { - return _region->_rect.bottom - _region->_rect.top; - } else { - if (_currentSprite == NULL) { - _currentSprite = _sprite; - } - return AdObject::getHeight(); - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdEntity::updatePosition() { - if (_region && !_sprite) { - _posX = _region->_rect.left + (_region->_rect.right - _region->_rect.left) / 2; - _posY = _region->_rect.bottom; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::persist(BasePersistenceManager *persistMgr) { - AdTalkHolder::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_item)); - persistMgr->transfer(TMEMBER(_region)); - //persistMgr->transfer(TMEMBER(_sprite)); - persistMgr->transfer(TMEMBER_INT(_subtype)); - _talkSprites.persist(persistMgr); - _talkSpritesEx.persist(persistMgr); - - persistMgr->transfer(TMEMBER(_walkToX)); - persistMgr->transfer(TMEMBER(_walkToY)); - persistMgr->transfer(TMEMBER_INT(_walkToDir)); - - persistMgr->transfer(TMEMBER(_theora)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdEntity::setItem(const char *itemName) { - BaseUtils::setString(&_item, itemName); -} - -////////////////////////////////////////////////////////////////////////// -bool AdEntity::setSprite(const char *filename) { - if (_currentSprite == _sprite) { - _currentSprite = NULL; - } - - delete _sprite; - _sprite = NULL; - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - delete _sprite; - _sprite = NULL; - return STATUS_FAILED; - } else { - _sprite = spr; - _currentSprite = _sprite; - return STATUS_OK; - } -} - -} // end of namespace Wintermute +/* 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_entity.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_active_rect.h" +#include "engines/wintermute/base/base_surface_storage.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_scene.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/ad/ad_waypoint_group.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/utils/utils.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/video/video_theora_player.h" +#include "engines/wintermute/base/particles/part_emitter.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdEntity, false) + +////////////////////////////////////////////////////////////////////////// +AdEntity::AdEntity(BaseGame *inGame) : AdTalkHolder(inGame) { + _type = OBJECT_ENTITY; + _subtype = ENTITY_NORMAL; + _region = NULL; + _item = NULL; + + _walkToX = _walkToY = 0; + _walkToDir = DI_NONE; + + _theora = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdEntity::~AdEntity() { + _gameRef->unregisterObject(_region); + + delete _theora; + _theora = NULL; + + delete[] _item; + _item = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdEntity::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 ENTITY file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(ENTITY) +TOKEN_DEF(SPRITE) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(SCALABLE) +TOKEN_DEF(REGISTRABLE) +TOKEN_DEF(INTERACTIVE) +TOKEN_DEF(SHADOWABLE) +TOKEN_DEF(COLORABLE) +TOKEN_DEF(ACTIVE) +TOKEN_DEF(EVENTS) +TOKEN_DEF(FONT) +TOKEN_DEF(TALK_SPECIAL) +TOKEN_DEF(TALK) +TOKEN_DEF(CURSOR) +TOKEN_DEF(REGION) +TOKEN_DEF(BLOCKED_REGION) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(SOUND_START_TIME) +TOKEN_DEF(SOUND_VOLUME) +TOKEN_DEF(SOUND_PANNING) +TOKEN_DEF(SOUND) +TOKEN_DEF(SUBTYPE) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(WAYPOINTS) +TOKEN_DEF(IGNORE_ITEMS) +TOKEN_DEF(ROTABLE) +TOKEN_DEF(ROTATABLE) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(SCALE) +TOKEN_DEF(RELATIVE_SCALE) +TOKEN_DEF(ALPHA) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(ITEM) +TOKEN_DEF(WALK_TO_X) +TOKEN_DEF(WALK_TO_Y) +TOKEN_DEF(WALK_TO_DIR) +TOKEN_DEF(SAVE_STATE) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdEntity::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ENTITY) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SCALABLE) + TOKEN_TABLE(REGISTRABLE) + TOKEN_TABLE(INTERACTIVE) + TOKEN_TABLE(SHADOWABLE) + TOKEN_TABLE(COLORABLE) + TOKEN_TABLE(ACTIVE) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TALK_SPECIAL) + TOKEN_TABLE(TALK) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(REGION) + TOKEN_TABLE(BLOCKED_REGION) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(SOUND_START_TIME) + TOKEN_TABLE(SOUND_VOLUME) + TOKEN_TABLE(SOUND_PANNING) + TOKEN_TABLE(SOUND) + TOKEN_TABLE(SUBTYPE) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(WAYPOINTS) + TOKEN_TABLE(IGNORE_ITEMS) + TOKEN_TABLE(ROTABLE) + TOKEN_TABLE(ROTATABLE) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(SCALE) + TOKEN_TABLE(RELATIVE_SCALE) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(ITEM) + TOKEN_TABLE(WALK_TO_X) + TOKEN_TABLE(WALK_TO_Y) + TOKEN_TABLE(WALK_TO_DIR) + TOKEN_TABLE(SAVE_STATE) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY) { + _gameRef->LOG(0, "'ENTITY' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + AdGame *adGame = (AdGame *)_gameRef; + BaseSprite *spr = NULL; + int ar = 0, ag = 0, ab = 0, alpha = 0; + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_SPRITE: { + delete _sprite; + _sprite = NULL; + spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } else { + _sprite = spr; + } + } + break; + + case TOKEN_TALK: { + spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSprites.add(spr); + } + } + break; + + case TOKEN_TALK_SPECIAL: { + spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, adGame->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSpritesEx.add(spr); + } + } + break; + + case TOKEN_NAME: + setName((char *)params); + break; + + case TOKEN_ITEM: + setItem((char *)params); + break; + + case TOKEN_CAPTION: + setCaption((char *)params); + break; + + case TOKEN_FONT: + setFont((char *)params); + break; + + case TOKEN_SCALABLE: + parser.scanStr((char *)params, "%b", &_zoomable); + break; + + case TOKEN_SCALE: { + int s; + parser.scanStr((char *)params, "%d", &s); + _scale = (float)s; + + } + break; + + case TOKEN_RELATIVE_SCALE: { + int s; + parser.scanStr((char *)params, "%d", &s); + _relativeScale = (float)s; + + } + break; + + case TOKEN_ROTABLE: + case TOKEN_ROTATABLE: + parser.scanStr((char *)params, "%b", &_rotatable); + break; + + case TOKEN_REGISTRABLE: + case TOKEN_INTERACTIVE: + parser.scanStr((char *)params, "%b", &_registrable); + break; + + case TOKEN_SHADOWABLE: + case TOKEN_COLORABLE: + parser.scanStr((char *)params, "%b", &_shadowable); + break; + + case TOKEN_ACTIVE: + parser.scanStr((char *)params, "%b", &_active); + 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_EDITOR_SELECTED: + parser.scanStr((char *)params, "%b", &_editorSelected); + break; + + case TOKEN_REGION: { + if (_region) { + _gameRef->unregisterObject(_region); + } + _region = NULL; + BaseRegion *rgn = new BaseRegion(_gameRef); + if (!rgn || DID_FAIL(rgn->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + } else { + _region = rgn; + _gameRef->registerObject(_region); + } + } + break; + + case TOKEN_BLOCKED_REGION: { + delete _blockRegion; + _blockRegion = NULL; + delete _currentBlockRegion; + _currentBlockRegion = NULL; + BaseRegion *rgn = new BaseRegion(_gameRef); + BaseRegion *crgn = new BaseRegion(_gameRef); + if (!rgn || !crgn || DID_FAIL(rgn->loadBuffer(params, false))) { + delete _blockRegion; + _blockRegion = NULL; + delete _currentBlockRegion; + _currentBlockRegion = NULL; + cmd = PARSERR_GENERIC; + } else { + _blockRegion = rgn; + _currentBlockRegion = crgn; + _currentBlockRegion->mimic(_blockRegion); + } + } + break; + + case TOKEN_WAYPOINTS: { + delete _wptGroup; + _wptGroup = NULL; + delete _currentWptGroup; + _currentWptGroup = NULL; + AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); + AdWaypointGroup *cwpt = new AdWaypointGroup(_gameRef); + if (!wpt || !cwpt || DID_FAIL(wpt->loadBuffer(params, false))) { + delete _wptGroup; + _wptGroup = NULL; + delete _currentWptGroup; + _currentWptGroup = NULL; + cmd = PARSERR_GENERIC; + } else { + _wptGroup = wpt; + _currentWptGroup = cwpt; + _currentWptGroup->mimic(_wptGroup); + } + } + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_SUBTYPE: { + if (scumm_stricmp((char *)params, "sound") == 0) { + delete _sprite; + _sprite = NULL; + if (_gameRef->_editorMode) { + spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile("entity_sound.sprite"))) { + cmd = PARSERR_GENERIC; + } else { + _sprite = spr; + } + } + if (_gameRef->_editorMode) { + _editorOnly = true; + } + _zoomable = false; + _rotatable = false; + _registrable = _gameRef->_editorMode; + _shadowable = false; + _subtype = ENTITY_SOUND; + } + } + break; + + case TOKEN_SOUND: + playSFX((char *)params, false, false); + break; + + case TOKEN_SOUND_START_TIME: + parser.scanStr((char *)params, "%d", &_sFXStart); + break; + + case TOKEN_SOUND_VOLUME: + parser.scanStr((char *)params, "%d", &_sFXVolume); + break; + + case TOKEN_SOUND_PANNING: + parser.scanStr((char *)params, "%b", &_autoSoundPanning); + break; + + case TOKEN_SAVE_STATE: + parser.scanStr((char *)params, "%b", &_saveState); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_IGNORE_ITEMS: + parser.scanStr((char *)params, "%b", &_ignoreItems); + break; + + case TOKEN_ALPHA_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.scanStr((char *)params, "%d", &alpha); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + + case TOKEN_WALK_TO_X: + parser.scanStr((char *)params, "%d", &_walkToX); + break; + + case TOKEN_WALK_TO_Y: + parser.scanStr((char *)params, "%d", &_walkToY); + break; + + case TOKEN_WALK_TO_DIR: { + int i; + parser.scanStr((char *)params, "%d", &i); + if (i < 0) { + i = 0; + } + if (i >= NUM_DIRECTIONS) { + i = DI_NONE; + } + _walkToDir = (TDirection)i; + } + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ENTITY definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading ENTITY definition"); + if (spr) { + delete spr; + } + return STATUS_FAILED; + } + + if (_region && _sprite) { + _gameRef->LOG(0, "Warning: Entity '%s' has both sprite and region.", getName()); + } + + updatePosition(); + + if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { + ar = ag = ab = 255; + } + _alphaColor = BYTETORGBA(ar, ag, ab, alpha); + _state = STATE_READY; + + if (_item && ((AdGame *)_gameRef)->isItemTaken(_item)) { + _active = false; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::display() { + if (_active) { + updateSounds(); + + uint32 alpha; + if (_alphaColor != 0) { + alpha = _alphaColor; + } else { + alpha = _shadowable ? ((AdGame *)_gameRef)->_scene->getAlphaAt(_posX, _posY) : 0xFFFFFFFF; + } + + float scaleX, scaleY; + getScale(&scaleX, &scaleY); + + float rotate; + if (_rotatable) { + if (_rotateValid) { + rotate = _rotate; + } else { + rotate = ((AdGame *)_gameRef)->_scene->getRotationAt(_posX, _posY) + _relativeRotate; + } + } else { + rotate = 0.0f; + } + + + bool reg = _registrable; + if (_ignoreItems && ((AdGame *)_gameRef)->_selectedItem) { + reg = false; + } + + if (_region && (reg || _editorAlwaysRegister)) { + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, _registerAlias, _region, _gameRef->_offsetX, _gameRef->_offsetY)); + } + + displaySpriteAttachments(true); + if (_theora && (_theora->isPlaying() || _theora->isPaused())) { + _theora->display(alpha); + } else if (_currentSprite) { + _currentSprite->display(_posX, + _posY, + (reg || _editorAlwaysRegister) ? _registerAlias : NULL, + scaleX, + scaleY, + alpha, + rotate, + _blendMode); + } + displaySpriteAttachments(false); + + if (_partEmitter) { + _partEmitter->display(_region); + } + + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::update() { + _currentSprite = NULL; + + if (_state == STATE_READY && _animSprite) { + delete _animSprite; + _animSprite = NULL; + } + + // finished playing animation? + if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { + _state = STATE_READY; + _currentSprite = _animSprite; + } + + if (_sentence && _state != STATE_TALKING) { + _sentence->finish(); + } + + // default: stand animation + if (!_currentSprite) { + _currentSprite = _sprite; + } + + switch (_state) { + ////////////////////////////////////////////////////////////////////////// + case STATE_PLAYING_ANIM: + _currentSprite = _animSprite; + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_READY: + if (!_animSprite) { + _currentSprite = _sprite; + } + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_TALKING: { + _sentence->update(); + if (_sentence->_currentSprite) { + _tempSprite2 = _sentence->_currentSprite; + } + + bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); + if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (timeIsUp) { + _sentence->finish(); + _tempSprite2 = NULL; + _state = STATE_READY; + } else { + _tempSprite2 = getTalkStance(_sentence->getNextStance()); + if (_tempSprite2) { + _tempSprite2->reset(); + _currentSprite = _tempSprite2; + } + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } else { + _currentSprite = _tempSprite2; + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } + break; + default: // Silence unhandled enum-warning + break; + } + + + if (_currentSprite) { + _currentSprite->getCurrentFrame(_zoomable ? ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) : 100); + if (_currentSprite->_changed) { + _posX += _currentSprite->_moveX; + _posY += _currentSprite->_moveY; + } + } + + updateBlockRegion(); + _ready = (_state == STATE_READY); + + if (_theora) { + int offsetX, offsetY; + _gameRef->getOffset(&offsetX, &offsetY); + _theora->_posX = _posX - offsetX; + _theora->_posY = _posY - offsetY; + + _theora->update(); + if (_theora->isFinished()) { + _theora->stop(); + delete _theora; + _theora = NULL; + } + } + + updatePartEmitter(); + updateSpriteAttachments(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // StopSound + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "StopSound") == 0 && _subtype == ENTITY_SOUND) { + stack->correctParams(0); + + if (DID_FAIL(stopSFX(false))) { + stack->pushBool(false); + } else { + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PlayTheora + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PlayTheora") == 0) { + stack->correctParams(4); + const char *filename = stack->pop()->getString(); + bool looping = stack->pop()->getBool(false); + ScValue *valAlpha = stack->pop(); + int startTime = stack->pop()->getInt(); + + delete _theora; + _theora = new VideoTheoraPlayer(_gameRef); + if (_theora && DID_SUCCEED(_theora->initialize(filename))) { + if (!valAlpha->isNULL()) { + _theora->setAlphaImage(valAlpha->getString()); + } + _theora->play(VID_PLAY_POS, 0, 0, false, false, looping, startTime, _scale >= 0.0f ? _scale : -1.0f, _sFXVolume); + //if (_scale>=0) _theora->_playZoom = _scale; + stack->pushBool(true); + } else { + script->runtimeError("Entity.PlayTheora - error playing video '%s'", filename); + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StopTheora + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StopTheora") == 0) { + stack->correctParams(0); + if (_theora) { + _theora->stop(); + delete _theora; + _theora = NULL; + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsTheoraPlaying + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsTheoraPlaying") == 0) { + stack->correctParams(0); + if (_theora && _theora->isPlaying()) { + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PauseTheora + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PauseTheora") == 0) { + stack->correctParams(0); + if (_theora && _theora->isPlaying()) { + _theora->pause(); + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ResumeTheora + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ResumeTheora") == 0) { + stack->correctParams(0); + if (_theora && _theora->isPaused()) { + _theora->resume(); + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsTheoraPaused + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsTheoraPaused") == 0) { + stack->correctParams(0); + if (_theora && _theora->isPaused()) { + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // CreateRegion + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateRegion") == 0) { + stack->correctParams(0); + if (!_region) { + _region = new BaseRegion(_gameRef); + _gameRef->registerObject(_region); + } + if (_region) { + stack->pushNative(_region, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteRegion + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteRegion") == 0) { + stack->correctParams(0); + if (_region) { + _gameRef->unregisterObject(_region); + _region = NULL; + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } else { + return AdTalkHolder::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdEntity::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("entity"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Item + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Item") == 0) { + if (_item) { + _scValue->setString(_item); + } else { + _scValue->setNULL(); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Subtype (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Subtype") == 0) { + if (_subtype == ENTITY_SOUND) { + _scValue->setString("sound"); + } else { + _scValue->setString("normal"); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToX") == 0) { + _scValue->setInt(_walkToX); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToY") == 0) { + _scValue->setInt(_walkToY); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToDirection + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToDirection") == 0) { + _scValue->setInt((int)_walkToDir); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Region (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Region") == 0) { + if (_region) { + _scValue->setNative(_region, true); + } else { + _scValue->setNULL(); + } + return _scValue; + } else { + return AdTalkHolder::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::scSetProperty(const char *name, ScValue *value) { + + ////////////////////////////////////////////////////////////////////////// + // Item + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Item") == 0) { + setItem(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToX") == 0) { + _walkToX = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToY") == 0) { + _walkToY = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // WalkToDirection + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "WalkToDirection") == 0) { + int dir = value->getInt(); + if (dir >= 0 && dir < NUM_DIRECTIONS) { + _walkToDir = (TDirection)dir; + } + return STATUS_OK; + } else { + return AdTalkHolder::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdEntity::scToString() { + return "[entity object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ENTITY {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + if (_subtype == ENTITY_SOUND) { + buffer->putTextIndent(indent + 2, "SUBTYPE=\"SOUND\"\n"); + } + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "SCALABLE=%s\n", _zoomable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "INTERACTIVE=%s\n", _registrable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "COLORABLE=%s\n", _shadowable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); + if (_ignoreItems) { + buffer->putTextIndent(indent + 2, "IGNORE_ITEMS=%s\n", _ignoreItems ? "TRUE" : "FALSE"); + } + if (_rotatable) { + buffer->putTextIndent(indent + 2, "ROTATABLE=%s\n", _rotatable ? "TRUE" : "FALSE"); + } + + if (!_autoSoundPanning) { + buffer->putTextIndent(indent + 2, "SOUND_PANNING=%s\n", _autoSoundPanning ? "TRUE" : "FALSE"); + } + + if (!_saveState) { + buffer->putTextIndent(indent + 2, "SAVE_STATE=%s\n", _saveState ? "TRUE" : "FALSE"); + } + + if (_item && _item[0] != '\0') { + buffer->putTextIndent(indent + 2, "ITEM=\"%s\"\n", _item); + } + + buffer->putTextIndent(indent + 2, "WALK_TO_X=%d\n", _walkToX); + buffer->putTextIndent(indent + 2, "WALK_TO_Y=%d\n", _walkToY); + if (_walkToDir != DI_NONE) { + buffer->putTextIndent(indent + 2, "WALK_TO_DIR=%d\n", (int)_walkToDir); + } + + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_subtype == ENTITY_NORMAL && _sprite && _sprite->getFilename()) { + buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _sprite->getFilename()); + } + + if (_subtype == ENTITY_SOUND && _sFX && _sFX->getFilename()) { + buffer->putTextIndent(indent + 2, "SOUND=\"%s\"\n", _sFX->getFilename()); + buffer->putTextIndent(indent + 2, "SOUND_START_TIME=%d\n", _sFXStart); + buffer->putTextIndent(indent + 2, "SOUND_VOLUME=%d\n", _sFXVolume); + } + + + if (RGBCOLGetR(_alphaColor) != 0 || RGBCOLGetG(_alphaColor) != 0 || RGBCOLGetB(_alphaColor) != 0) { + buffer->putTextIndent(indent + 2, "ALPHA_COLOR { %d,%d,%d }\n", RGBCOLGetR(_alphaColor), RGBCOLGetG(_alphaColor), RGBCOLGetB(_alphaColor)); + } + + if (RGBCOLGetA(_alphaColor) != 0) { + buffer->putTextIndent(indent + 2, "ALPHA = %d\n", RGBCOLGetA(_alphaColor)); + } + + if (_scale >= 0) { + buffer->putTextIndent(indent + 2, "SCALE = %d\n", (int)_scale); + } + + if (_relativeScale != 0) { + buffer->putTextIndent(indent + 2, "RELATIVE_SCALE = %d\n", (int)_relativeScale); + } + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + AdTalkHolder::saveAsText(buffer, indent + 2); + + if (_region) { + _region->saveAsText(buffer, indent + 2); + } + + if (_scProp) { + _scProp->saveAsText(buffer, indent + 2); + } + + AdObject::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int AdEntity::getHeight() { + if (_region && !_sprite) { + return _region->_rect.bottom - _region->_rect.top; + } else { + if (_currentSprite == NULL) { + _currentSprite = _sprite; + } + return AdObject::getHeight(); + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdEntity::updatePosition() { + if (_region && !_sprite) { + _posX = _region->_rect.left + (_region->_rect.right - _region->_rect.left) / 2; + _posY = _region->_rect.bottom; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::persist(BasePersistenceManager *persistMgr) { + AdTalkHolder::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_item)); + persistMgr->transfer(TMEMBER(_region)); + //persistMgr->transfer(TMEMBER(_sprite)); + persistMgr->transfer(TMEMBER_INT(_subtype)); + _talkSprites.persist(persistMgr); + _talkSpritesEx.persist(persistMgr); + + persistMgr->transfer(TMEMBER(_walkToX)); + persistMgr->transfer(TMEMBER(_walkToY)); + persistMgr->transfer(TMEMBER_INT(_walkToDir)); + + persistMgr->transfer(TMEMBER(_theora)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdEntity::setItem(const char *itemName) { + BaseUtils::setString(&_item, itemName); +} + +////////////////////////////////////////////////////////////////////////// +bool AdEntity::setSprite(const char *filename) { + if (_currentSprite == _sprite) { + _currentSprite = NULL; + } + + delete _sprite; + _sprite = NULL; + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + delete _sprite; + _sprite = NULL; + return STATUS_FAILED; + } else { + _sprite = spr; + _currentSprite = _sprite; + return STATUS_OK; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_entity.h b/engines/wintermute/ad/ad_entity.h index 2178563534d8..39dc133eefdf 100644 --- a/engines/wintermute/ad/ad_entity.h +++ b/engines/wintermute/ad/ad_entity.h @@ -1,68 +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_ADENTITY_H -#define WINTERMUTE_ADENTITY_H - -#include "engines/wintermute/ad/ad_talk_holder.h" - -namespace Wintermute { -class VideoTheoraPlayer; -class AdEntity : public AdTalkHolder { -public: - VideoTheoraPlayer *_theora; - bool setSprite(const char *filename); - int _walkToX; - int _walkToY; - TDirection _walkToDir; - void setItem(const char *itemName); - char *_item; - DECLARE_PERSISTENT(AdEntity, AdTalkHolder) - void updatePosition(); - virtual int getHeight(); - BaseRegion *_region; - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - virtual bool update(); - virtual bool display(); - AdEntity(BaseGame *inGame); - virtual ~AdEntity(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - TEntityType _subtype; - - // 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 +/* 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_ADENTITY_H +#define WINTERMUTE_ADENTITY_H + +#include "engines/wintermute/ad/ad_talk_holder.h" + +namespace Wintermute { +class VideoTheoraPlayer; +class AdEntity : public AdTalkHolder { +public: + VideoTheoraPlayer *_theora; + bool setSprite(const char *filename); + int _walkToX; + int _walkToY; + TDirection _walkToDir; + void setItem(const char *itemName); + char *_item; + DECLARE_PERSISTENT(AdEntity, AdTalkHolder) + void updatePosition(); + virtual int getHeight(); + BaseRegion *_region; + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + virtual bool update(); + virtual bool display(); + AdEntity(BaseGame *inGame); + virtual ~AdEntity(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + TEntityType _subtype; + + // 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/ad/ad_game.cpp b/engines/wintermute/ad/ad_game.cpp index f5d865d9f869..fe8a5991e274 100644 --- a/engines/wintermute/ad/ad_game.cpp +++ b/engines/wintermute/ad/ad_game.cpp @@ -1,2280 +1,2280 @@ -/* 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_actor.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_entity.h" -#include "engines/wintermute/ad/ad_inventory.h" -#include "engines/wintermute/ad/ad_inventory_box.h" -#include "engines/wintermute/ad/ad_item.h" -#include "engines/wintermute/ad/ad_response.h" -#include "engines/wintermute/ad/ad_response_box.h" -#include "engines/wintermute/ad/ad_response_context.h" -#include "engines/wintermute/ad/ad_scene.h" -#include "engines/wintermute/ad/ad_scene_state.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_object.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/base_surface_storage.h" -#include "engines/wintermute/base/base_transition_manager.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_viewport.h" -#include "engines/wintermute/base/particles/part_emitter.h" -#include "engines/wintermute/base/saveload.h" -#include "engines/wintermute/base/scriptables/script_engine.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/ui/ui_entity.h" -#include "engines/wintermute/ui/ui_window.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/video/video_player.h" -#include "engines/wintermute/video/video_theora_player.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdGame, true) - -////////////////////////////////////////////////////////////////////////// -AdGame::AdGame(const Common::String &gameId) : BaseGame(gameId) { - _responseBox = NULL; - _inventoryBox = NULL; - - _scene = new AdScene(_gameRef); - _scene->setName(""); - registerObject(_scene); - - _prevSceneName = NULL; - _prevSceneFilename = NULL; - _scheduledScene = NULL; - _scheduledFadeIn = false; - - - _stateEx = GAME_NORMAL; - - _selectedItem = NULL; - - - _texItemLifeTime = 10000; - _texWalkLifeTime = 10000; - _texStandLifeTime = 10000; - _texTalkLifeTime = 10000; - - _talkSkipButton = TALK_SKIP_LEFT; - - _sceneViewport = NULL; - - _initialScene = true; - _debugStartupScene = NULL; - _startupScene = NULL; - - _invObject = new AdObject(this); - _inventoryOwner = _invObject; - - _tempDisableSaveState = false; - _itemsFile = NULL; - - _smartItemCursor = false; - - addSpeechDir("speech"); -} - - -////////////////////////////////////////////////////////////////////////// -AdGame::~AdGame() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::cleanup() { - for (uint32 i = 0; i < _objects.size(); i++) { - unregisterObject(_objects[i]); - _objects[i] = NULL; - } - _objects.clear(); - - - for (uint32 i = 0; i < _dlgPendingBranches.size(); i++) { - delete[] _dlgPendingBranches[i]; - } - _dlgPendingBranches.clear(); - - for (uint32 i = 0; i < _speechDirs.size(); i++) { - delete[] _speechDirs[i]; - } - _speechDirs.clear(); - - - unregisterObject(_scene); - _scene = NULL; - - // remove items - for (uint32 i = 0; i < _items.size(); i++) { - _gameRef->unregisterObject(_items[i]); - } - _items.clear(); - - - // clear remaining inventories - delete _invObject; - _invObject = NULL; - - for (uint32 i = 0; i < _inventories.size(); i++) { - delete _inventories[i]; - } - _inventories.clear(); - - - if (_responseBox) { - _gameRef->unregisterObject(_responseBox); - _responseBox = NULL; - } - - if (_inventoryBox) { - _gameRef->unregisterObject(_inventoryBox); - _inventoryBox = NULL; - } - - delete[] _prevSceneName; - delete[] _prevSceneFilename; - delete[] _scheduledScene; - delete[] _debugStartupScene; - delete[] _itemsFile; - _prevSceneName = NULL; - _prevSceneFilename = NULL; - _scheduledScene = NULL; - _debugStartupScene = NULL; - _startupScene = NULL; - _itemsFile = NULL; - - delete _sceneViewport; - _sceneViewport = NULL; - - for (uint32 i = 0; i < _sceneStates.size(); i++) { - delete _sceneStates[i]; - } - _sceneStates.clear(); - - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - delete _responsesBranch[i]; - } - _responsesBranch.clear(); - - for (uint32 i = 0; i < _responsesGame.size(); i++) { - delete _responsesGame[i]; - } - _responsesGame.clear(); - - return BaseGame::cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::initLoop() { - if (_scheduledScene && _transMgr->isReady()) { - changeScene(_scheduledScene, _scheduledFadeIn); - delete[] _scheduledScene; - _scheduledScene = NULL; - - _gameRef->_activeObject = NULL; - } - - - bool res; - res = BaseGame::initLoop(); - if (DID_FAIL(res)) { - return res; - } - - if (_scene) { - res = _scene->initLoop(); - } - - _sentences.clear(); - - return res; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::addObject(AdObject *object) { - _objects.add(object); - return registerObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::removeObject(AdObject *object) { - // in case the user called Scene.CreateXXX() and Game.DeleteXXX() - if (_scene) { - bool res = _scene->removeObject(object); - if (DID_SUCCEED(res)) { - return res; - } - } - - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i] == object) { - _objects.remove_at(i); - break; - } - } - return unregisterObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::changeScene(const char *filename, bool fadeIn) { - if (_scene == NULL) { - _scene = new AdScene(_gameRef); - registerObject(_scene); - } else { - _scene->applyEvent("SceneShutdown", true); - - setPrevSceneName(_scene->getName()); - setPrevSceneFilename(_scene->getFilename()); - - if (!_tempDisableSaveState) { - _scene->saveState(); - } - _tempDisableSaveState = false; - } - - if (_scene) { - // reset objects - for (uint32 i = 0; i < _objects.size(); i++) { - _objects[i]->reset(); - } - - // reset scene properties - _scene->_sFXVolume = 100; - if (_scene->_scProp) { - _scene->_scProp->cleanup(); - } - - bool ret; - if (_initialScene && _debugDebugMode && _debugStartupScene) { - _initialScene = false; - ret = _scene->loadFile(_debugStartupScene); - } else { - ret = _scene->loadFile(filename); - } - - if (DID_SUCCEED(ret)) { - // invalidate references to the original scene - for (uint32 i = 0; i < _objects.size(); i++) { - _objects[i]->invalidateCurrRegions(); - _objects[i]->_stickRegion = NULL; - } - - _scene->loadState(); - } - if (fadeIn) { - _gameRef->_transMgr->start(TRANSITION_FADE_IN); - } - return ret; - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdGame::addSentence(AdSentence *sentence) { - _sentences.add(sentence); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::displaySentences(bool frozen) { - for (uint32 i = 0; i < _sentences.size(); i++) { - if (frozen && _sentences[i]->_freezable) { - continue; - } else { - _sentences[i]->display(); - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdGame::finishSentences() { - for (uint32 i = 0; i < _sentences.size(); i++) { - if (_sentences[i]->canSkip()) { - _sentences[i]->_duration = 0; - if (_sentences[i]->_sound) { - _sentences[i]->_sound->stop(); - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // ChangeScene - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "ChangeScene") == 0) { - stack->correctParams(3); - const char *filename = stack->pop()->getString(); - ScValue *valFadeOut = stack->pop(); - ScValue *valFadeIn = stack->pop(); - - bool transOut = valFadeOut->isNULL() ? true : valFadeOut->getBool(); - bool transIn = valFadeIn->isNULL() ? true : valFadeIn->getBool(); - - scheduleChangeScene(filename, transIn); - if (transOut) { - _transMgr->start(TRANSITION_FADE_OUT, true); - } - stack->pushNULL(); - - - //bool ret = ChangeScene(stack->pop()->getString()); - //if (DID_FAIL(ret)) stack->pushBool(false); - //else stack->pushBool(true); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadActor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadActor") == 0) { - stack->correctParams(1); - AdActor *act = new AdActor(_gameRef); - if (act && DID_SUCCEED(act->loadFile(stack->pop()->getString()))) { - addObject(act); - stack->pushNative(act, true); - } else { - delete act; - act = NULL; - stack->pushNULL(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadEntity") == 0) { - stack->correctParams(1); - AdEntity *ent = new AdEntity(_gameRef); - if (ent && DID_SUCCEED(ent->loadFile(stack->pop()->getString()))) { - addObject(ent); - stack->pushNative(ent, true); - } else { - delete ent; - ent = NULL; - stack->pushNULL(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // UnloadObject / UnloadActor / UnloadEntity / DeleteEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "UnloadObject") == 0 || strcmp(name, "UnloadActor") == 0 || strcmp(name, "UnloadEntity") == 0 || strcmp(name, "DeleteEntity") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - AdObject *obj = (AdObject *)val->getNative(); - removeObject(obj); - if (val->getType() == VAL_VARIABLE_REF) { - val->setNULL(); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateEntity") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdEntity *ent = new AdEntity(_gameRef); - addObject(ent); - if (!val->isNULL()) { - ent->setName(val->getString()); - } - stack->pushNative(ent, true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateItem") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdItem *item = new AdItem(_gameRef); - addItem(item); - if (!val->isNULL()) { - item->setName(val->getString()); - } - stack->pushNative(item, true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteItem") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdItem *item = NULL; - if (val->isNative()) { - item = (AdItem *)val->getNative(); - } else { - item = getItemByName(val->getString()); - } - - if (item) { - deleteItem(item); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // QueryItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "QueryItem") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdItem *item = NULL; - if (val->isInt()) { - int index = val->getInt(); - if (index >= 0 && index < (int32)_items.size()) { - item = _items[index]; - } - } else { - item = getItemByName(val->getString()); - } - - if (item) { - stack->pushNative(item, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // AddResponse/AddResponseOnce/AddResponseOnceGame - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddResponse") == 0 || strcmp(name, "AddResponseOnce") == 0 || strcmp(name, "AddResponseOnceGame") == 0) { - stack->correctParams(6); - int id = stack->pop()->getInt(); - const char *text = stack->pop()->getString(); - ScValue *val1 = stack->pop(); - ScValue *val2 = stack->pop(); - ScValue *val3 = stack->pop(); - ScValue *val4 = stack->pop(); - - if (_responseBox) { - AdResponse *res = new AdResponse(_gameRef); - if (res) { - res->_iD = id; - res->setText(text); - _stringTable->expand(&res->_text); - if (!val1->isNULL()) { - res->setIcon(val1->getString()); - } - if (!val2->isNULL()) { - res->setIconHover(val2->getString()); - } - if (!val3->isNULL()) { - res->setIconPressed(val3->getString()); - } - if (!val4->isNULL()) { - res->setFont(val4->getString()); - } - - if (strcmp(name, "AddResponseOnce") == 0) { - res->_responseType = RESPONSE_ONCE; - } else if (strcmp(name, "AddResponseOnceGame") == 0) { - res->_responseType = RESPONSE_ONCE_GAME; - } - - _responseBox->_responses.add(res); - } - } else { - script->runtimeError("Game.AddResponse: response box is not defined"); - } - stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ResetResponse - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ResetResponse") == 0) { - stack->correctParams(1); - int id = stack->pop()->getInt(-1); - resetResponse(id); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ClearResponses - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ClearResponses") == 0) { - stack->correctParams(0); - _responseBox->clearResponses(); - _responseBox->clearButtons(); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetResponse - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetResponse") == 0) { - stack->correctParams(1); - bool autoSelectLast = stack->pop()->getBool(); - - if (_responseBox) { - _responseBox->weedResponses(); - - if (_responseBox->_responses.size() == 0) { - stack->pushNULL(); - return STATUS_OK; - } - - - if (_responseBox->_responses.size() == 1 && autoSelectLast) { - stack->pushInt(_responseBox->_responses[0]->_iD); - _responseBox->handleResponse(_responseBox->_responses[0]); - _responseBox->clearResponses(); - return STATUS_OK; - } - - _responseBox->createButtons(); - _responseBox->_waitingScript = script; - script->waitForExclusive(_responseBox); - _state = GAME_SEMI_FROZEN; - _stateEx = GAME_WAITING_RESPONSE; - } else { - script->runtimeError("Game.GetResponse: response box is not defined"); - stack->pushNULL(); - } - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // GetNumResponses - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetNumResponses") == 0) { - stack->correctParams(0); - if (_responseBox) { - _responseBox->weedResponses(); - stack->pushInt(_responseBox->_responses.size()); - } else { - script->runtimeError("Game.GetNumResponses: response box is not defined"); - stack->pushNULL(); - } - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // StartDlgBranch - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StartDlgBranch") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - Common::String branchName; - if (val->isNULL()) { - branchName.format("line%d", script->_currentLine); - } else { - branchName = val->getString(); - } - - startDlgBranch(branchName.c_str(), script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); - stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // EndDlgBranch - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "EndDlgBranch") == 0) { - stack->correctParams(1); - - const char *branchName = NULL; - ScValue *val = stack->pop(); - if (!val->isNULL()) { - branchName = val->getString(); - } - endDlgBranch(branchName, script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); - - stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetCurrentDlgBranch - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetCurrentDlgBranch") == 0) { - stack->correctParams(0); - - if (_dlgPendingBranches.size() > 0) { - stack->pushString(_dlgPendingBranches[_dlgPendingBranches.size() - 1]); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TakeItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TakeItem") == 0) { - return _invObject->scCallMethod(script, stack, thisStack, name); - } - - ////////////////////////////////////////////////////////////////////////// - // DropItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DropItem") == 0) { - return _invObject->scCallMethod(script, stack, thisStack, name); - } - - ////////////////////////////////////////////////////////////////////////// - // GetItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetItem") == 0) { - return _invObject->scCallMethod(script, stack, thisStack, name); - } - - ////////////////////////////////////////////////////////////////////////// - // HasItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "HasItem") == 0) { - return _invObject->scCallMethod(script, stack, thisStack, name); - } - - ////////////////////////////////////////////////////////////////////////// - // IsItemTaken - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsItemTaken") == 0) { - stack->correctParams(1); - - ScValue *val = stack->pop(); - if (!val->isNULL()) { - for (uint32 i = 0; i < _inventories.size(); i++) { - AdInventory *inv = _inventories[i]; - - for (uint32 j = 0; j < inv->_takenItems.size(); j++) { - if (val->getNative() == inv->_takenItems[j]) { - stack->pushBool(true); - return STATUS_OK; - } else if (scumm_stricmp(val->getString(), inv->_takenItems[j]->getName()) == 0) { - stack->pushBool(true); - return STATUS_OK; - } - } - } - } else { - script->runtimeError("Game.IsItemTaken: item name expected"); - } - - stack->pushBool(false); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetInventoryWindow - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetInventoryWindow") == 0) { - stack->correctParams(0); - if (_inventoryBox && _inventoryBox->_window) { - stack->pushNative(_inventoryBox->_window, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetResponsesWindow - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetResponsesWindow") == 0 || strcmp(name, "GetResponseWindow") == 0) { - stack->correctParams(0); - if (_responseBox && _responseBox->_window) { - stack->pushNative(_responseBox->_window, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadResponseBox - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadResponseBox") == 0) { - stack->correctParams(1); - const char *filename = stack->pop()->getString(); - - _gameRef->unregisterObject(_responseBox); - _responseBox = new AdResponseBox(_gameRef); - if (_responseBox && !DID_FAIL(_responseBox->loadFile(filename))) { - registerObject(_responseBox); - stack->pushBool(true); - } else { - delete _responseBox; - _responseBox = NULL; - stack->pushBool(false); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadInventoryBox - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadInventoryBox") == 0) { - stack->correctParams(1); - const char *filename = stack->pop()->getString(); - - _gameRef->unregisterObject(_inventoryBox); - _inventoryBox = new AdInventoryBox(_gameRef); - if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile(filename))) { - registerObject(_inventoryBox); - stack->pushBool(true); - } else { - delete _inventoryBox; - _inventoryBox = NULL; - stack->pushBool(false); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadItems - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadItems") == 0) { - stack->correctParams(2); - const char *filename = stack->pop()->getString(); - bool merge = stack->pop()->getBool(false); - - bool ret = loadItemsFile(filename, merge); - stack->pushBool(DID_SUCCEED(ret)); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddSpeechDir - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddSpeechDir") == 0) { - stack->correctParams(1); - const char *dir = stack->pop()->getString(); - stack->pushBool(DID_SUCCEED(addSpeechDir(dir))); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // RemoveSpeechDir - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "RemoveSpeechDir") == 0) { - stack->correctParams(1); - const char *dir = stack->pop()->getString(); - stack->pushBool(DID_SUCCEED(removeSpeechDir(dir))); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetSceneViewport - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetSceneViewport") == 0) { - stack->correctParams(4); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - int width = stack->pop()->getInt(); - int height = stack->pop()->getInt(); - - if (width <= 0) { - width = _renderer->_width; - } - if (height <= 0) { - height = _renderer->_height; - } - - if (!_sceneViewport) { - _sceneViewport = new BaseViewport(_gameRef); - } - if (_sceneViewport) { - _sceneViewport->setRect(x, y, x + width, y + height); - } - - stack->pushBool(true); - - return STATUS_OK; - } - - - else { - return BaseGame::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdGame::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("game"); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Scene - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scene") == 0) { - if (_scene) { - _scValue->setNative(_scene, true); - } else { - _scValue->setNULL(); - } - - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // SelectedItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SelectedItem") == 0) { - //if (_selectedItem) _scValue->setString(_selectedItem->_name); - if (_selectedItem) { - _scValue->setNative(_selectedItem, true); - } else { - _scValue->setNULL(); - } - - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // NumItems - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumItems") == 0) { - return _invObject->scGetProperty(name); - } - - ////////////////////////////////////////////////////////////////////////// - // SmartItemCursor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SmartItemCursor") == 0) { - _scValue->setBool(_smartItemCursor); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryVisible - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryVisible") == 0) { - _scValue->setBool(_inventoryBox && _inventoryBox->_visible); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryScrollOffset - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryScrollOffset") == 0) { - if (_inventoryBox) { - _scValue->setInt(_inventoryBox->_scrollOffset); - } else { - _scValue->setInt(0); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ResponsesVisible (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ResponsesVisible") == 0) { - _scValue->setBool(_stateEx == GAME_WAITING_RESPONSE); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // PrevScene / PreviousScene (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PrevScene") == 0 || strcmp(name, "PreviousScene") == 0) { - if (!_prevSceneName) { - _scValue->setString(""); - } else { - _scValue->setString(_prevSceneName); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // PrevSceneFilename / PreviousSceneFilename (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PrevSceneFilename") == 0 || strcmp(name, "PreviousSceneFilename") == 0) { - if (!_prevSceneFilename) { - _scValue->setString(""); - } else { - _scValue->setString(_prevSceneFilename); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // LastResponse (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LastResponse") == 0) { - if (!_responseBox || !_responseBox->_lastResponseText) { - _scValue->setString(""); - } else { - _scValue->setString(_responseBox->_lastResponseText); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // LastResponseOrig (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LastResponseOrig") == 0) { - if (!_responseBox || !_responseBox->_lastResponseTextOrig) { - _scValue->setString(""); - } else { - _scValue->setString(_responseBox->_lastResponseTextOrig); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryObject") == 0) { - if (_inventoryOwner == _invObject) { - _scValue->setNative(this, true); - } else { - _scValue->setNative(_inventoryOwner, true); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TotalNumItems - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TotalNumItems") == 0) { - _scValue->setInt(_items.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TalkSkipButton - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TalkSkipButton") == 0) { - _scValue->setInt(_talkSkipButton); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ChangingScene - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ChangingScene") == 0) { - _scValue->setBool(_scheduledScene != NULL); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // StartupScene - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StartupScene") == 0) { - if (!_startupScene) { - _scValue->setNULL(); - } else { - _scValue->setString(_startupScene); - } - return _scValue; - } - - else { - return BaseGame::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::scSetProperty(const char *name, ScValue *value) { - - ////////////////////////////////////////////////////////////////////////// - // SelectedItem - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SelectedItem") == 0) { - if (value->isNULL()) { - _selectedItem = NULL; - } else { - if (value->isNative()) { - _selectedItem = NULL; - for (uint32 i = 0; i < _items.size(); i++) { - if (_items[i] == value->getNative()) { - _selectedItem = (AdItem *)value->getNative(); - break; - } - } - } else { - // try to get by name - _selectedItem = getItemByName(value->getString()); - } - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SmartItemCursor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SmartItemCursor") == 0) { - _smartItemCursor = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryVisible - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryVisible") == 0) { - if (_inventoryBox) { - _inventoryBox->_visible = value->getBool(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryObject") == 0) { - if (_inventoryOwner && _inventoryBox) { - _inventoryOwner->getInventory()->_scrollOffset = _inventoryBox->_scrollOffset; - } - - if (value->isNULL()) { - _inventoryOwner = _invObject; - } else { - BaseObject *obj = (BaseObject *)value->getNative(); - if (obj == this) { - _inventoryOwner = _invObject; - } else if (_gameRef->validObject(obj)) { - _inventoryOwner = (AdObject *)obj; - } - } - - if (_inventoryOwner && _inventoryBox) { - _inventoryBox->_scrollOffset = _inventoryOwner->getInventory()->_scrollOffset; - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InventoryScrollOffset - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InventoryScrollOffset") == 0) { - if (_inventoryBox) { - _inventoryBox->_scrollOffset = value->getInt(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TalkSkipButton - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TalkSkipButton") == 0) { - int val = value->getInt(); - if (val < 0) { - val = 0; - } - if (val > TALK_SKIP_NONE) { - val = TALK_SKIP_NONE; - } - _talkSkipButton = (TTalkSkipButton)val; - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // StartupScene - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StartupScene") == 0) { - if (value == NULL) { - delete[] _startupScene; - _startupScene = NULL; - } else { - BaseUtils::setString(&_startupScene, value->getString()); - } - - return STATUS_OK; - } - - else { - return BaseGame::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name) { - ScValue *thisObj; - - ////////////////////////////////////////////////////////////////////////// - // Actor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Actor") == 0) { - stack->correctParams(0); - thisObj = thisStack->getTop(); - - thisObj->setNative(new AdActor(_gameRef)); - stack->pushNULL(); - } - - ////////////////////////////////////////////////////////////////////////// - // Entity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Entity") == 0) { - stack->correctParams(0); - thisObj = thisStack->getTop(); - - thisObj->setNative(new AdEntity(_gameRef)); - stack->pushNULL(); - } - - - ////////////////////////////////////////////////////////////////////////// - // call parent - else { - return BaseGame::externalCall(script, stack, thisStack, name); - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::showCursor() { - if (_cursorHidden) { - return STATUS_OK; - } - - if (_selectedItem && _gameRef->_state == GAME_RUNNING && _stateEx == GAME_NORMAL && _interactive) { - if (_selectedItem->_cursorCombined) { - BaseSprite *origLastCursor = _lastCursor; - BaseGame::showCursor(); - _lastCursor = origLastCursor; - } - if (_activeObject && _selectedItem->_cursorHover && _activeObject->getExtendedFlag("usable")) { - if (!_smartItemCursor || _activeObject->canHandleEvent(_selectedItem->getName())) { - return drawCursor(_selectedItem->_cursorHover); - } else { - return drawCursor(_selectedItem->_cursorNormal); - } - } else { - return drawCursor(_selectedItem->_cursorNormal); - } - } else { - return BaseGame::showCursor(); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdGame::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(AD_GAME) -TOKEN_DEF(RESPONSE_BOX) -TOKEN_DEF(INVENTORY_BOX) -TOKEN_DEF(ITEMS) -TOKEN_DEF(ITEM) -TOKEN_DEF(TALK_SKIP_BUTTON) -TOKEN_DEF(SCENE_VIEWPORT) -TOKEN_DEF(ENTITY_CONTAINER) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(STARTUP_SCENE) -TOKEN_DEF(DEBUG_STARTUP_SCENE) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdGame::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(GAME) - TOKEN_TABLE(AD_GAME) - TOKEN_TABLE(RESPONSE_BOX) - TOKEN_TABLE(INVENTORY_BOX) - TOKEN_TABLE(ITEMS) - TOKEN_TABLE(TALK_SKIP_BUTTON) - TOKEN_TABLE(SCENE_VIEWPORT) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(STARTUP_SCENE) - TOKEN_TABLE(DEBUG_STARTUP_SCENE) - TOKEN_TABLE_END - - byte *params; - byte *params2; - int cmd = 1; - BaseParser parser; - - bool itemFound = false, itemsFound = false; - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_GAME: - if (DID_FAIL(BaseGame::loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_AD_GAME: - while (cmd > 0 && (cmd = parser.getCommand((char **)¶ms, commands, (char **)¶ms2)) > 0) { - switch (cmd) { - case TOKEN_RESPONSE_BOX: - delete _responseBox; - _responseBox = new AdResponseBox(_gameRef); - if (_responseBox && !DID_FAIL(_responseBox->loadFile((char *)params2))) { - registerObject(_responseBox); - } else { - delete _responseBox; - _responseBox = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_INVENTORY_BOX: - delete _inventoryBox; - _inventoryBox = new AdInventoryBox(_gameRef); - if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile((char *)params2))) { - registerObject(_inventoryBox); - } else { - delete _inventoryBox; - _inventoryBox = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_ITEMS: - itemsFound = true; - BaseUtils::setString(&_itemsFile, (char *)params2); - if (DID_FAIL(loadItemsFile(_itemsFile))) { - delete[] _itemsFile; - _itemsFile = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_TALK_SKIP_BUTTON: - if (scumm_stricmp((char *)params2, "right") == 0) { - _talkSkipButton = TALK_SKIP_RIGHT; - } else if (scumm_stricmp((char *)params2, "both") == 0) { - _talkSkipButton = TALK_SKIP_BOTH; - } else { - _talkSkipButton = TALK_SKIP_LEFT; - } - break; - - case TOKEN_SCENE_VIEWPORT: { - Rect32 rc; - parser.scanStr((char *)params2, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom); - if (!_sceneViewport) { - _sceneViewport = new BaseViewport(_gameRef); - } - if (_sceneViewport) { - _sceneViewport->setRect(rc.left, rc.top, rc.right, rc.bottom); - } - } - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params2, false); - break; - - case TOKEN_STARTUP_SCENE: - BaseUtils::setString(&_startupScene, (char *)params2); - break; - - case TOKEN_DEBUG_STARTUP_SCENE: - BaseUtils::setString(&_debugStartupScene, (char *)params2); - break; - } - } - break; - } - } - - 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; - } - - if (itemFound && !itemsFound) { - _gameRef->LOG(0, "**Warning** Please put the items definition to a separate file."); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::persist(BasePersistenceManager *persistMgr) { - if (!persistMgr->getIsSaving()) { - cleanup(); - } - BaseGame::persist(persistMgr); - - _dlgPendingBranches.persist(persistMgr); - - _inventories.persist(persistMgr); - persistMgr->transfer(TMEMBER(_inventoryBox)); - - _objects.persist(persistMgr); - - persistMgr->transfer(TMEMBER(_prevSceneName)); - persistMgr->transfer(TMEMBER(_prevSceneFilename)); - - persistMgr->transfer(TMEMBER(_responseBox)); - _responsesBranch.persist(persistMgr); - _responsesGame.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scene)); - _sceneStates.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scheduledFadeIn)); - persistMgr->transfer(TMEMBER(_scheduledScene)); - persistMgr->transfer(TMEMBER(_selectedItem)); - persistMgr->transfer(TMEMBER_INT(_talkSkipButton)); - - _sentences.persist(persistMgr); - - persistMgr->transfer(TMEMBER(_sceneViewport)); - persistMgr->transfer(TMEMBER_INT(_stateEx)); - persistMgr->transfer(TMEMBER(_initialScene)); - persistMgr->transfer(TMEMBER(_debugStartupScene)); - - persistMgr->transfer(TMEMBER(_invObject)); - persistMgr->transfer(TMEMBER(_inventoryOwner)); - persistMgr->transfer(TMEMBER(_tempDisableSaveState)); - _items.persist(persistMgr); - - persistMgr->transfer(TMEMBER(_itemsFile)); - - _speechDirs.persist(persistMgr); - persistMgr->transfer(TMEMBER(_smartItemCursor)); - - if (!persistMgr->getIsSaving()) { - _initialScene = false; - } - - persistMgr->transfer(TMEMBER(_startupScene)); - - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void AdGame::setPrevSceneName(const char *name) { - delete[] _prevSceneName; - _prevSceneName = NULL; - if (name) { - _prevSceneName = new char[strlen(name) + 1]; - if (_prevSceneName) { - strcpy(_prevSceneName, name); - } - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdGame::setPrevSceneFilename(const char *name) { - delete[] _prevSceneFilename; - _prevSceneFilename = NULL; - if (name) { - _prevSceneFilename = new char[strlen(name) + 1]; - if (_prevSceneFilename) { - strcpy(_prevSceneFilename, name); - } - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::scheduleChangeScene(const char *filename, bool fadeIn) { - delete[] _scheduledScene; - _scheduledScene = NULL; - - if (_scene && !_scene->_initialized) { - return changeScene(filename, fadeIn); - } else { - _scheduledScene = new char [strlen(filename) + 1]; - strcpy(_scheduledScene, filename); - - _scheduledFadeIn = fadeIn; - - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) { - BaseGame::getVersion(verMajor, verMinor, NULL, NULL); - - if (extMajor) { - *extMajor = 0; - } - if (extMinor) { - *extMinor = 0; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::loadItemsFile(const char *filename, bool merge) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdGame::LoadItemsFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - //_filename = new char [strlen(filename)+1]; - //strcpy(_filename, filename); - - if (DID_FAIL(ret = loadItemsBuffer(buffer, merge))) { - _gameRef->LOG(0, "Error parsing ITEMS file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::loadItemsBuffer(byte *buffer, bool merge) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ITEM) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (!merge) { - while (_items.size() > 0) { - deleteItem(_items[0]); - } - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_ITEM: { - AdItem *item = new AdItem(_gameRef); - if (item && !DID_FAIL(item->loadBuffer(params, false))) { - // delete item with the same name, if exists - if (merge) { - AdItem *prevItem = getItemByName(item->getName()); - if (prevItem) { - deleteItem(prevItem); - } - } - addItem(item); - } else { - delete item; - item = NULL; - cmd = PARSERR_GENERIC; - } - } - break; - } - } - - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ITEMS definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading ITEMS definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -AdSceneState *AdGame::getSceneState(const char *filename, bool saving) { - char *filenameCor = new char[strlen(filename) + 1]; - strcpy(filenameCor, filename); - for (uint32 i = 0; i < strlen(filenameCor); i++) { - if (filenameCor[i] == '/') { - filenameCor[i] = '\\'; - } - } - - for (uint32 i = 0; i < _sceneStates.size(); i++) { - if (scumm_stricmp(_sceneStates[i]->_filename, filenameCor) == 0) { - delete[] filenameCor; - return _sceneStates[i]; - } - } - - if (saving) { - AdSceneState *ret = new AdSceneState(_gameRef); - ret->setFilename(filenameCor); - - _sceneStates.add(ret); - - delete[] filenameCor; - return ret; - } else { - delete[] filenameCor; - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::windowLoadHook(UIWindow *win, char **buffer, char **params) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ENTITY_CONTAINER) - TOKEN_TABLE_END - - int cmd = PARSERR_GENERIC; - BaseParser parser; - - cmd = parser.getCommand(buffer, commands, params); - switch (cmd) { - case TOKEN_ENTITY_CONTAINER: { - UIEntity *ent = new UIEntity(_gameRef); - if (!ent || DID_FAIL(ent->loadBuffer((byte *)*params, false))) { - delete ent; - ent = NULL; - cmd = PARSERR_GENERIC; - } else { - ent->_parent = win; - win->_widgets.add(ent); - } - } - break; - } - - if (cmd == PARSERR_TOKENNOTFOUND || cmd == PARSERR_GENERIC) { - return STATUS_FAILED; - } - - return STATUS_OK; - -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name) { - if (strcmp(name, "CreateEntityContainer") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - UIEntity *ent = new UIEntity(_gameRef); - if (!val->isNULL()) { - ent->setName(val->getString()); - } - stack->pushNative(ent, true); - - ent->_parent = win; - win->_widgets.add(ent); - - return STATUS_OK; - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::startDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { - char *name = new char[strlen(branchName) + 1 + strlen(scriptName) + 1 + strlen(eventName) + 1]; - if (name) { - sprintf(name, "%s.%s.%s", branchName, scriptName, eventName); - _dlgPendingBranches.add(name); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::endDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { - char *name = NULL; - bool deleteName = false; - if (branchName == NULL && _dlgPendingBranches.size() > 0) { - name = _dlgPendingBranches[_dlgPendingBranches.size() - 1]; - } else { - if (branchName != NULL) { - name = new char[strlen(branchName) + 1 + strlen(scriptName) + 1 + strlen(eventName) + 1]; - if (name) { - sprintf(name, "%s.%s.%s", branchName, scriptName, eventName); - deleteName = true; - } - } - } - - if (name == NULL) { - return STATUS_OK; - } - - - int startIndex = -1; - for (int i = _dlgPendingBranches.size() - 1; i >= 0; i--) { - if (scumm_stricmp(name, _dlgPendingBranches[i]) == 0) { - startIndex = i; - break; - } - } - if (startIndex >= 0) { - for (uint32 i = startIndex; i < _dlgPendingBranches.size(); i++) { - //ClearBranchResponses(_dlgPendingBranches[i]); - delete[] _dlgPendingBranches[i]; - _dlgPendingBranches[i] = NULL; - } - _dlgPendingBranches.remove_at(startIndex, _dlgPendingBranches.size() - startIndex); - } - - // dialogue is over, forget selected responses - if (_dlgPendingBranches.size() == 0) { - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - delete _responsesBranch[i]; - } - _responsesBranch.clear(); - } - - if (deleteName) { - delete[] name; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::clearBranchResponses(char *name) { - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - if (scumm_stricmp(name, _responsesBranch[i]->_context) == 0) { - delete _responsesBranch[i]; - _responsesBranch.remove_at(i); - i--; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::addBranchResponse(int id) { - if (branchResponseUsed(id)) { - return STATUS_OK; - } - AdResponseContext *r = new AdResponseContext(_gameRef); - r->_id = id; - r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); - _responsesBranch.add(r); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::branchResponseUsed(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - if (_responsesBranch[i]->_id == id) { - if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { - return true; - } - } - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::addGameResponse(int id) { - if (gameResponseUsed(id)) { - return STATUS_OK; - } - AdResponseContext *r = new AdResponseContext(_gameRef); - r->_id = id; - r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); - _responsesGame.add(r); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::gameResponseUsed(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; - for (uint32 i = 0; i < _responsesGame.size(); i++) { - AdResponseContext *respContext = _responsesGame[i]; - if (respContext->_id == id) { - if ((context == NULL && respContext->_context == NULL) || ((context != NULL && respContext->_context != NULL) && scumm_stricmp(context, respContext->_context) == 0)) { - return true; - } - } - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::resetResponse(int id) { - char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; - - for (uint32 i = 0; i < _responsesGame.size(); i++) { - if (_responsesGame[i]->_id == id) { - if ((context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(context, _responsesGame[i]->_context) == 0) { - delete _responsesGame[i]; - _responsesGame.remove_at(i); - break; - } - } - } - - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - if (_responsesBranch[i]->_id == id) { - if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { - delete _responsesBranch[i]; - _responsesBranch.remove_at(i); - break; - } - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::displayContent(bool doUpdate, bool displayAll) { - // init - if (doUpdate) { - initLoop(); - } - - // fill black - _renderer->fill(0, 0, 0); - if (!_editorMode) { - _renderer->setScreenViewport(); - } - - // playing exclusive video? - if (_videoPlayer->isPlaying()) { - if (doUpdate) { - _videoPlayer->update(); - } - _videoPlayer->display(); - } else if (_theoraPlayer) { - if (_theoraPlayer->isPlaying()) { - if (doUpdate) { - _theoraPlayer->update(); - } - _theoraPlayer->display(); - } - if (_theoraPlayer->isFinished()) { - delete _theoraPlayer; - _theoraPlayer = NULL; - } - } else { - - // process scripts - if (doUpdate) { - _scEngine->tick(); - } - - Point32 p; - getMousePos(&p); - - _scene->update(); - _scene->display(); - - - // display in-game windows - displayWindows(true); - if (_inventoryBox) { - _inventoryBox->display(); - } - if (_stateEx == GAME_WAITING_RESPONSE) { - _responseBox->display(); - } - _renderer->displayIndicator(); - - - if (doUpdate || displayAll) { - // display normal windows - displayWindows(false); - - setActiveObject(_gameRef->_renderer->getObjectAt(p.x, p.y)); - - // textual info - displaySentences(_state == GAME_FROZEN); - - showCursor(); - - if (_fader) { - _fader->display(); - } - _transMgr->update(); - } - - } - if (_loadingIcon) { - _loadingIcon->display(_loadingIconX, _loadingIconY); - if (!_loadingIconPersistent) { - delete _loadingIcon; - _loadingIcon = NULL; - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::registerInventory(AdInventory *inv) { - for (uint32 i = 0; i < _inventories.size(); i++) { - if (_inventories[i] == inv) { - return STATUS_OK; - } - } - registerObject(inv); - _inventories.add(inv); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::unregisterInventory(AdInventory *inv) { - for (uint32 i = 0; i < _inventories.size(); i++) { - if (_inventories[i] == inv) { - unregisterObject(_inventories[i]); - _inventories.remove_at(i); - return STATUS_OK; - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::isItemTaken(char *itemName) { - for (uint32 i = 0; i < _inventories.size(); i++) { - AdInventory *inv = _inventories[i]; - - for (uint32 j = 0; j < inv->_takenItems.size(); j++) { - if (scumm_stricmp(itemName, inv->_takenItems[j]->getName()) == 0) { - return true; - } - } - } - return false; -} - -////////////////////////////////////////////////////////////////////////// -AdItem *AdGame::getItemByName(const char *name) { - for (uint32 i = 0; i < _items.size(); i++) { - if (scumm_stricmp(_items[i]->getName(), name) == 0) { - return _items[i]; - } - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::addItem(AdItem *item) { - _items.add(item); - return _gameRef->registerObject(item); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::resetContent() { - // clear pending dialogs - for (uint32 i = 0; i < _dlgPendingBranches.size(); i++) { - delete[] _dlgPendingBranches[i]; - } - _dlgPendingBranches.clear(); - - - // clear inventories - for (uint32 i = 0; i < _inventories.size(); i++) { - _inventories[i]->_takenItems.clear(); - } - - // clear scene states - for (uint32 i = 0; i < _sceneStates.size(); i++) { - delete _sceneStates[i]; - } - _sceneStates.clear(); - - // clear once responses - for (uint32 i = 0; i < _responsesBranch.size(); i++) { - delete _responsesBranch[i]; - } - _responsesBranch.clear(); - - // clear once game responses - for (uint32 i = 0; i < _responsesGame.size(); i++) { - delete _responsesGame[i]; - } - _responsesGame.clear(); - - // reload inventory items - if (_itemsFile) { - loadItemsFile(_itemsFile); - } - - _tempDisableSaveState = true; - - return BaseGame::resetContent(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::deleteItem(AdItem *item) { - if (!item) { - return STATUS_FAILED; - } - - if (_selectedItem == item) { - _selectedItem = NULL; - } - _scene->handleItemAssociations(item->getName(), false); - - // remove from all inventories - for (uint32 i = 0; i < _inventories.size(); i++) { - _inventories[i]->removeItem(item); - } - - // remove object - for (uint32 i = 0; i < _items.size(); i++) { - if (_items[i] == item) { - unregisterObject(_items[i]); - _items.remove_at(i); - break; - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::addSpeechDir(const char *dir) { - if (!dir || dir[0] == '\0') { - return STATUS_FAILED; - } - - char *temp = new char[strlen(dir) + 2]; - strcpy(temp, dir); - if (temp[strlen(temp) - 1] != '\\' && temp[strlen(temp) - 1] != '/') { - strcat(temp, "\\"); - } - - for (uint32 i = 0; i < _speechDirs.size(); i++) { - if (scumm_stricmp(_speechDirs[i], temp) == 0) { - delete[] temp; - return STATUS_OK; - } - } - _speechDirs.add(temp); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::removeSpeechDir(const char *dir) { - if (!dir || dir[0] == '\0') { - return STATUS_FAILED; - } - - char *temp = new char[strlen(dir) + 2]; - strcpy(temp, dir); - if (temp[strlen(temp) - 1] != '\\' && temp[strlen(temp) - 1] != '/') { - strcat(temp, "\\"); - } - - bool found = false; - for (uint32 i = 0; i < _speechDirs.size(); i++) { - if (scumm_stricmp(_speechDirs[i], temp) == 0) { - delete[] _speechDirs[i]; - _speechDirs.remove_at(i); - found = true; - break; - } - } - delete[] temp; - - return found; -} - - -////////////////////////////////////////////////////////////////////////// -char *AdGame::findSpeechFile(char *stringID) { - char *ret = new char[MAX_PATH_LENGTH]; - - for (uint32 i = 0; i < _speechDirs.size(); i++) { - sprintf(ret, "%s%s.ogg", _speechDirs[i], stringID); - if (BaseFileManager::getEngineInstance()->hasFile(ret)) { - return ret; - } - - sprintf(ret, "%s%s.wav", _speechDirs[i], stringID); - if (BaseFileManager::getEngineInstance()->hasFile(ret)) { - return ret; - } - } - delete[] ret; - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::validMouse() { - Point32 pos; - BasePlatform::getCursorPos(&pos); - - return _renderer->pointInViewport(&pos); -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::onMouseLeftDown() { - if (!validMouse()) { - return STATUS_OK; - } - if (_state == GAME_RUNNING && !_interactive) { - if (_talkSkipButton == TALK_SKIP_LEFT || _talkSkipButton == TALK_SKIP_BOTH) { - finishSentences(); - } - return STATUS_OK; - } - - 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"); - } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { - _scene->applyEvent("LeftClick"); - } - } - - if (_activeObject != NULL) { - _gameRef->_capturedObject = _gameRef->_activeObject; - } - _mouseLeftDown = true; - BasePlatform::setCapture(/*_renderer->_window*/); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::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"); - } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { - _scene->applyEvent("LeftRelease"); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::onMouseLeftDblClick() { - if (!validMouse()) { - return STATUS_OK; - } - - 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"); - } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { - _scene->applyEvent("LeftDoubleClick"); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::onMouseRightDown() { - if (!validMouse()) { - return STATUS_OK; - } - if (_state == GAME_RUNNING && !_interactive) { - if (_talkSkipButton == TALK_SKIP_RIGHT || _talkSkipButton == TALK_SKIP_BOTH) { - finishSentences(); - } - return STATUS_OK; - } - - if ((_state == GAME_RUNNING && !_interactive) || _stateEx == GAME_WAITING_RESPONSE) { - return STATUS_OK; - } - - 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"); - } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { - _scene->applyEvent("RightClick"); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::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"); - } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { - _scene->applyEvent("RightRelease"); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdGame::displayDebugInfo() { - char str[100]; - if (_gameRef->_debugDebugMode) { - sprintf(str, "Mouse: %d, %d (scene: %d, %d)", _mousePos.x, _mousePos.y, _mousePos.x + _scene->getOffsetLeft(), _mousePos.y + _scene->getOffsetTop()); - _systemFont->drawText((byte *)str, 0, 90, _renderer->_width, TAL_RIGHT); - - sprintf(str, "Scene: %s (prev: %s)", (_scene && _scene->getName()) ? _scene->getName() : "???", _prevSceneName ? _prevSceneName : "???"); - _systemFont->drawText((byte *)str, 0, 110, _renderer->_width, TAL_RIGHT); - } - return BaseGame::displayDebugInfo(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdGame::onScriptShutdown(ScScript *script) { - if (_responseBox && _responseBox->_waitingScript == script) { - _responseBox->_waitingScript = NULL; - } - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_actor.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_entity.h" +#include "engines/wintermute/ad/ad_inventory.h" +#include "engines/wintermute/ad/ad_inventory_box.h" +#include "engines/wintermute/ad/ad_item.h" +#include "engines/wintermute/ad/ad_response.h" +#include "engines/wintermute/ad/ad_response_box.h" +#include "engines/wintermute/ad/ad_response_context.h" +#include "engines/wintermute/ad/ad_scene.h" +#include "engines/wintermute/ad/ad_scene_state.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/base_surface_storage.h" +#include "engines/wintermute/base/base_transition_manager.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_viewport.h" +#include "engines/wintermute/base/particles/part_emitter.h" +#include "engines/wintermute/base/saveload.h" +#include "engines/wintermute/base/scriptables/script_engine.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/ui/ui_entity.h" +#include "engines/wintermute/ui/ui_window.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/video/video_player.h" +#include "engines/wintermute/video/video_theora_player.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdGame, true) + +////////////////////////////////////////////////////////////////////////// +AdGame::AdGame(const Common::String &gameId) : BaseGame(gameId) { + _responseBox = NULL; + _inventoryBox = NULL; + + _scene = new AdScene(_gameRef); + _scene->setName(""); + registerObject(_scene); + + _prevSceneName = NULL; + _prevSceneFilename = NULL; + _scheduledScene = NULL; + _scheduledFadeIn = false; + + + _stateEx = GAME_NORMAL; + + _selectedItem = NULL; + + + _texItemLifeTime = 10000; + _texWalkLifeTime = 10000; + _texStandLifeTime = 10000; + _texTalkLifeTime = 10000; + + _talkSkipButton = TALK_SKIP_LEFT; + + _sceneViewport = NULL; + + _initialScene = true; + _debugStartupScene = NULL; + _startupScene = NULL; + + _invObject = new AdObject(this); + _inventoryOwner = _invObject; + + _tempDisableSaveState = false; + _itemsFile = NULL; + + _smartItemCursor = false; + + addSpeechDir("speech"); +} + + +////////////////////////////////////////////////////////////////////////// +AdGame::~AdGame() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::cleanup() { + for (uint32 i = 0; i < _objects.size(); i++) { + unregisterObject(_objects[i]); + _objects[i] = NULL; + } + _objects.clear(); + + + for (uint32 i = 0; i < _dlgPendingBranches.size(); i++) { + delete[] _dlgPendingBranches[i]; + } + _dlgPendingBranches.clear(); + + for (uint32 i = 0; i < _speechDirs.size(); i++) { + delete[] _speechDirs[i]; + } + _speechDirs.clear(); + + + unregisterObject(_scene); + _scene = NULL; + + // remove items + for (uint32 i = 0; i < _items.size(); i++) { + _gameRef->unregisterObject(_items[i]); + } + _items.clear(); + + + // clear remaining inventories + delete _invObject; + _invObject = NULL; + + for (uint32 i = 0; i < _inventories.size(); i++) { + delete _inventories[i]; + } + _inventories.clear(); + + + if (_responseBox) { + _gameRef->unregisterObject(_responseBox); + _responseBox = NULL; + } + + if (_inventoryBox) { + _gameRef->unregisterObject(_inventoryBox); + _inventoryBox = NULL; + } + + delete[] _prevSceneName; + delete[] _prevSceneFilename; + delete[] _scheduledScene; + delete[] _debugStartupScene; + delete[] _itemsFile; + _prevSceneName = NULL; + _prevSceneFilename = NULL; + _scheduledScene = NULL; + _debugStartupScene = NULL; + _startupScene = NULL; + _itemsFile = NULL; + + delete _sceneViewport; + _sceneViewport = NULL; + + for (uint32 i = 0; i < _sceneStates.size(); i++) { + delete _sceneStates[i]; + } + _sceneStates.clear(); + + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + delete _responsesBranch[i]; + } + _responsesBranch.clear(); + + for (uint32 i = 0; i < _responsesGame.size(); i++) { + delete _responsesGame[i]; + } + _responsesGame.clear(); + + return BaseGame::cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::initLoop() { + if (_scheduledScene && _transMgr->isReady()) { + changeScene(_scheduledScene, _scheduledFadeIn); + delete[] _scheduledScene; + _scheduledScene = NULL; + + _gameRef->_activeObject = NULL; + } + + + bool res; + res = BaseGame::initLoop(); + if (DID_FAIL(res)) { + return res; + } + + if (_scene) { + res = _scene->initLoop(); + } + + _sentences.clear(); + + return res; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::addObject(AdObject *object) { + _objects.add(object); + return registerObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::removeObject(AdObject *object) { + // in case the user called Scene.CreateXXX() and Game.DeleteXXX() + if (_scene) { + bool res = _scene->removeObject(object); + if (DID_SUCCEED(res)) { + return res; + } + } + + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i] == object) { + _objects.remove_at(i); + break; + } + } + return unregisterObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::changeScene(const char *filename, bool fadeIn) { + if (_scene == NULL) { + _scene = new AdScene(_gameRef); + registerObject(_scene); + } else { + _scene->applyEvent("SceneShutdown", true); + + setPrevSceneName(_scene->getName()); + setPrevSceneFilename(_scene->getFilename()); + + if (!_tempDisableSaveState) { + _scene->saveState(); + } + _tempDisableSaveState = false; + } + + if (_scene) { + // reset objects + for (uint32 i = 0; i < _objects.size(); i++) { + _objects[i]->reset(); + } + + // reset scene properties + _scene->_sFXVolume = 100; + if (_scene->_scProp) { + _scene->_scProp->cleanup(); + } + + bool ret; + if (_initialScene && _debugDebugMode && _debugStartupScene) { + _initialScene = false; + ret = _scene->loadFile(_debugStartupScene); + } else { + ret = _scene->loadFile(filename); + } + + if (DID_SUCCEED(ret)) { + // invalidate references to the original scene + for (uint32 i = 0; i < _objects.size(); i++) { + _objects[i]->invalidateCurrRegions(); + _objects[i]->_stickRegion = NULL; + } + + _scene->loadState(); + } + if (fadeIn) { + _gameRef->_transMgr->start(TRANSITION_FADE_IN); + } + return ret; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdGame::addSentence(AdSentence *sentence) { + _sentences.add(sentence); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::displaySentences(bool frozen) { + for (uint32 i = 0; i < _sentences.size(); i++) { + if (frozen && _sentences[i]->_freezable) { + continue; + } else { + _sentences[i]->display(); + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdGame::finishSentences() { + for (uint32 i = 0; i < _sentences.size(); i++) { + if (_sentences[i]->canSkip()) { + _sentences[i]->_duration = 0; + if (_sentences[i]->_sound) { + _sentences[i]->_sound->stop(); + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdGame::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // ChangeScene + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "ChangeScene") == 0) { + stack->correctParams(3); + const char *filename = stack->pop()->getString(); + ScValue *valFadeOut = stack->pop(); + ScValue *valFadeIn = stack->pop(); + + bool transOut = valFadeOut->isNULL() ? true : valFadeOut->getBool(); + bool transIn = valFadeIn->isNULL() ? true : valFadeIn->getBool(); + + scheduleChangeScene(filename, transIn); + if (transOut) { + _transMgr->start(TRANSITION_FADE_OUT, true); + } + stack->pushNULL(); + + + //bool ret = ChangeScene(stack->pop()->getString()); + //if (DID_FAIL(ret)) stack->pushBool(false); + //else stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadActor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadActor") == 0) { + stack->correctParams(1); + AdActor *act = new AdActor(_gameRef); + if (act && DID_SUCCEED(act->loadFile(stack->pop()->getString()))) { + addObject(act); + stack->pushNative(act, true); + } else { + delete act; + act = NULL; + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadEntity") == 0) { + stack->correctParams(1); + AdEntity *ent = new AdEntity(_gameRef); + if (ent && DID_SUCCEED(ent->loadFile(stack->pop()->getString()))) { + addObject(ent); + stack->pushNative(ent, true); + } else { + delete ent; + ent = NULL; + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // UnloadObject / UnloadActor / UnloadEntity / DeleteEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "UnloadObject") == 0 || strcmp(name, "UnloadActor") == 0 || strcmp(name, "UnloadEntity") == 0 || strcmp(name, "DeleteEntity") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + AdObject *obj = (AdObject *)val->getNative(); + removeObject(obj); + if (val->getType() == VAL_VARIABLE_REF) { + val->setNULL(); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateEntity") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdEntity *ent = new AdEntity(_gameRef); + addObject(ent); + if (!val->isNULL()) { + ent->setName(val->getString()); + } + stack->pushNative(ent, true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateItem") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdItem *item = new AdItem(_gameRef); + addItem(item); + if (!val->isNULL()) { + item->setName(val->getString()); + } + stack->pushNative(item, true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteItem") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdItem *item = NULL; + if (val->isNative()) { + item = (AdItem *)val->getNative(); + } else { + item = getItemByName(val->getString()); + } + + if (item) { + deleteItem(item); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // QueryItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "QueryItem") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdItem *item = NULL; + if (val->isInt()) { + int index = val->getInt(); + if (index >= 0 && index < (int32)_items.size()) { + item = _items[index]; + } + } else { + item = getItemByName(val->getString()); + } + + if (item) { + stack->pushNative(item, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // AddResponse/AddResponseOnce/AddResponseOnceGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddResponse") == 0 || strcmp(name, "AddResponseOnce") == 0 || strcmp(name, "AddResponseOnceGame") == 0) { + stack->correctParams(6); + int id = stack->pop()->getInt(); + const char *text = stack->pop()->getString(); + ScValue *val1 = stack->pop(); + ScValue *val2 = stack->pop(); + ScValue *val3 = stack->pop(); + ScValue *val4 = stack->pop(); + + if (_responseBox) { + AdResponse *res = new AdResponse(_gameRef); + if (res) { + res->_iD = id; + res->setText(text); + _stringTable->expand(&res->_text); + if (!val1->isNULL()) { + res->setIcon(val1->getString()); + } + if (!val2->isNULL()) { + res->setIconHover(val2->getString()); + } + if (!val3->isNULL()) { + res->setIconPressed(val3->getString()); + } + if (!val4->isNULL()) { + res->setFont(val4->getString()); + } + + if (strcmp(name, "AddResponseOnce") == 0) { + res->_responseType = RESPONSE_ONCE; + } else if (strcmp(name, "AddResponseOnceGame") == 0) { + res->_responseType = RESPONSE_ONCE_GAME; + } + + _responseBox->_responses.add(res); + } + } else { + script->runtimeError("Game.AddResponse: response box is not defined"); + } + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ResetResponse + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ResetResponse") == 0) { + stack->correctParams(1); + int id = stack->pop()->getInt(-1); + resetResponse(id); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ClearResponses + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ClearResponses") == 0) { + stack->correctParams(0); + _responseBox->clearResponses(); + _responseBox->clearButtons(); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetResponse + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetResponse") == 0) { + stack->correctParams(1); + bool autoSelectLast = stack->pop()->getBool(); + + if (_responseBox) { + _responseBox->weedResponses(); + + if (_responseBox->_responses.size() == 0) { + stack->pushNULL(); + return STATUS_OK; + } + + + if (_responseBox->_responses.size() == 1 && autoSelectLast) { + stack->pushInt(_responseBox->_responses[0]->_iD); + _responseBox->handleResponse(_responseBox->_responses[0]); + _responseBox->clearResponses(); + return STATUS_OK; + } + + _responseBox->createButtons(); + _responseBox->_waitingScript = script; + script->waitForExclusive(_responseBox); + _state = GAME_SEMI_FROZEN; + _stateEx = GAME_WAITING_RESPONSE; + } else { + script->runtimeError("Game.GetResponse: response box is not defined"); + stack->pushNULL(); + } + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // GetNumResponses + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetNumResponses") == 0) { + stack->correctParams(0); + if (_responseBox) { + _responseBox->weedResponses(); + stack->pushInt(_responseBox->_responses.size()); + } else { + script->runtimeError("Game.GetNumResponses: response box is not defined"); + stack->pushNULL(); + } + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // StartDlgBranch + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StartDlgBranch") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + Common::String branchName; + if (val->isNULL()) { + branchName.format("line%d", script->_currentLine); + } else { + branchName = val->getString(); + } + + startDlgBranch(branchName.c_str(), script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // EndDlgBranch + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "EndDlgBranch") == 0) { + stack->correctParams(1); + + const char *branchName = NULL; + ScValue *val = stack->pop(); + if (!val->isNULL()) { + branchName = val->getString(); + } + endDlgBranch(branchName, script->_filename == NULL ? "" : script->_filename, script->_threadEvent == NULL ? "" : script->_threadEvent); + + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetCurrentDlgBranch + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetCurrentDlgBranch") == 0) { + stack->correctParams(0); + + if (_dlgPendingBranches.size() > 0) { + stack->pushString(_dlgPendingBranches[_dlgPendingBranches.size() - 1]); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TakeItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TakeItem") == 0) { + return _invObject->scCallMethod(script, stack, thisStack, name); + } + + ////////////////////////////////////////////////////////////////////////// + // DropItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DropItem") == 0) { + return _invObject->scCallMethod(script, stack, thisStack, name); + } + + ////////////////////////////////////////////////////////////////////////// + // GetItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetItem") == 0) { + return _invObject->scCallMethod(script, stack, thisStack, name); + } + + ////////////////////////////////////////////////////////////////////////// + // HasItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HasItem") == 0) { + return _invObject->scCallMethod(script, stack, thisStack, name); + } + + ////////////////////////////////////////////////////////////////////////// + // IsItemTaken + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsItemTaken") == 0) { + stack->correctParams(1); + + ScValue *val = stack->pop(); + if (!val->isNULL()) { + for (uint32 i = 0; i < _inventories.size(); i++) { + AdInventory *inv = _inventories[i]; + + for (uint32 j = 0; j < inv->_takenItems.size(); j++) { + if (val->getNative() == inv->_takenItems[j]) { + stack->pushBool(true); + return STATUS_OK; + } else if (scumm_stricmp(val->getString(), inv->_takenItems[j]->getName()) == 0) { + stack->pushBool(true); + return STATUS_OK; + } + } + } + } else { + script->runtimeError("Game.IsItemTaken: item name expected"); + } + + stack->pushBool(false); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetInventoryWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetInventoryWindow") == 0) { + stack->correctParams(0); + if (_inventoryBox && _inventoryBox->_window) { + stack->pushNative(_inventoryBox->_window, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetResponsesWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetResponsesWindow") == 0 || strcmp(name, "GetResponseWindow") == 0) { + stack->correctParams(0); + if (_responseBox && _responseBox->_window) { + stack->pushNative(_responseBox->_window, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadResponseBox + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadResponseBox") == 0) { + stack->correctParams(1); + const char *filename = stack->pop()->getString(); + + _gameRef->unregisterObject(_responseBox); + _responseBox = new AdResponseBox(_gameRef); + if (_responseBox && !DID_FAIL(_responseBox->loadFile(filename))) { + registerObject(_responseBox); + stack->pushBool(true); + } else { + delete _responseBox; + _responseBox = NULL; + stack->pushBool(false); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadInventoryBox + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadInventoryBox") == 0) { + stack->correctParams(1); + const char *filename = stack->pop()->getString(); + + _gameRef->unregisterObject(_inventoryBox); + _inventoryBox = new AdInventoryBox(_gameRef); + if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile(filename))) { + registerObject(_inventoryBox); + stack->pushBool(true); + } else { + delete _inventoryBox; + _inventoryBox = NULL; + stack->pushBool(false); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadItems + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadItems") == 0) { + stack->correctParams(2); + const char *filename = stack->pop()->getString(); + bool merge = stack->pop()->getBool(false); + + bool ret = loadItemsFile(filename, merge); + stack->pushBool(DID_SUCCEED(ret)); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddSpeechDir + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddSpeechDir") == 0) { + stack->correctParams(1); + const char *dir = stack->pop()->getString(); + stack->pushBool(DID_SUCCEED(addSpeechDir(dir))); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveSpeechDir + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveSpeechDir") == 0) { + stack->correctParams(1); + const char *dir = stack->pop()->getString(); + stack->pushBool(DID_SUCCEED(removeSpeechDir(dir))); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetSceneViewport + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetSceneViewport") == 0) { + stack->correctParams(4); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + int width = stack->pop()->getInt(); + int height = stack->pop()->getInt(); + + if (width <= 0) { + width = _renderer->_width; + } + if (height <= 0) { + height = _renderer->_height; + } + + if (!_sceneViewport) { + _sceneViewport = new BaseViewport(_gameRef); + } + if (_sceneViewport) { + _sceneViewport->setRect(x, y, x + width, y + height); + } + + stack->pushBool(true); + + return STATUS_OK; + } + + + else { + return BaseGame::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdGame::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("game"); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Scene + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scene") == 0) { + if (_scene) { + _scValue->setNative(_scene, true); + } else { + _scValue->setNULL(); + } + + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // SelectedItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SelectedItem") == 0) { + //if (_selectedItem) _scValue->setString(_selectedItem->_name); + if (_selectedItem) { + _scValue->setNative(_selectedItem, true); + } else { + _scValue->setNULL(); + } + + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // NumItems + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumItems") == 0) { + return _invObject->scGetProperty(name); + } + + ////////////////////////////////////////////////////////////////////////// + // SmartItemCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SmartItemCursor") == 0) { + _scValue->setBool(_smartItemCursor); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryVisible + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryVisible") == 0) { + _scValue->setBool(_inventoryBox && _inventoryBox->_visible); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryScrollOffset + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryScrollOffset") == 0) { + if (_inventoryBox) { + _scValue->setInt(_inventoryBox->_scrollOffset); + } else { + _scValue->setInt(0); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ResponsesVisible (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ResponsesVisible") == 0) { + _scValue->setBool(_stateEx == GAME_WAITING_RESPONSE); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PrevScene / PreviousScene (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PrevScene") == 0 || strcmp(name, "PreviousScene") == 0) { + if (!_prevSceneName) { + _scValue->setString(""); + } else { + _scValue->setString(_prevSceneName); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PrevSceneFilename / PreviousSceneFilename (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PrevSceneFilename") == 0 || strcmp(name, "PreviousSceneFilename") == 0) { + if (!_prevSceneFilename) { + _scValue->setString(""); + } else { + _scValue->setString(_prevSceneFilename); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // LastResponse (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LastResponse") == 0) { + if (!_responseBox || !_responseBox->_lastResponseText) { + _scValue->setString(""); + } else { + _scValue->setString(_responseBox->_lastResponseText); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // LastResponseOrig (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LastResponseOrig") == 0) { + if (!_responseBox || !_responseBox->_lastResponseTextOrig) { + _scValue->setString(""); + } else { + _scValue->setString(_responseBox->_lastResponseTextOrig); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryObject") == 0) { + if (_inventoryOwner == _invObject) { + _scValue->setNative(this, true); + } else { + _scValue->setNative(_inventoryOwner, true); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TotalNumItems + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TotalNumItems") == 0) { + _scValue->setInt(_items.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TalkSkipButton + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TalkSkipButton") == 0) { + _scValue->setInt(_talkSkipButton); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ChangingScene + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ChangingScene") == 0) { + _scValue->setBool(_scheduledScene != NULL); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // StartupScene + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StartupScene") == 0) { + if (!_startupScene) { + _scValue->setNULL(); + } else { + _scValue->setString(_startupScene); + } + return _scValue; + } + + else { + return BaseGame::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::scSetProperty(const char *name, ScValue *value) { + + ////////////////////////////////////////////////////////////////////////// + // SelectedItem + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SelectedItem") == 0) { + if (value->isNULL()) { + _selectedItem = NULL; + } else { + if (value->isNative()) { + _selectedItem = NULL; + for (uint32 i = 0; i < _items.size(); i++) { + if (_items[i] == value->getNative()) { + _selectedItem = (AdItem *)value->getNative(); + break; + } + } + } else { + // try to get by name + _selectedItem = getItemByName(value->getString()); + } + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SmartItemCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SmartItemCursor") == 0) { + _smartItemCursor = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryVisible + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryVisible") == 0) { + if (_inventoryBox) { + _inventoryBox->_visible = value->getBool(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryObject") == 0) { + if (_inventoryOwner && _inventoryBox) { + _inventoryOwner->getInventory()->_scrollOffset = _inventoryBox->_scrollOffset; + } + + if (value->isNULL()) { + _inventoryOwner = _invObject; + } else { + BaseObject *obj = (BaseObject *)value->getNative(); + if (obj == this) { + _inventoryOwner = _invObject; + } else if (_gameRef->validObject(obj)) { + _inventoryOwner = (AdObject *)obj; + } + } + + if (_inventoryOwner && _inventoryBox) { + _inventoryBox->_scrollOffset = _inventoryOwner->getInventory()->_scrollOffset; + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InventoryScrollOffset + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InventoryScrollOffset") == 0) { + if (_inventoryBox) { + _inventoryBox->_scrollOffset = value->getInt(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TalkSkipButton + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TalkSkipButton") == 0) { + int val = value->getInt(); + if (val < 0) { + val = 0; + } + if (val > TALK_SKIP_NONE) { + val = TALK_SKIP_NONE; + } + _talkSkipButton = (TTalkSkipButton)val; + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StartupScene + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StartupScene") == 0) { + if (value == NULL) { + delete[] _startupScene; + _startupScene = NULL; + } else { + BaseUtils::setString(&_startupScene, value->getString()); + } + + return STATUS_OK; + } + + else { + return BaseGame::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name) { + ScValue *thisObj; + + ////////////////////////////////////////////////////////////////////////// + // Actor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Actor") == 0) { + stack->correctParams(0); + thisObj = thisStack->getTop(); + + thisObj->setNative(new AdActor(_gameRef)); + stack->pushNULL(); + } + + ////////////////////////////////////////////////////////////////////////// + // Entity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Entity") == 0) { + stack->correctParams(0); + thisObj = thisStack->getTop(); + + thisObj->setNative(new AdEntity(_gameRef)); + stack->pushNULL(); + } + + + ////////////////////////////////////////////////////////////////////////// + // call parent + else { + return BaseGame::externalCall(script, stack, thisStack, name); + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::showCursor() { + if (_cursorHidden) { + return STATUS_OK; + } + + if (_selectedItem && _gameRef->_state == GAME_RUNNING && _stateEx == GAME_NORMAL && _interactive) { + if (_selectedItem->_cursorCombined) { + BaseSprite *origLastCursor = _lastCursor; + BaseGame::showCursor(); + _lastCursor = origLastCursor; + } + if (_activeObject && _selectedItem->_cursorHover && _activeObject->getExtendedFlag("usable")) { + if (!_smartItemCursor || _activeObject->canHandleEvent(_selectedItem->getName())) { + return drawCursor(_selectedItem->_cursorHover); + } else { + return drawCursor(_selectedItem->_cursorNormal); + } + } else { + return drawCursor(_selectedItem->_cursorNormal); + } + } else { + return BaseGame::showCursor(); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdGame::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(AD_GAME) +TOKEN_DEF(RESPONSE_BOX) +TOKEN_DEF(INVENTORY_BOX) +TOKEN_DEF(ITEMS) +TOKEN_DEF(ITEM) +TOKEN_DEF(TALK_SKIP_BUTTON) +TOKEN_DEF(SCENE_VIEWPORT) +TOKEN_DEF(ENTITY_CONTAINER) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(STARTUP_SCENE) +TOKEN_DEF(DEBUG_STARTUP_SCENE) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdGame::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(GAME) + TOKEN_TABLE(AD_GAME) + TOKEN_TABLE(RESPONSE_BOX) + TOKEN_TABLE(INVENTORY_BOX) + TOKEN_TABLE(ITEMS) + TOKEN_TABLE(TALK_SKIP_BUTTON) + TOKEN_TABLE(SCENE_VIEWPORT) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(STARTUP_SCENE) + TOKEN_TABLE(DEBUG_STARTUP_SCENE) + TOKEN_TABLE_END + + byte *params; + byte *params2; + int cmd = 1; + BaseParser parser; + + bool itemFound = false, itemsFound = false; + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_GAME: + if (DID_FAIL(BaseGame::loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_AD_GAME: + while (cmd > 0 && (cmd = parser.getCommand((char **)¶ms, commands, (char **)¶ms2)) > 0) { + switch (cmd) { + case TOKEN_RESPONSE_BOX: + delete _responseBox; + _responseBox = new AdResponseBox(_gameRef); + if (_responseBox && !DID_FAIL(_responseBox->loadFile((char *)params2))) { + registerObject(_responseBox); + } else { + delete _responseBox; + _responseBox = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_INVENTORY_BOX: + delete _inventoryBox; + _inventoryBox = new AdInventoryBox(_gameRef); + if (_inventoryBox && !DID_FAIL(_inventoryBox->loadFile((char *)params2))) { + registerObject(_inventoryBox); + } else { + delete _inventoryBox; + _inventoryBox = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_ITEMS: + itemsFound = true; + BaseUtils::setString(&_itemsFile, (char *)params2); + if (DID_FAIL(loadItemsFile(_itemsFile))) { + delete[] _itemsFile; + _itemsFile = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_TALK_SKIP_BUTTON: + if (scumm_stricmp((char *)params2, "right") == 0) { + _talkSkipButton = TALK_SKIP_RIGHT; + } else if (scumm_stricmp((char *)params2, "both") == 0) { + _talkSkipButton = TALK_SKIP_BOTH; + } else { + _talkSkipButton = TALK_SKIP_LEFT; + } + break; + + case TOKEN_SCENE_VIEWPORT: { + Rect32 rc; + parser.scanStr((char *)params2, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom); + if (!_sceneViewport) { + _sceneViewport = new BaseViewport(_gameRef); + } + if (_sceneViewport) { + _sceneViewport->setRect(rc.left, rc.top, rc.right, rc.bottom); + } + } + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params2, false); + break; + + case TOKEN_STARTUP_SCENE: + BaseUtils::setString(&_startupScene, (char *)params2); + break; + + case TOKEN_DEBUG_STARTUP_SCENE: + BaseUtils::setString(&_debugStartupScene, (char *)params2); + break; + } + } + break; + } + } + + 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; + } + + if (itemFound && !itemsFound) { + _gameRef->LOG(0, "**Warning** Please put the items definition to a separate file."); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::persist(BasePersistenceManager *persistMgr) { + if (!persistMgr->getIsSaving()) { + cleanup(); + } + BaseGame::persist(persistMgr); + + _dlgPendingBranches.persist(persistMgr); + + _inventories.persist(persistMgr); + persistMgr->transfer(TMEMBER(_inventoryBox)); + + _objects.persist(persistMgr); + + persistMgr->transfer(TMEMBER(_prevSceneName)); + persistMgr->transfer(TMEMBER(_prevSceneFilename)); + + persistMgr->transfer(TMEMBER(_responseBox)); + _responsesBranch.persist(persistMgr); + _responsesGame.persist(persistMgr); + persistMgr->transfer(TMEMBER(_scene)); + _sceneStates.persist(persistMgr); + persistMgr->transfer(TMEMBER(_scheduledFadeIn)); + persistMgr->transfer(TMEMBER(_scheduledScene)); + persistMgr->transfer(TMEMBER(_selectedItem)); + persistMgr->transfer(TMEMBER_INT(_talkSkipButton)); + + _sentences.persist(persistMgr); + + persistMgr->transfer(TMEMBER(_sceneViewport)); + persistMgr->transfer(TMEMBER_INT(_stateEx)); + persistMgr->transfer(TMEMBER(_initialScene)); + persistMgr->transfer(TMEMBER(_debugStartupScene)); + + persistMgr->transfer(TMEMBER(_invObject)); + persistMgr->transfer(TMEMBER(_inventoryOwner)); + persistMgr->transfer(TMEMBER(_tempDisableSaveState)); + _items.persist(persistMgr); + + persistMgr->transfer(TMEMBER(_itemsFile)); + + _speechDirs.persist(persistMgr); + persistMgr->transfer(TMEMBER(_smartItemCursor)); + + if (!persistMgr->getIsSaving()) { + _initialScene = false; + } + + persistMgr->transfer(TMEMBER(_startupScene)); + + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void AdGame::setPrevSceneName(const char *name) { + delete[] _prevSceneName; + _prevSceneName = NULL; + if (name) { + _prevSceneName = new char[strlen(name) + 1]; + if (_prevSceneName) { + strcpy(_prevSceneName, name); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdGame::setPrevSceneFilename(const char *name) { + delete[] _prevSceneFilename; + _prevSceneFilename = NULL; + if (name) { + _prevSceneFilename = new char[strlen(name) + 1]; + if (_prevSceneFilename) { + strcpy(_prevSceneFilename, name); + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::scheduleChangeScene(const char *filename, bool fadeIn) { + delete[] _scheduledScene; + _scheduledScene = NULL; + + if (_scene && !_scene->_initialized) { + return changeScene(filename, fadeIn); + } else { + _scheduledScene = new char [strlen(filename) + 1]; + strcpy(_scheduledScene, filename); + + _scheduledFadeIn = fadeIn; + + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor) { + BaseGame::getVersion(verMajor, verMinor, NULL, NULL); + + if (extMajor) { + *extMajor = 0; + } + if (extMinor) { + *extMinor = 0; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::loadItemsFile(const char *filename, bool merge) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdGame::LoadItemsFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + //_filename = new char [strlen(filename)+1]; + //strcpy(_filename, filename); + + if (DID_FAIL(ret = loadItemsBuffer(buffer, merge))) { + _gameRef->LOG(0, "Error parsing ITEMS file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::loadItemsBuffer(byte *buffer, bool merge) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ITEM) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (!merge) { + while (_items.size() > 0) { + deleteItem(_items[0]); + } + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_ITEM: { + AdItem *item = new AdItem(_gameRef); + if (item && !DID_FAIL(item->loadBuffer(params, false))) { + // delete item with the same name, if exists + if (merge) { + AdItem *prevItem = getItemByName(item->getName()); + if (prevItem) { + deleteItem(prevItem); + } + } + addItem(item); + } else { + delete item; + item = NULL; + cmd = PARSERR_GENERIC; + } + } + break; + } + } + + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ITEMS definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading ITEMS definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +AdSceneState *AdGame::getSceneState(const char *filename, bool saving) { + char *filenameCor = new char[strlen(filename) + 1]; + strcpy(filenameCor, filename); + for (uint32 i = 0; i < strlen(filenameCor); i++) { + if (filenameCor[i] == '/') { + filenameCor[i] = '\\'; + } + } + + for (uint32 i = 0; i < _sceneStates.size(); i++) { + if (scumm_stricmp(_sceneStates[i]->_filename, filenameCor) == 0) { + delete[] filenameCor; + return _sceneStates[i]; + } + } + + if (saving) { + AdSceneState *ret = new AdSceneState(_gameRef); + ret->setFilename(filenameCor); + + _sceneStates.add(ret); + + delete[] filenameCor; + return ret; + } else { + delete[] filenameCor; + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::windowLoadHook(UIWindow *win, char **buffer, char **params) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ENTITY_CONTAINER) + TOKEN_TABLE_END + + int cmd = PARSERR_GENERIC; + BaseParser parser; + + cmd = parser.getCommand(buffer, commands, params); + switch (cmd) { + case TOKEN_ENTITY_CONTAINER: { + UIEntity *ent = new UIEntity(_gameRef); + if (!ent || DID_FAIL(ent->loadBuffer((byte *)*params, false))) { + delete ent; + ent = NULL; + cmd = PARSERR_GENERIC; + } else { + ent->_parent = win; + win->_widgets.add(ent); + } + } + break; + } + + if (cmd == PARSERR_TOKENNOTFOUND || cmd == PARSERR_GENERIC) { + return STATUS_FAILED; + } + + return STATUS_OK; + +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name) { + if (strcmp(name, "CreateEntityContainer") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + UIEntity *ent = new UIEntity(_gameRef); + if (!val->isNULL()) { + ent->setName(val->getString()); + } + stack->pushNative(ent, true); + + ent->_parent = win; + win->_widgets.add(ent); + + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::startDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { + char *name = new char[strlen(branchName) + 1 + strlen(scriptName) + 1 + strlen(eventName) + 1]; + if (name) { + sprintf(name, "%s.%s.%s", branchName, scriptName, eventName); + _dlgPendingBranches.add(name); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::endDlgBranch(const char *branchName, const char *scriptName, const char *eventName) { + char *name = NULL; + bool deleteName = false; + if (branchName == NULL && _dlgPendingBranches.size() > 0) { + name = _dlgPendingBranches[_dlgPendingBranches.size() - 1]; + } else { + if (branchName != NULL) { + name = new char[strlen(branchName) + 1 + strlen(scriptName) + 1 + strlen(eventName) + 1]; + if (name) { + sprintf(name, "%s.%s.%s", branchName, scriptName, eventName); + deleteName = true; + } + } + } + + if (name == NULL) { + return STATUS_OK; + } + + + int startIndex = -1; + for (int i = _dlgPendingBranches.size() - 1; i >= 0; i--) { + if (scumm_stricmp(name, _dlgPendingBranches[i]) == 0) { + startIndex = i; + break; + } + } + if (startIndex >= 0) { + for (uint32 i = startIndex; i < _dlgPendingBranches.size(); i++) { + //ClearBranchResponses(_dlgPendingBranches[i]); + delete[] _dlgPendingBranches[i]; + _dlgPendingBranches[i] = NULL; + } + _dlgPendingBranches.remove_at(startIndex, _dlgPendingBranches.size() - startIndex); + } + + // dialogue is over, forget selected responses + if (_dlgPendingBranches.size() == 0) { + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + delete _responsesBranch[i]; + } + _responsesBranch.clear(); + } + + if (deleteName) { + delete[] name; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::clearBranchResponses(char *name) { + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + if (scumm_stricmp(name, _responsesBranch[i]->_context) == 0) { + delete _responsesBranch[i]; + _responsesBranch.remove_at(i); + i--; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::addBranchResponse(int id) { + if (branchResponseUsed(id)) { + return STATUS_OK; + } + AdResponseContext *r = new AdResponseContext(_gameRef); + r->_id = id; + r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); + _responsesBranch.add(r); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::branchResponseUsed(int id) { + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + if (_responsesBranch[i]->_id == id) { + if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { + return true; + } + } + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::addGameResponse(int id) { + if (gameResponseUsed(id)) { + return STATUS_OK; + } + AdResponseContext *r = new AdResponseContext(_gameRef); + r->_id = id; + r->setContext(_dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL); + _responsesGame.add(r); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::gameResponseUsed(int id) { + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + for (uint32 i = 0; i < _responsesGame.size(); i++) { + AdResponseContext *respContext = _responsesGame[i]; + if (respContext->_id == id) { + if ((context == NULL && respContext->_context == NULL) || ((context != NULL && respContext->_context != NULL) && scumm_stricmp(context, respContext->_context) == 0)) { + return true; + } + } + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::resetResponse(int id) { + char *context = _dlgPendingBranches.size() > 0 ? _dlgPendingBranches[_dlgPendingBranches.size() - 1] : NULL; + + for (uint32 i = 0; i < _responsesGame.size(); i++) { + if (_responsesGame[i]->_id == id) { + if ((context == NULL && _responsesGame[i]->_context == NULL) || scumm_stricmp(context, _responsesGame[i]->_context) == 0) { + delete _responsesGame[i]; + _responsesGame.remove_at(i); + break; + } + } + } + + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + if (_responsesBranch[i]->_id == id) { + if ((context == NULL && _responsesBranch[i]->_context == NULL) || scumm_stricmp(context, _responsesBranch[i]->_context) == 0) { + delete _responsesBranch[i]; + _responsesBranch.remove_at(i); + break; + } + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::displayContent(bool doUpdate, bool displayAll) { + // init + if (doUpdate) { + initLoop(); + } + + // fill black + _renderer->fill(0, 0, 0); + if (!_editorMode) { + _renderer->setScreenViewport(); + } + + // playing exclusive video? + if (_videoPlayer->isPlaying()) { + if (doUpdate) { + _videoPlayer->update(); + } + _videoPlayer->display(); + } else if (_theoraPlayer) { + if (_theoraPlayer->isPlaying()) { + if (doUpdate) { + _theoraPlayer->update(); + } + _theoraPlayer->display(); + } + if (_theoraPlayer->isFinished()) { + delete _theoraPlayer; + _theoraPlayer = NULL; + } + } else { + + // process scripts + if (doUpdate) { + _scEngine->tick(); + } + + Point32 p; + getMousePos(&p); + + _scene->update(); + _scene->display(); + + + // display in-game windows + displayWindows(true); + if (_inventoryBox) { + _inventoryBox->display(); + } + if (_stateEx == GAME_WAITING_RESPONSE) { + _responseBox->display(); + } + _renderer->displayIndicator(); + + + if (doUpdate || displayAll) { + // display normal windows + displayWindows(false); + + setActiveObject(_gameRef->_renderer->getObjectAt(p.x, p.y)); + + // textual info + displaySentences(_state == GAME_FROZEN); + + showCursor(); + + if (_fader) { + _fader->display(); + } + _transMgr->update(); + } + + } + if (_loadingIcon) { + _loadingIcon->display(_loadingIconX, _loadingIconY); + if (!_loadingIconPersistent) { + delete _loadingIcon; + _loadingIcon = NULL; + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::registerInventory(AdInventory *inv) { + for (uint32 i = 0; i < _inventories.size(); i++) { + if (_inventories[i] == inv) { + return STATUS_OK; + } + } + registerObject(inv); + _inventories.add(inv); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::unregisterInventory(AdInventory *inv) { + for (uint32 i = 0; i < _inventories.size(); i++) { + if (_inventories[i] == inv) { + unregisterObject(_inventories[i]); + _inventories.remove_at(i); + return STATUS_OK; + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::isItemTaken(char *itemName) { + for (uint32 i = 0; i < _inventories.size(); i++) { + AdInventory *inv = _inventories[i]; + + for (uint32 j = 0; j < inv->_takenItems.size(); j++) { + if (scumm_stricmp(itemName, inv->_takenItems[j]->getName()) == 0) { + return true; + } + } + } + return false; +} + +////////////////////////////////////////////////////////////////////////// +AdItem *AdGame::getItemByName(const char *name) { + for (uint32 i = 0; i < _items.size(); i++) { + if (scumm_stricmp(_items[i]->getName(), name) == 0) { + return _items[i]; + } + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::addItem(AdItem *item) { + _items.add(item); + return _gameRef->registerObject(item); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::resetContent() { + // clear pending dialogs + for (uint32 i = 0; i < _dlgPendingBranches.size(); i++) { + delete[] _dlgPendingBranches[i]; + } + _dlgPendingBranches.clear(); + + + // clear inventories + for (uint32 i = 0; i < _inventories.size(); i++) { + _inventories[i]->_takenItems.clear(); + } + + // clear scene states + for (uint32 i = 0; i < _sceneStates.size(); i++) { + delete _sceneStates[i]; + } + _sceneStates.clear(); + + // clear once responses + for (uint32 i = 0; i < _responsesBranch.size(); i++) { + delete _responsesBranch[i]; + } + _responsesBranch.clear(); + + // clear once game responses + for (uint32 i = 0; i < _responsesGame.size(); i++) { + delete _responsesGame[i]; + } + _responsesGame.clear(); + + // reload inventory items + if (_itemsFile) { + loadItemsFile(_itemsFile); + } + + _tempDisableSaveState = true; + + return BaseGame::resetContent(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::deleteItem(AdItem *item) { + if (!item) { + return STATUS_FAILED; + } + + if (_selectedItem == item) { + _selectedItem = NULL; + } + _scene->handleItemAssociations(item->getName(), false); + + // remove from all inventories + for (uint32 i = 0; i < _inventories.size(); i++) { + _inventories[i]->removeItem(item); + } + + // remove object + for (uint32 i = 0; i < _items.size(); i++) { + if (_items[i] == item) { + unregisterObject(_items[i]); + _items.remove_at(i); + break; + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::addSpeechDir(const char *dir) { + if (!dir || dir[0] == '\0') { + return STATUS_FAILED; + } + + char *temp = new char[strlen(dir) + 2]; + strcpy(temp, dir); + if (temp[strlen(temp) - 1] != '\\' && temp[strlen(temp) - 1] != '/') { + strcat(temp, "\\"); + } + + for (uint32 i = 0; i < _speechDirs.size(); i++) { + if (scumm_stricmp(_speechDirs[i], temp) == 0) { + delete[] temp; + return STATUS_OK; + } + } + _speechDirs.add(temp); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::removeSpeechDir(const char *dir) { + if (!dir || dir[0] == '\0') { + return STATUS_FAILED; + } + + char *temp = new char[strlen(dir) + 2]; + strcpy(temp, dir); + if (temp[strlen(temp) - 1] != '\\' && temp[strlen(temp) - 1] != '/') { + strcat(temp, "\\"); + } + + bool found = false; + for (uint32 i = 0; i < _speechDirs.size(); i++) { + if (scumm_stricmp(_speechDirs[i], temp) == 0) { + delete[] _speechDirs[i]; + _speechDirs.remove_at(i); + found = true; + break; + } + } + delete[] temp; + + return found; +} + + +////////////////////////////////////////////////////////////////////////// +char *AdGame::findSpeechFile(char *stringID) { + char *ret = new char[MAX_PATH_LENGTH]; + + for (uint32 i = 0; i < _speechDirs.size(); i++) { + sprintf(ret, "%s%s.ogg", _speechDirs[i], stringID); + if (BaseFileManager::getEngineInstance()->hasFile(ret)) { + return ret; + } + + sprintf(ret, "%s%s.wav", _speechDirs[i], stringID); + if (BaseFileManager::getEngineInstance()->hasFile(ret)) { + return ret; + } + } + delete[] ret; + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::validMouse() { + Point32 pos; + BasePlatform::getCursorPos(&pos); + + return _renderer->pointInViewport(&pos); +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::onMouseLeftDown() { + if (!validMouse()) { + return STATUS_OK; + } + if (_state == GAME_RUNNING && !_interactive) { + if (_talkSkipButton == TALK_SKIP_LEFT || _talkSkipButton == TALK_SKIP_BOTH) { + finishSentences(); + } + return STATUS_OK; + } + + 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"); + } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { + _scene->applyEvent("LeftClick"); + } + } + + if (_activeObject != NULL) { + _gameRef->_capturedObject = _gameRef->_activeObject; + } + _mouseLeftDown = true; + BasePlatform::setCapture(/*_renderer->_window*/); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::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"); + } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { + _scene->applyEvent("LeftRelease"); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::onMouseLeftDblClick() { + if (!validMouse()) { + return STATUS_OK; + } + + 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"); + } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { + _scene->applyEvent("LeftDoubleClick"); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::onMouseRightDown() { + if (!validMouse()) { + return STATUS_OK; + } + if (_state == GAME_RUNNING && !_interactive) { + if (_talkSkipButton == TALK_SKIP_RIGHT || _talkSkipButton == TALK_SKIP_BOTH) { + finishSentences(); + } + return STATUS_OK; + } + + if ((_state == GAME_RUNNING && !_interactive) || _stateEx == GAME_WAITING_RESPONSE) { + return STATUS_OK; + } + + 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"); + } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { + _scene->applyEvent("RightClick"); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::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"); + } else if (_state == GAME_RUNNING && _scene && _scene->pointInViewport(_mousePos.x, _mousePos.y)) { + _scene->applyEvent("RightRelease"); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdGame::displayDebugInfo() { + char str[100]; + if (_gameRef->_debugDebugMode) { + sprintf(str, "Mouse: %d, %d (scene: %d, %d)", _mousePos.x, _mousePos.y, _mousePos.x + _scene->getOffsetLeft(), _mousePos.y + _scene->getOffsetTop()); + _systemFont->drawText((byte *)str, 0, 90, _renderer->_width, TAL_RIGHT); + + sprintf(str, "Scene: %s (prev: %s)", (_scene && _scene->getName()) ? _scene->getName() : "???", _prevSceneName ? _prevSceneName : "???"); + _systemFont->drawText((byte *)str, 0, 110, _renderer->_width, TAL_RIGHT); + } + return BaseGame::displayDebugInfo(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdGame::onScriptShutdown(ScScript *script) { + if (_responseBox && _responseBox->_waitingScript == script) { + _responseBox->_waitingScript = NULL; + } + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_game.h b/engines/wintermute/ad/ad_game.h index 5707ec48fdee..46427331bf36 100644 --- a/engines/wintermute/ad/ad_game.h +++ b/engines/wintermute/ad/ad_game.h @@ -1,163 +1,163 @@ -/* 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_ADGAME_H -#define WINTERMUTE_ADGAME_H - -#include "engines/wintermute/ad/ad_types.h" -#include "engines/wintermute/base/base_game.h" - -namespace Wintermute { -class AdItem; -class AdInventory; -class AdSceneState; -class AdScene; -class AdItem; -class AdObject; -class AdSentence; -class AdInventoryBox; -class AdResponseContext; -class AdResponseBox; -class AdGame : public BaseGame { -public: - virtual bool onScriptShutdown(ScScript *script); - - virtual bool onMouseLeftDown(); - virtual bool onMouseLeftUp(); - virtual bool onMouseLeftDblClick(); - virtual bool onMouseRightDown(); - virtual bool onMouseRightUp(); - - virtual bool displayDebugInfo(); - - bool addSpeechDir(const char *dir); - bool removeSpeechDir(const char *dir); - char *findSpeechFile(char *StringID); - - bool deleteItem(AdItem *Item); - char *_itemsFile; - bool _tempDisableSaveState; - virtual bool resetContent(); - bool addItem(AdItem *item); - AdItem *getItemByName(const char *name); - - AdObject *_inventoryOwner; - bool isItemTaken(char *itemName); - bool registerInventory(AdInventory *inv); - bool unregisterInventory(AdInventory *inv); - virtual bool displayContent(bool update = true, bool displayAll = false); - - bool gameResponseUsed(int ID); - bool addGameResponse(int ID); - bool resetResponse(int ID); - - bool branchResponseUsed(int ID); - bool addBranchResponse(int ID); - bool clearBranchResponses(char *name); - bool startDlgBranch(const char *branchName, const char *scriptName, const char *eventName); - bool endDlgBranch(const char *branchName, const char *scriptName, const char *eventName); - virtual bool windowLoadHook(UIWindow *win, char **buf, char **params); - virtual bool windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name); - - AdSceneState *getSceneState(const char *filename, bool saving); - BaseViewport *_sceneViewport; - - int _texItemLifeTime; - int _texWalkLifeTime; - int _texStandLifeTime; - int _texTalkLifeTime; - - TTalkSkipButton _talkSkipButton; - - virtual bool getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor); - bool scheduleChangeScene(const char *filename, bool fadeIn); - void setPrevSceneName(const char *name); - void setPrevSceneFilename(const char *name); - - AdItem *_selectedItem; - bool cleanup(); - DECLARE_PERSISTENT(AdGame, BaseGame) - - void finishSentences(); - bool showCursor(); - - TGameStateEx _stateEx; - - bool displaySentences(bool frozen); - void addSentence(AdSentence *sentence); - bool changeScene(const char *filename, bool fadeIn); - bool removeObject(AdObject *object); - bool addObject(AdObject *object); - AdScene *_scene; - bool initLoop(); - AdGame(const Common::String &gameId); - virtual ~AdGame(); - - BaseArray _objects; - - virtual bool loadFile(const char *filename); - virtual bool loadBuffer(byte *buffer, bool complete = true); - - bool loadItemsFile(const char *filename, bool merge = false); - bool loadItemsBuffer(byte *buffer, bool merge = false); - - // 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); - bool validMouse(); -private: - virtual bool externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name); - - AdObject *_invObject; - BaseArray _inventories; - char *_scheduledScene; - bool _scheduledFadeIn; - char *_prevSceneName; - char *_prevSceneFilename; - char *_debugStartupScene; - char *_startupScene; - bool _initialScene; - bool _smartItemCursor; - BaseArray _speechDirs; - BaseArray _items; - - BaseArray _sentences; - - BaseArray _sceneStates; - BaseArray _dlgPendingBranches; - - BaseArray _responsesBranch; - BaseArray _responsesGame; - - AdResponseBox *_responseBox; - AdInventoryBox *_inventoryBox; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADGAME_H +#define WINTERMUTE_ADGAME_H + +#include "engines/wintermute/ad/ad_types.h" +#include "engines/wintermute/base/base_game.h" + +namespace Wintermute { +class AdItem; +class AdInventory; +class AdSceneState; +class AdScene; +class AdItem; +class AdObject; +class AdSentence; +class AdInventoryBox; +class AdResponseContext; +class AdResponseBox; +class AdGame : public BaseGame { +public: + virtual bool onScriptShutdown(ScScript *script); + + virtual bool onMouseLeftDown(); + virtual bool onMouseLeftUp(); + virtual bool onMouseLeftDblClick(); + virtual bool onMouseRightDown(); + virtual bool onMouseRightUp(); + + virtual bool displayDebugInfo(); + + bool addSpeechDir(const char *dir); + bool removeSpeechDir(const char *dir); + char *findSpeechFile(char *StringID); + + bool deleteItem(AdItem *Item); + char *_itemsFile; + bool _tempDisableSaveState; + virtual bool resetContent(); + bool addItem(AdItem *item); + AdItem *getItemByName(const char *name); + + AdObject *_inventoryOwner; + bool isItemTaken(char *itemName); + bool registerInventory(AdInventory *inv); + bool unregisterInventory(AdInventory *inv); + virtual bool displayContent(bool update = true, bool displayAll = false); + + bool gameResponseUsed(int ID); + bool addGameResponse(int ID); + bool resetResponse(int ID); + + bool branchResponseUsed(int ID); + bool addBranchResponse(int ID); + bool clearBranchResponses(char *name); + bool startDlgBranch(const char *branchName, const char *scriptName, const char *eventName); + bool endDlgBranch(const char *branchName, const char *scriptName, const char *eventName); + virtual bool windowLoadHook(UIWindow *win, char **buf, char **params); + virtual bool windowScriptMethodHook(UIWindow *win, ScScript *script, ScStack *stack, const char *name); + + AdSceneState *getSceneState(const char *filename, bool saving); + BaseViewport *_sceneViewport; + + int _texItemLifeTime; + int _texWalkLifeTime; + int _texStandLifeTime; + int _texTalkLifeTime; + + TTalkSkipButton _talkSkipButton; + + virtual bool getVersion(byte *verMajor, byte *verMinor, byte *extMajor, byte *extMinor); + bool scheduleChangeScene(const char *filename, bool fadeIn); + void setPrevSceneName(const char *name); + void setPrevSceneFilename(const char *name); + + AdItem *_selectedItem; + bool cleanup(); + DECLARE_PERSISTENT(AdGame, BaseGame) + + void finishSentences(); + bool showCursor(); + + TGameStateEx _stateEx; + + bool displaySentences(bool frozen); + void addSentence(AdSentence *sentence); + bool changeScene(const char *filename, bool fadeIn); + bool removeObject(AdObject *object); + bool addObject(AdObject *object); + AdScene *_scene; + bool initLoop(); + AdGame(const Common::String &gameId); + virtual ~AdGame(); + + BaseArray _objects; + + virtual bool loadFile(const char *filename); + virtual bool loadBuffer(byte *buffer, bool complete = true); + + bool loadItemsFile(const char *filename, bool merge = false); + bool loadItemsBuffer(byte *buffer, bool merge = false); + + // 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); + bool validMouse(); +private: + virtual bool externalCall(ScScript *script, ScStack *stack, ScStack *thisStack, char *name); + + AdObject *_invObject; + BaseArray _inventories; + char *_scheduledScene; + bool _scheduledFadeIn; + char *_prevSceneName; + char *_prevSceneFilename; + char *_debugStartupScene; + char *_startupScene; + bool _initialScene; + bool _smartItemCursor; + BaseArray _speechDirs; + BaseArray _items; + + BaseArray _sentences; + + BaseArray _sceneStates; + BaseArray _dlgPendingBranches; + + BaseArray _responsesBranch; + BaseArray _responsesGame; + + AdResponseBox *_responseBox; + AdInventoryBox *_inventoryBox; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_inventory.cpp b/engines/wintermute/ad/ad_inventory.cpp index 44b2dc05081c..72f8fa0fb4f3 100644 --- a/engines/wintermute/ad/ad_inventory.cpp +++ b/engines/wintermute/ad/ad_inventory.cpp @@ -1,136 +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/ad/ad_inventory.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_item.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdInventory, false) - -////////////////////////////////////////////////////////////////////////// -AdInventory::AdInventory(BaseGame *inGame) : BaseObject(inGame) { - _scrollOffset = 0; -} - - -////////////////////////////////////////////////////////////////////////// -AdInventory::~AdInventory() { - _takenItems.clear(); // ref only -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventory::insertItem(const char *name, const char *insertAfter) { - if (name == NULL) { - return STATUS_FAILED; - } - - AdItem *item = ((AdGame *)_gameRef)->getItemByName(name); - if (item == NULL) { - return STATUS_FAILED; - } - - int insertIndex = -1; - for (uint32 i = 0; i < _takenItems.size(); i++) { - if (scumm_stricmp(_takenItems[i]->getName(), name) == 0) { - _takenItems.remove_at(i); - i--; - continue; - } - if (insertAfter && scumm_stricmp(_takenItems[i]->getName(), insertAfter) == 0) { - insertIndex = i + 1; - } - } - - - if (insertIndex == -1) { - _takenItems.add(item); - } else { - _takenItems.insert_at(insertIndex, item); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventory::removeItem(const char *name) { - if (name == NULL) { - return STATUS_FAILED; - } - - for (uint32 i = 0; i < _takenItems.size(); i++) { - if (scumm_stricmp(_takenItems[i]->getName(), name) == 0) { - if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { - ((AdGame *)_gameRef)->_selectedItem = NULL; - } - _takenItems.remove_at(i); - return STATUS_OK; - } - } - - return STATUS_FAILED; -} - - - -////////////////////////////////////////////////////////////////////////// -bool AdInventory::removeItem(AdItem *item) { - if (item == NULL) { - return STATUS_FAILED; - } - - for (uint32 i = 0; i < _takenItems.size(); i++) { - if (_takenItems[i] == item) { - if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { - ((AdGame *)_gameRef)->_selectedItem = NULL; - } - _takenItems.remove_at(i); - return STATUS_OK; - } - } - - return STATUS_FAILED; -} - -////////////////////////////////////////////////////////////////////////// -bool AdInventory::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - _takenItems.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scrollOffset)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_inventory.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_item.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdInventory, false) + +////////////////////////////////////////////////////////////////////////// +AdInventory::AdInventory(BaseGame *inGame) : BaseObject(inGame) { + _scrollOffset = 0; +} + + +////////////////////////////////////////////////////////////////////////// +AdInventory::~AdInventory() { + _takenItems.clear(); // ref only +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventory::insertItem(const char *name, const char *insertAfter) { + if (name == NULL) { + return STATUS_FAILED; + } + + AdItem *item = ((AdGame *)_gameRef)->getItemByName(name); + if (item == NULL) { + return STATUS_FAILED; + } + + int insertIndex = -1; + for (uint32 i = 0; i < _takenItems.size(); i++) { + if (scumm_stricmp(_takenItems[i]->getName(), name) == 0) { + _takenItems.remove_at(i); + i--; + continue; + } + if (insertAfter && scumm_stricmp(_takenItems[i]->getName(), insertAfter) == 0) { + insertIndex = i + 1; + } + } + + + if (insertIndex == -1) { + _takenItems.add(item); + } else { + _takenItems.insert_at(insertIndex, item); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventory::removeItem(const char *name) { + if (name == NULL) { + return STATUS_FAILED; + } + + for (uint32 i = 0; i < _takenItems.size(); i++) { + if (scumm_stricmp(_takenItems[i]->getName(), name) == 0) { + if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { + ((AdGame *)_gameRef)->_selectedItem = NULL; + } + _takenItems.remove_at(i); + return STATUS_OK; + } + } + + return STATUS_FAILED; +} + + + +////////////////////////////////////////////////////////////////////////// +bool AdInventory::removeItem(AdItem *item) { + if (item == NULL) { + return STATUS_FAILED; + } + + for (uint32 i = 0; i < _takenItems.size(); i++) { + if (_takenItems[i] == item) { + if (((AdGame *)_gameRef)->_selectedItem == _takenItems[i]) { + ((AdGame *)_gameRef)->_selectedItem = NULL; + } + _takenItems.remove_at(i); + return STATUS_OK; + } + } + + return STATUS_FAILED; +} + +////////////////////////////////////////////////////////////////////////// +bool AdInventory::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + _takenItems.persist(persistMgr); + persistMgr->transfer(TMEMBER(_scrollOffset)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_inventory.h b/engines/wintermute/ad/ad_inventory.h index 9a12eb1abe4b..4017d914bcf5 100644 --- a/engines/wintermute/ad/ad_inventory.h +++ b/engines/wintermute/ad/ad_inventory.h @@ -1,52 +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_ADINVENTORY_H -#define WINTERMUTE_ADINVENTORY_H - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { - -class AdItem; - -class AdInventory : public BaseObject { -public: - DECLARE_PERSISTENT(AdInventory, BaseObject) - bool removeItem(const char *name); - bool removeItem(AdItem *Item); - bool insertItem(const char *name, const char *insertAfter = NULL); - AdInventory(BaseGame *inGame); - virtual ~AdInventory(); - BaseArray _takenItems; - int _scrollOffset; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADINVENTORY_H +#define WINTERMUTE_ADINVENTORY_H + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class AdItem; + +class AdInventory : public BaseObject { +public: + DECLARE_PERSISTENT(AdInventory, BaseObject) + bool removeItem(const char *name); + bool removeItem(AdItem *Item); + bool insertItem(const char *name, const char *insertAfter = NULL); + AdInventory(BaseGame *inGame); + virtual ~AdInventory(); + BaseArray _takenItems; + int _scrollOffset; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_inventory_box.cpp b/engines/wintermute/ad/ad_inventory_box.cpp index ad679007df2c..16b8e01ff380 100644 --- a/engines/wintermute/ad/ad_inventory_box.cpp +++ b/engines/wintermute/ad/ad_inventory_box.cpp @@ -1,388 +1,388 @@ -/* 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/ad/ad_inventory_box.h" -#include "engines/wintermute/ad/ad_inventory.h" -#include "engines/wintermute/ad/ad_item.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/base_viewport.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/ui/ui_button.h" -#include "engines/wintermute/ui/ui_window.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" -#include "common/rect.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdInventoryBox, false) - -////////////////////////////////////////////////////////////////////////// -AdInventoryBox::AdInventoryBox(BaseGame *inGame) : BaseObject(inGame) { - _itemsArea.setEmpty(); - _scrollOffset = 0; - _spacing = 0; - _itemWidth = _itemHeight = 50; - _scrollBy = 1; - - _window = NULL; - _closeButton = NULL; - - _hideSelected = false; - - _visible = false; - _exclusive = false; -} - - -////////////////////////////////////////////////////////////////////////// -AdInventoryBox::~AdInventoryBox() { - _gameRef->unregisterObject(_window); - _window = NULL; - - delete _closeButton; - _closeButton = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::listen(BaseScriptHolder *param1, uint32 param2) { - UIObject *obj = (UIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->getName(), "close") == 0) { - _visible = false; - } else if (scumm_stricmp(obj->getName(), "prev") == 0) { - _scrollOffset -= _scrollBy; - _scrollOffset = MAX(_scrollOffset, 0); - } else if (scumm_stricmp(obj->getName(), "next") == 0) { - _scrollOffset += _scrollBy; - } else { - return BaseObject::listen(param1, param2); - } - break; - default: - error("AdInventoryBox::Listen - Unhandled enum"); - break; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::display() { - AdGame *adGame = (AdGame *)_gameRef; - - if (!_visible) { - return STATUS_OK; - } - - int itemsX, itemsY; - itemsX = (int)floor((float)((_itemsArea.right - _itemsArea.left + _spacing) / (_itemWidth + _spacing))); - itemsY = (int)floor((float)((_itemsArea.bottom - _itemsArea.top + _spacing) / (_itemHeight + _spacing))); - - if (_window) { - _window->enableWidget("prev", _scrollOffset > 0); - _window->enableWidget("next", _scrollOffset + itemsX * itemsY < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()); - } - - - if (_closeButton) { - _closeButton->_posX = _closeButton->_posY = 0; - _closeButton->_width = _gameRef->_renderer->_width; - _closeButton->_height = _gameRef->_renderer->_height; - - _closeButton->display(); - } - - - // display window - Rect32 rect = _itemsArea; - if (_window) { - rect.offsetRect(_window->_posX, _window->_posY); - _window->display(); - } - - // display items - if (_window && _window->_alphaColor != 0) { - _gameRef->_renderer->_forceAlphaColor = _window->_alphaColor; - } - int yyy = rect.top; - for (int j = 0; j < itemsY; j++) { - int xxx = rect.left; - for (int i = 0; i < itemsX; i++) { - int itemIndex = _scrollOffset + j * itemsX + i; - if (itemIndex >= 0 && itemIndex < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()) { - AdItem *item = adGame->_inventoryOwner->getInventory()->_takenItems[itemIndex]; - if (item != ((AdGame *)_gameRef)->_selectedItem || !_hideSelected) { - item->update(); - item->display(xxx, yyy); - } - } - - xxx += (_itemWidth + _spacing); - } - yyy += (_itemHeight + _spacing); - } - if (_window && _window->_alphaColor != 0) { - _gameRef->_renderer->_forceAlphaColor = 0; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdInventoryBox::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 INVENTORY_BOX file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(INVENTORY_BOX) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(WINDOW) -TOKEN_DEF(EXCLUSIVE) -TOKEN_DEF(ALWAYS_VISIBLE) -TOKEN_DEF(AREA) -TOKEN_DEF(SPACING) -TOKEN_DEF(ITEM_WIDTH) -TOKEN_DEF(ITEM_HEIGHT) -TOKEN_DEF(SCROLL_BY) -TOKEN_DEF(NAME) -TOKEN_DEF(CAPTION) -TOKEN_DEF(HIDE_SELECTED) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(INVENTORY_BOX) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(WINDOW) - TOKEN_TABLE(EXCLUSIVE) - TOKEN_TABLE(ALWAYS_VISIBLE) - TOKEN_TABLE(AREA) - TOKEN_TABLE(SPACING) - TOKEN_TABLE(ITEM_WIDTH) - TOKEN_TABLE(ITEM_HEIGHT) - TOKEN_TABLE(SCROLL_BY) - TOKEN_TABLE(NAME) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(HIDE_SELECTED) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - bool alwaysVisible = false; - - _exclusive = false; - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_INVENTORY_BOX) { - _gameRef->LOG(0, "'INVENTORY_BOX' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_WINDOW: - delete _window; - _window = new UIWindow(_gameRef); - if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { - delete _window; - _window = NULL; - cmd = PARSERR_GENERIC; - } else { - _gameRef->registerObject(_window); - } - break; - - case TOKEN_AREA: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_itemsArea.left, &_itemsArea.top, &_itemsArea.right, &_itemsArea.bottom); - break; - - case TOKEN_EXCLUSIVE: - parser.scanStr((char *)params, "%b", &_exclusive); - break; - - case TOKEN_HIDE_SELECTED: - parser.scanStr((char *)params, "%b", &_hideSelected); - break; - - case TOKEN_ALWAYS_VISIBLE: - parser.scanStr((char *)params, "%b", &alwaysVisible); - break; - - case TOKEN_SPACING: - parser.scanStr((char *)params, "%d", &_spacing); - break; - - case TOKEN_ITEM_WIDTH: - parser.scanStr((char *)params, "%d", &_itemWidth); - break; - - case TOKEN_ITEM_HEIGHT: - parser.scanStr((char *)params, "%d", &_itemHeight); - break; - - case TOKEN_SCROLL_BY: - parser.scanStr((char *)params, "%d", &_scrollBy); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in INVENTORY_BOX definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading INVENTORY_BOX definition"); - return STATUS_FAILED; - } - - if (_exclusive) { - delete _closeButton; - _closeButton = new UIButton(_gameRef); - if (_closeButton) { - _closeButton->setName("close"); - _closeButton->setListener(this, _closeButton, 0); - _closeButton->_parent = _window; - } - } - - _visible = alwaysVisible; - - if (_window) { - for (uint32 i = 0; i < _window->_widgets.size(); i++) { - if (!_window->_widgets[i]->_listenerObject) { - _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); - } - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "INVENTORY_BOX\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "AREA { %d, %d, %d, %d }\n", _itemsArea.left, _itemsArea.top, _itemsArea.right, _itemsArea.bottom); - - buffer->putTextIndent(indent + 2, "EXCLUSIVE=%s\n", _exclusive ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "HIDE_SELECTED=%s\n", _hideSelected ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "ALWAYS_VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "SPACING=%d\n", _spacing); - buffer->putTextIndent(indent + 2, "ITEM_WIDTH=%d\n", _itemWidth); - buffer->putTextIndent(indent + 2, "ITEM_HEIGHT=%d\n", _itemHeight); - buffer->putTextIndent(indent + 2, "SCROLL_BY=%d\n", _scrollBy); - - buffer->putTextIndent(indent + 2, "\n"); - - // window - if (_window) { - _window->saveAsText(buffer, indent + 2); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdInventoryBox::persist(BasePersistenceManager *persistMgr) { - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_closeButton)); - persistMgr->transfer(TMEMBER(_hideSelected)); - persistMgr->transfer(TMEMBER(_itemHeight)); - persistMgr->transfer(TMEMBER(_itemsArea)); - persistMgr->transfer(TMEMBER(_itemWidth)); - persistMgr->transfer(TMEMBER(_scrollBy)); - persistMgr->transfer(TMEMBER(_scrollOffset)); - persistMgr->transfer(TMEMBER(_spacing)); - persistMgr->transfer(TMEMBER(_visible)); - persistMgr->transfer(TMEMBER(_window)); - persistMgr->transfer(TMEMBER(_exclusive)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ad/ad_inventory_box.h" +#include "engines/wintermute/ad/ad_inventory.h" +#include "engines/wintermute/ad/ad_item.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/base_viewport.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/ui/ui_button.h" +#include "engines/wintermute/ui/ui_window.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" +#include "common/rect.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdInventoryBox, false) + +////////////////////////////////////////////////////////////////////////// +AdInventoryBox::AdInventoryBox(BaseGame *inGame) : BaseObject(inGame) { + _itemsArea.setEmpty(); + _scrollOffset = 0; + _spacing = 0; + _itemWidth = _itemHeight = 50; + _scrollBy = 1; + + _window = NULL; + _closeButton = NULL; + + _hideSelected = false; + + _visible = false; + _exclusive = false; +} + + +////////////////////////////////////////////////////////////////////////// +AdInventoryBox::~AdInventoryBox() { + _gameRef->unregisterObject(_window); + _window = NULL; + + delete _closeButton; + _closeButton = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::listen(BaseScriptHolder *param1, uint32 param2) { + UIObject *obj = (UIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->getName(), "close") == 0) { + _visible = false; + } else if (scumm_stricmp(obj->getName(), "prev") == 0) { + _scrollOffset -= _scrollBy; + _scrollOffset = MAX(_scrollOffset, 0); + } else if (scumm_stricmp(obj->getName(), "next") == 0) { + _scrollOffset += _scrollBy; + } else { + return BaseObject::listen(param1, param2); + } + break; + default: + error("AdInventoryBox::Listen - Unhandled enum"); + break; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::display() { + AdGame *adGame = (AdGame *)_gameRef; + + if (!_visible) { + return STATUS_OK; + } + + int itemsX, itemsY; + itemsX = (int)floor((float)((_itemsArea.right - _itemsArea.left + _spacing) / (_itemWidth + _spacing))); + itemsY = (int)floor((float)((_itemsArea.bottom - _itemsArea.top + _spacing) / (_itemHeight + _spacing))); + + if (_window) { + _window->enableWidget("prev", _scrollOffset > 0); + _window->enableWidget("next", _scrollOffset + itemsX * itemsY < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()); + } + + + if (_closeButton) { + _closeButton->_posX = _closeButton->_posY = 0; + _closeButton->_width = _gameRef->_renderer->_width; + _closeButton->_height = _gameRef->_renderer->_height; + + _closeButton->display(); + } + + + // display window + Rect32 rect = _itemsArea; + if (_window) { + rect.offsetRect(_window->_posX, _window->_posY); + _window->display(); + } + + // display items + if (_window && _window->_alphaColor != 0) { + _gameRef->_renderer->_forceAlphaColor = _window->_alphaColor; + } + int yyy = rect.top; + for (int j = 0; j < itemsY; j++) { + int xxx = rect.left; + for (int i = 0; i < itemsX; i++) { + int itemIndex = _scrollOffset + j * itemsX + i; + if (itemIndex >= 0 && itemIndex < (int32)adGame->_inventoryOwner->getInventory()->_takenItems.size()) { + AdItem *item = adGame->_inventoryOwner->getInventory()->_takenItems[itemIndex]; + if (item != ((AdGame *)_gameRef)->_selectedItem || !_hideSelected) { + item->update(); + item->display(xxx, yyy); + } + } + + xxx += (_itemWidth + _spacing); + } + yyy += (_itemHeight + _spacing); + } + if (_window && _window->_alphaColor != 0) { + _gameRef->_renderer->_forceAlphaColor = 0; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdInventoryBox::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 INVENTORY_BOX file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(INVENTORY_BOX) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(WINDOW) +TOKEN_DEF(EXCLUSIVE) +TOKEN_DEF(ALWAYS_VISIBLE) +TOKEN_DEF(AREA) +TOKEN_DEF(SPACING) +TOKEN_DEF(ITEM_WIDTH) +TOKEN_DEF(ITEM_HEIGHT) +TOKEN_DEF(SCROLL_BY) +TOKEN_DEF(NAME) +TOKEN_DEF(CAPTION) +TOKEN_DEF(HIDE_SELECTED) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(INVENTORY_BOX) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(WINDOW) + TOKEN_TABLE(EXCLUSIVE) + TOKEN_TABLE(ALWAYS_VISIBLE) + TOKEN_TABLE(AREA) + TOKEN_TABLE(SPACING) + TOKEN_TABLE(ITEM_WIDTH) + TOKEN_TABLE(ITEM_HEIGHT) + TOKEN_TABLE(SCROLL_BY) + TOKEN_TABLE(NAME) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(HIDE_SELECTED) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + bool alwaysVisible = false; + + _exclusive = false; + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_INVENTORY_BOX) { + _gameRef->LOG(0, "'INVENTORY_BOX' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_WINDOW: + delete _window; + _window = new UIWindow(_gameRef); + if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { + delete _window; + _window = NULL; + cmd = PARSERR_GENERIC; + } else { + _gameRef->registerObject(_window); + } + break; + + case TOKEN_AREA: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_itemsArea.left, &_itemsArea.top, &_itemsArea.right, &_itemsArea.bottom); + break; + + case TOKEN_EXCLUSIVE: + parser.scanStr((char *)params, "%b", &_exclusive); + break; + + case TOKEN_HIDE_SELECTED: + parser.scanStr((char *)params, "%b", &_hideSelected); + break; + + case TOKEN_ALWAYS_VISIBLE: + parser.scanStr((char *)params, "%b", &alwaysVisible); + break; + + case TOKEN_SPACING: + parser.scanStr((char *)params, "%d", &_spacing); + break; + + case TOKEN_ITEM_WIDTH: + parser.scanStr((char *)params, "%d", &_itemWidth); + break; + + case TOKEN_ITEM_HEIGHT: + parser.scanStr((char *)params, "%d", &_itemHeight); + break; + + case TOKEN_SCROLL_BY: + parser.scanStr((char *)params, "%d", &_scrollBy); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in INVENTORY_BOX definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading INVENTORY_BOX definition"); + return STATUS_FAILED; + } + + if (_exclusive) { + delete _closeButton; + _closeButton = new UIButton(_gameRef); + if (_closeButton) { + _closeButton->setName("close"); + _closeButton->setListener(this, _closeButton, 0); + _closeButton->_parent = _window; + } + } + + _visible = alwaysVisible; + + if (_window) { + for (uint32 i = 0; i < _window->_widgets.size(); i++) { + if (!_window->_widgets[i]->_listenerObject) { + _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); + } + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "INVENTORY_BOX\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "AREA { %d, %d, %d, %d }\n", _itemsArea.left, _itemsArea.top, _itemsArea.right, _itemsArea.bottom); + + buffer->putTextIndent(indent + 2, "EXCLUSIVE=%s\n", _exclusive ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "HIDE_SELECTED=%s\n", _hideSelected ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "ALWAYS_VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "SPACING=%d\n", _spacing); + buffer->putTextIndent(indent + 2, "ITEM_WIDTH=%d\n", _itemWidth); + buffer->putTextIndent(indent + 2, "ITEM_HEIGHT=%d\n", _itemHeight); + buffer->putTextIndent(indent + 2, "SCROLL_BY=%d\n", _scrollBy); + + buffer->putTextIndent(indent + 2, "\n"); + + // window + if (_window) { + _window->saveAsText(buffer, indent + 2); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdInventoryBox::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_closeButton)); + persistMgr->transfer(TMEMBER(_hideSelected)); + persistMgr->transfer(TMEMBER(_itemHeight)); + persistMgr->transfer(TMEMBER(_itemsArea)); + persistMgr->transfer(TMEMBER(_itemWidth)); + persistMgr->transfer(TMEMBER(_scrollBy)); + persistMgr->transfer(TMEMBER(_scrollOffset)); + persistMgr->transfer(TMEMBER(_spacing)); + persistMgr->transfer(TMEMBER(_visible)); + persistMgr->transfer(TMEMBER(_window)); + persistMgr->transfer(TMEMBER(_exclusive)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_inventory_box.h b/engines/wintermute/ad/ad_inventory_box.h index 451ebf9635b5..cb6d084562dc 100644 --- a/engines/wintermute/ad/ad_inventory_box.h +++ b/engines/wintermute/ad/ad_inventory_box.h @@ -1,65 +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 - */ - -#ifndef WINTERMUTE_ADINVENTORYBOX_H -#define WINTERMUTE_ADINVENTORYBOX_H - -#include "engines/wintermute/base/base_object.h" -#include "common/rect.h" - -namespace Wintermute { -class UIButton; -class UIWindow; - -class AdInventoryBox : public BaseObject { -public: - bool _hideSelected; - DECLARE_PERSISTENT(AdInventoryBox, BaseObject) - bool _visible; - virtual bool display(); - UIButton *_closeButton; - int _spacing; - int _scrollOffset; - Rect32 _itemsArea; - bool listen(BaseScriptHolder *param1, uint32 param2); - UIWindow *_window; - AdInventoryBox(BaseGame *inGame); - virtual ~AdInventoryBox(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); -private: - bool _exclusive; - int _scrollBy; - int _itemHeight; - int _itemWidth; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADINVENTORYBOX_H +#define WINTERMUTE_ADINVENTORYBOX_H + +#include "engines/wintermute/base/base_object.h" +#include "common/rect.h" + +namespace Wintermute { +class UIButton; +class UIWindow; + +class AdInventoryBox : public BaseObject { +public: + bool _hideSelected; + DECLARE_PERSISTENT(AdInventoryBox, BaseObject) + bool _visible; + virtual bool display(); + UIButton *_closeButton; + int _spacing; + int _scrollOffset; + Rect32 _itemsArea; + bool listen(BaseScriptHolder *param1, uint32 param2); + UIWindow *_window; + AdInventoryBox(BaseGame *inGame); + virtual ~AdInventoryBox(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); +private: + bool _exclusive; + int _scrollBy; + int _itemHeight; + int _itemWidth; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_item.cpp b/engines/wintermute/ad/ad_item.cpp index f5c8b163084e..afd813933bea 100644 --- a/engines/wintermute/ad/ad_item.cpp +++ b/engines/wintermute/ad/ad_item.cpp @@ -1,813 +1,813 @@ -/* 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_item.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/platform_osystem.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 "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdItem, false) - -////////////////////////////////////////////////////////////////////////// -AdItem::AdItem(BaseGame *inGame) : AdTalkHolder(inGame) { - _spriteHover = NULL; - _cursorNormal = _cursorHover = NULL; - - _cursorCombined = true; - _inInventory = false; - - _displayAmount = false; - _amount = 0; - _amountOffsetX = 0; - _amountOffsetY = 0; - _amountAlign = TAL_RIGHT; - _amountString = NULL; - - _state = STATE_READY; - - _movable = false; -} - - -////////////////////////////////////////////////////////////////////////// -AdItem::~AdItem() { - delete _spriteHover; - delete _cursorNormal; - delete _cursorHover; - _spriteHover = NULL; - _cursorNormal = NULL; - _cursorHover = NULL; - - delete[] _amountString; - _amountString = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdItem::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 ITEM file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(ITEM) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(CURSOR_HOVER) -TOKEN_DEF(CURSOR_COMBINED) -TOKEN_DEF(CURSOR) -TOKEN_DEF(NAME) -TOKEN_DEF(IMAGE_HOVER) -TOKEN_DEF(IMAGE) -TOKEN_DEF(EVENTS) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(FONT) -TOKEN_DEF(ALPHA_COLOR) -TOKEN_DEF(ALPHA) -TOKEN_DEF(TALK_SPECIAL) -TOKEN_DEF(TALK) -TOKEN_DEF(SPRITE_HOVER) -TOKEN_DEF(SPRITE) -TOKEN_DEF(DISPLAY_AMOUNT) -TOKEN_DEF(AMOUNT_OFFSET_X) -TOKEN_DEF(AMOUNT_OFFSET_Y) -TOKEN_DEF(AMOUNT_ALIGN) -TOKEN_DEF(AMOUNT_STRING) -TOKEN_DEF(AMOUNT) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdItem::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ITEM) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(CURSOR_HOVER) - TOKEN_TABLE(CURSOR_COMBINED) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(NAME) - TOKEN_TABLE(IMAGE_HOVER) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(EVENTS) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(FONT) - TOKEN_TABLE(ALPHA_COLOR) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(TALK_SPECIAL) - TOKEN_TABLE(TALK) - TOKEN_TABLE(SPRITE_HOVER) - TOKEN_TABLE(SPRITE) - TOKEN_TABLE(DISPLAY_AMOUNT) - TOKEN_TABLE(AMOUNT_OFFSET_X) - TOKEN_TABLE(AMOUNT_OFFSET_Y) - TOKEN_TABLE(AMOUNT_ALIGN) - TOKEN_TABLE(AMOUNT_STRING) - TOKEN_TABLE(AMOUNT) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ITEM) { - _gameRef->LOG(0, "'ITEM' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - int ar = 0, ag = 0, ab = 0, alpha = 255; - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_FONT: - setFont((char *)params); - break; - - case TOKEN_CAPTION: - setCaption((char *)params); - break; - - case TOKEN_IMAGE: - case TOKEN_SPRITE: - delete _sprite; - _sprite = new BaseSprite(_gameRef, this); - if (!_sprite || DID_FAIL(_sprite->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { - delete _sprite; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_HOVER: - case TOKEN_SPRITE_HOVER: - delete _spriteHover; - _spriteHover = new BaseSprite(_gameRef, this); - if (!_spriteHover || DID_FAIL(_spriteHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { - delete _spriteHover; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_AMOUNT: - parser.scanStr((char *)params, "%d", &_amount); - break; - - case TOKEN_DISPLAY_AMOUNT: - parser.scanStr((char *)params, "%b", &_displayAmount); - break; - - case TOKEN_AMOUNT_OFFSET_X: - parser.scanStr((char *)params, "%d", &_amountOffsetX); - break; - - case TOKEN_AMOUNT_OFFSET_Y: - parser.scanStr((char *)params, "%d", &_amountOffsetY); - break; - - case TOKEN_AMOUNT_ALIGN: - if (scumm_stricmp((char *)params, "left") == 0) { - _amountAlign = TAL_LEFT; - } else if (scumm_stricmp((char *)params, "right") == 0) { - _amountAlign = TAL_RIGHT; - } else { - _amountAlign = TAL_CENTER; - } - break; - - case TOKEN_AMOUNT_STRING: - BaseUtils::setString(&_amountString, (char *)params); - break; - - case TOKEN_TALK: { - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSprites.add(spr); - } - } - break; - - case TOKEN_TALK_SPECIAL: { - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) { - cmd = PARSERR_GENERIC; - } else { - _talkSpritesEx.add(spr); - } - } - break; - - case TOKEN_CURSOR: - delete _cursorNormal; - _cursorNormal = new BaseSprite(_gameRef); - if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { - delete _cursorNormal; - _cursorNormal = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_CURSOR_HOVER: - delete _cursorHover; - _cursorHover = new BaseSprite(_gameRef); - if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { - delete _cursorHover; - _cursorHover = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_CURSOR_COMBINED: - parser.scanStr((char *)params, "%b", &_cursorCombined); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_ALPHA_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); - break; - - case TOKEN_ALPHA: - parser.scanStr((char *)params, "%d", &alpha); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ITEM definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading ITEM definition"); - return STATUS_FAILED; - } - - if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { - ar = ag = ab = 255; - } - _alphaColor = BYTETORGBA(ar, ag, ab, alpha); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::update() { - _currentSprite = NULL; - - if (_state == STATE_READY && _animSprite) { - delete _animSprite; - _animSprite = NULL; - } - - // finished playing animation? - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { - _state = STATE_READY; - _currentSprite = _animSprite; - } - - if (_sentence && _state != STATE_TALKING) { - _sentence->finish(); - } - - // default: stand animation - if (!_currentSprite) { - _currentSprite = _sprite; - } - - switch (_state) { - ////////////////////////////////////////////////////////////////////////// - case STATE_PLAYING_ANIM: - _currentSprite = _animSprite; - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_READY: - if (!_animSprite) { - if (_gameRef->_activeObject == this && _spriteHover) { - _currentSprite = _spriteHover; - } else { - _currentSprite = _sprite; - } - } - break; - - ////////////////////////////////////////////////////////////////////////// - case STATE_TALKING: { - _sentence->update(); - if (_sentence->_currentSprite) { - _tempSprite2 = _sentence->_currentSprite; - } - - bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); - if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { - if (timeIsUp) { - _sentence->finish(); - _tempSprite2 = NULL; - _state = STATE_READY; - } else { - _tempSprite2 = getTalkStance(_sentence->getNextStance()); - if (_tempSprite2) { - _tempSprite2->reset(); - _currentSprite = _tempSprite2; - } - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } else { - _currentSprite = _tempSprite2; - ((AdGame *)_gameRef)->addSentence(_sentence); - } - } - default: - break; - } - _ready = (_state == STATE_READY); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::display(int x, int y) { - int width = 0; - if (_currentSprite) { - Rect32 rc; - _currentSprite->getBoundingRect(&rc, 0, 0); - width = rc.width(); - } - - _posX = x + width / 2; - _posY = y; - - bool ret; - if (_currentSprite) { - ret = _currentSprite->draw(x, y, this, 100, 100, _alphaColor); - } else { - ret = STATUS_OK; - } - - if (_displayAmount) { - int amountX = x; - int amountY = y + _amountOffsetY; - - if (_amountAlign == TAL_RIGHT) { - width -= _amountOffsetX; - amountX -= _amountOffsetX; - } - amountX += _amountOffsetX; - - BaseFont *font = _font ? _font : _gameRef->_systemFont; - if (font) { - if (_amountString) { - font->drawText((byte *)_amountString, amountX, amountY, width, _amountAlign); - } else { - char str[256]; - sprintf(str, "%d", _amount); - font->drawText((byte *)str, amountX, amountY, width, _amountAlign); - } - } - } - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetHoverSprite - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetHoverSprite") == 0) { - stack->correctParams(1); - - bool setCurrent = false; - if (_currentSprite && _currentSprite == _spriteHover) { - setCurrent = true; - } - - const char *filename = stack->pop()->getString(); - - delete _spriteHover; - _spriteHover = NULL; - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - stack->pushBool(false); - script->runtimeError("Item.SetHoverSprite failed for file '%s'", filename); - } else { - _spriteHover = spr; - if (setCurrent) { - _currentSprite = _spriteHover; - } - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverSprite") == 0) { - stack->correctParams(0); - - if (!_spriteHover || !_spriteHover->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_spriteHover->getFilename()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverSpriteObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverSpriteObject") == 0) { - stack->correctParams(0); - if (!_spriteHover) { - stack->pushNULL(); - } else { - stack->pushNative(_spriteHover, true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetNormalCursor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetNormalCursor") == 0) { - stack->correctParams(1); - - const char *filename = stack->pop()->getString(); - - delete _cursorNormal; - _cursorNormal = NULL; - BaseSprite *spr = new BaseSprite(_gameRef); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - stack->pushBool(false); - script->runtimeError("Item.SetNormalCursor failed for file '%s'", filename); - } else { - _cursorNormal = spr; - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetNormalCursor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetNormalCursor") == 0) { - stack->correctParams(0); - - if (!_cursorNormal || !_cursorNormal->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_cursorNormal->getFilename()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetNormalCursorObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetNormalCursorObject") == 0) { - stack->correctParams(0); - - if (!_cursorNormal) { - stack->pushNULL(); - } else { - stack->pushNative(_cursorNormal, true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetHoverCursor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetHoverCursor") == 0) { - stack->correctParams(1); - - const char *filename = stack->pop()->getString(); - - delete _cursorHover; - _cursorHover = NULL; - BaseSprite *spr = new BaseSprite(_gameRef); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - stack->pushBool(false); - script->runtimeError("Item.SetHoverCursor failed for file '%s'", filename); - } else { - _cursorHover = spr; - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverCursor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverCursor") == 0) { - stack->correctParams(0); - - if (!_cursorHover || !_cursorHover->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_cursorHover->getFilename()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverCursorObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverCursorObject") == 0) { - stack->correctParams(0); - - if (!_cursorHover) { - stack->pushNULL(); - } else { - stack->pushNative(_cursorHover, true); - } - return STATUS_OK; - } else { - return AdTalkHolder::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdItem::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("item"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Name") == 0) { - _scValue->setString(getName()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // DisplayAmount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DisplayAmount") == 0) { - _scValue->setBool(_displayAmount); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Amount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Amount") == 0) { - _scValue->setInt(_amount); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountOffsetX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountOffsetX") == 0) { - _scValue->setInt(_amountOffsetX); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountOffsetY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountOffsetY") == 0) { - _scValue->setInt(_amountOffsetY); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountAlign") == 0) { - _scValue->setInt(_amountAlign); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountString - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountString") == 0) { - if (!_amountString) { - _scValue->setNULL(); - } else { - _scValue->setString(_amountString); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorCombined - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorCombined") == 0) { - _scValue->setBool(_cursorCombined); - return _scValue; - } else { - return AdTalkHolder::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DisplayAmount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DisplayAmount") == 0) { - _displayAmount = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Amount - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Amount") == 0) { - _amount = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountOffsetX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountOffsetX") == 0) { - _amountOffsetX = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountOffsetY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountOffsetY") == 0) { - _amountOffsetY = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountAlign") == 0) { - _amountAlign = (TTextAlign)value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AmountString - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AmountString") == 0) { - if (value->isNULL()) { - delete[] _amountString; - _amountString = NULL; - } else { - BaseUtils::setString(&_amountString, value->getString()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorCombined - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorCombined") == 0) { - _cursorCombined = value->getBool(); - return STATUS_OK; - } else { - return AdTalkHolder::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdItem::scToString() { - return "[item]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::persist(BasePersistenceManager *persistMgr) { - - AdTalkHolder::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_cursorCombined)); - persistMgr->transfer(TMEMBER(_cursorHover)); - persistMgr->transfer(TMEMBER(_cursorNormal)); - persistMgr->transfer(TMEMBER(_spriteHover)); - persistMgr->transfer(TMEMBER(_inInventory)); - persistMgr->transfer(TMEMBER(_displayAmount)); - persistMgr->transfer(TMEMBER(_amount)); - persistMgr->transfer(TMEMBER(_amountOffsetX)); - persistMgr->transfer(TMEMBER(_amountOffsetY)); - persistMgr->transfer(TMEMBER_INT(_amountAlign)); - persistMgr->transfer(TMEMBER(_amountString)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdItem::getExtendedFlag(const char *flagName) { - if (!flagName) { - return false; - } else if (strcmp(flagName, "usable") == 0) { - return true; - } else { - return AdObject::getExtendedFlag(flagName); - } -} - -} // end of namespace Wintermute +/* 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_item.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/platform_osystem.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 "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdItem, false) + +////////////////////////////////////////////////////////////////////////// +AdItem::AdItem(BaseGame *inGame) : AdTalkHolder(inGame) { + _spriteHover = NULL; + _cursorNormal = _cursorHover = NULL; + + _cursorCombined = true; + _inInventory = false; + + _displayAmount = false; + _amount = 0; + _amountOffsetX = 0; + _amountOffsetY = 0; + _amountAlign = TAL_RIGHT; + _amountString = NULL; + + _state = STATE_READY; + + _movable = false; +} + + +////////////////////////////////////////////////////////////////////////// +AdItem::~AdItem() { + delete _spriteHover; + delete _cursorNormal; + delete _cursorHover; + _spriteHover = NULL; + _cursorNormal = NULL; + _cursorHover = NULL; + + delete[] _amountString; + _amountString = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdItem::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 ITEM file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(ITEM) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(CURSOR_HOVER) +TOKEN_DEF(CURSOR_COMBINED) +TOKEN_DEF(CURSOR) +TOKEN_DEF(NAME) +TOKEN_DEF(IMAGE_HOVER) +TOKEN_DEF(IMAGE) +TOKEN_DEF(EVENTS) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(FONT) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(TALK_SPECIAL) +TOKEN_DEF(TALK) +TOKEN_DEF(SPRITE_HOVER) +TOKEN_DEF(SPRITE) +TOKEN_DEF(DISPLAY_AMOUNT) +TOKEN_DEF(AMOUNT_OFFSET_X) +TOKEN_DEF(AMOUNT_OFFSET_Y) +TOKEN_DEF(AMOUNT_ALIGN) +TOKEN_DEF(AMOUNT_STRING) +TOKEN_DEF(AMOUNT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdItem::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ITEM) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(CURSOR_HOVER) + TOKEN_TABLE(CURSOR_COMBINED) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(NAME) + TOKEN_TABLE(IMAGE_HOVER) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(FONT) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(TALK_SPECIAL) + TOKEN_TABLE(TALK) + TOKEN_TABLE(SPRITE_HOVER) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(DISPLAY_AMOUNT) + TOKEN_TABLE(AMOUNT_OFFSET_X) + TOKEN_TABLE(AMOUNT_OFFSET_Y) + TOKEN_TABLE(AMOUNT_ALIGN) + TOKEN_TABLE(AMOUNT_STRING) + TOKEN_TABLE(AMOUNT) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ITEM) { + _gameRef->LOG(0, "'ITEM' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + int ar = 0, ag = 0, ab = 0, alpha = 255; + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_FONT: + setFont((char *)params); + break; + + case TOKEN_CAPTION: + setCaption((char *)params); + break; + + case TOKEN_IMAGE: + case TOKEN_SPRITE: + delete _sprite; + _sprite = new BaseSprite(_gameRef, this); + if (!_sprite || DID_FAIL(_sprite->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { + delete _sprite; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_HOVER: + case TOKEN_SPRITE_HOVER: + delete _spriteHover; + _spriteHover = new BaseSprite(_gameRef, this); + if (!_spriteHover || DID_FAIL(_spriteHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { + delete _spriteHover; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_AMOUNT: + parser.scanStr((char *)params, "%d", &_amount); + break; + + case TOKEN_DISPLAY_AMOUNT: + parser.scanStr((char *)params, "%b", &_displayAmount); + break; + + case TOKEN_AMOUNT_OFFSET_X: + parser.scanStr((char *)params, "%d", &_amountOffsetX); + break; + + case TOKEN_AMOUNT_OFFSET_Y: + parser.scanStr((char *)params, "%d", &_amountOffsetY); + break; + + case TOKEN_AMOUNT_ALIGN: + if (scumm_stricmp((char *)params, "left") == 0) { + _amountAlign = TAL_LEFT; + } else if (scumm_stricmp((char *)params, "right") == 0) { + _amountAlign = TAL_RIGHT; + } else { + _amountAlign = TAL_CENTER; + } + break; + + case TOKEN_AMOUNT_STRING: + BaseUtils::setString(&_amountString, (char *)params); + break; + + case TOKEN_TALK: { + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSprites.add(spr); + } + } + break; + + case TOKEN_TALK_SPECIAL: { + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile((char *)params, ((AdGame *)_gameRef)->_texTalkLifeTime))) { + cmd = PARSERR_GENERIC; + } else { + _talkSpritesEx.add(spr); + } + } + break; + + case TOKEN_CURSOR: + delete _cursorNormal; + _cursorNormal = new BaseSprite(_gameRef); + if (!_cursorNormal || DID_FAIL(_cursorNormal->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { + delete _cursorNormal; + _cursorNormal = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_CURSOR_HOVER: + delete _cursorHover; + _cursorHover = new BaseSprite(_gameRef); + if (!_cursorHover || DID_FAIL(_cursorHover->loadFile((char *)params, ((AdGame *)_gameRef)->_texItemLifeTime))) { + delete _cursorHover; + _cursorHover = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_CURSOR_COMBINED: + parser.scanStr((char *)params, "%b", &_cursorCombined); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_ALPHA_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.scanStr((char *)params, "%d", &alpha); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ITEM definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading ITEM definition"); + return STATUS_FAILED; + } + + if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { + ar = ag = ab = 255; + } + _alphaColor = BYTETORGBA(ar, ag, ab, alpha); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::update() { + _currentSprite = NULL; + + if (_state == STATE_READY && _animSprite) { + delete _animSprite; + _animSprite = NULL; + } + + // finished playing animation? + if (_state == STATE_PLAYING_ANIM && _animSprite != NULL && _animSprite->_finished) { + _state = STATE_READY; + _currentSprite = _animSprite; + } + + if (_sentence && _state != STATE_TALKING) { + _sentence->finish(); + } + + // default: stand animation + if (!_currentSprite) { + _currentSprite = _sprite; + } + + switch (_state) { + ////////////////////////////////////////////////////////////////////////// + case STATE_PLAYING_ANIM: + _currentSprite = _animSprite; + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_READY: + if (!_animSprite) { + if (_gameRef->_activeObject == this && _spriteHover) { + _currentSprite = _spriteHover; + } else { + _currentSprite = _sprite; + } + } + break; + + ////////////////////////////////////////////////////////////////////////// + case STATE_TALKING: { + _sentence->update(); + if (_sentence->_currentSprite) { + _tempSprite2 = _sentence->_currentSprite; + } + + bool timeIsUp = (_sentence->_sound && _sentence->_soundStarted && (!_sentence->_sound->isPlaying() && !_sentence->_sound->isPaused())) || (!_sentence->_sound && _sentence->_duration <= _gameRef->_timer - _sentence->_startTime); + if (_tempSprite2 == NULL || _tempSprite2->_finished || (/*_tempSprite2->_looping &&*/ timeIsUp)) { + if (timeIsUp) { + _sentence->finish(); + _tempSprite2 = NULL; + _state = STATE_READY; + } else { + _tempSprite2 = getTalkStance(_sentence->getNextStance()); + if (_tempSprite2) { + _tempSprite2->reset(); + _currentSprite = _tempSprite2; + } + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } else { + _currentSprite = _tempSprite2; + ((AdGame *)_gameRef)->addSentence(_sentence); + } + } + default: + break; + } + _ready = (_state == STATE_READY); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::display(int x, int y) { + int width = 0; + if (_currentSprite) { + Rect32 rc; + _currentSprite->getBoundingRect(&rc, 0, 0); + width = rc.width(); + } + + _posX = x + width / 2; + _posY = y; + + bool ret; + if (_currentSprite) { + ret = _currentSprite->draw(x, y, this, 100, 100, _alphaColor); + } else { + ret = STATUS_OK; + } + + if (_displayAmount) { + int amountX = x; + int amountY = y + _amountOffsetY; + + if (_amountAlign == TAL_RIGHT) { + width -= _amountOffsetX; + amountX -= _amountOffsetX; + } + amountX += _amountOffsetX; + + BaseFont *font = _font ? _font : _gameRef->_systemFont; + if (font) { + if (_amountString) { + font->drawText((byte *)_amountString, amountX, amountY, width, _amountAlign); + } else { + char str[256]; + sprintf(str, "%d", _amount); + font->drawText((byte *)str, amountX, amountY, width, _amountAlign); + } + } + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdItem::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetHoverSprite + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetHoverSprite") == 0) { + stack->correctParams(1); + + bool setCurrent = false; + if (_currentSprite && _currentSprite == _spriteHover) { + setCurrent = true; + } + + const char *filename = stack->pop()->getString(); + + delete _spriteHover; + _spriteHover = NULL; + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + stack->pushBool(false); + script->runtimeError("Item.SetHoverSprite failed for file '%s'", filename); + } else { + _spriteHover = spr; + if (setCurrent) { + _currentSprite = _spriteHover; + } + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverSprite") == 0) { + stack->correctParams(0); + + if (!_spriteHover || !_spriteHover->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_spriteHover->getFilename()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverSpriteObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverSpriteObject") == 0) { + stack->correctParams(0); + if (!_spriteHover) { + stack->pushNULL(); + } else { + stack->pushNative(_spriteHover, true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetNormalCursor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetNormalCursor") == 0) { + stack->correctParams(1); + + const char *filename = stack->pop()->getString(); + + delete _cursorNormal; + _cursorNormal = NULL; + BaseSprite *spr = new BaseSprite(_gameRef); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + stack->pushBool(false); + script->runtimeError("Item.SetNormalCursor failed for file '%s'", filename); + } else { + _cursorNormal = spr; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetNormalCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetNormalCursor") == 0) { + stack->correctParams(0); + + if (!_cursorNormal || !_cursorNormal->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_cursorNormal->getFilename()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetNormalCursorObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetNormalCursorObject") == 0) { + stack->correctParams(0); + + if (!_cursorNormal) { + stack->pushNULL(); + } else { + stack->pushNative(_cursorNormal, true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetHoverCursor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetHoverCursor") == 0) { + stack->correctParams(1); + + const char *filename = stack->pop()->getString(); + + delete _cursorHover; + _cursorHover = NULL; + BaseSprite *spr = new BaseSprite(_gameRef); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + stack->pushBool(false); + script->runtimeError("Item.SetHoverCursor failed for file '%s'", filename); + } else { + _cursorHover = spr; + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverCursor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverCursor") == 0) { + stack->correctParams(0); + + if (!_cursorHover || !_cursorHover->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_cursorHover->getFilename()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverCursorObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverCursorObject") == 0) { + stack->correctParams(0); + + if (!_cursorHover) { + stack->pushNULL(); + } else { + stack->pushNative(_cursorHover, true); + } + return STATUS_OK; + } else { + return AdTalkHolder::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdItem::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("item"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Name") == 0) { + _scValue->setString(getName()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // DisplayAmount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DisplayAmount") == 0) { + _scValue->setBool(_displayAmount); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Amount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Amount") == 0) { + _scValue->setInt(_amount); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountOffsetX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountOffsetX") == 0) { + _scValue->setInt(_amountOffsetX); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountOffsetY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountOffsetY") == 0) { + _scValue->setInt(_amountOffsetY); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountAlign") == 0) { + _scValue->setInt(_amountAlign); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountString") == 0) { + if (!_amountString) { + _scValue->setNULL(); + } else { + _scValue->setString(_amountString); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorCombined + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorCombined") == 0) { + _scValue->setBool(_cursorCombined); + return _scValue; + } else { + return AdTalkHolder::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DisplayAmount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DisplayAmount") == 0) { + _displayAmount = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Amount + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Amount") == 0) { + _amount = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountOffsetX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountOffsetX") == 0) { + _amountOffsetX = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountOffsetY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountOffsetY") == 0) { + _amountOffsetY = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountAlign") == 0) { + _amountAlign = (TTextAlign)value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AmountString + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AmountString") == 0) { + if (value->isNULL()) { + delete[] _amountString; + _amountString = NULL; + } else { + BaseUtils::setString(&_amountString, value->getString()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorCombined + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorCombined") == 0) { + _cursorCombined = value->getBool(); + return STATUS_OK; + } else { + return AdTalkHolder::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdItem::scToString() { + return "[item]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::persist(BasePersistenceManager *persistMgr) { + + AdTalkHolder::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_cursorCombined)); + persistMgr->transfer(TMEMBER(_cursorHover)); + persistMgr->transfer(TMEMBER(_cursorNormal)); + persistMgr->transfer(TMEMBER(_spriteHover)); + persistMgr->transfer(TMEMBER(_inInventory)); + persistMgr->transfer(TMEMBER(_displayAmount)); + persistMgr->transfer(TMEMBER(_amount)); + persistMgr->transfer(TMEMBER(_amountOffsetX)); + persistMgr->transfer(TMEMBER(_amountOffsetY)); + persistMgr->transfer(TMEMBER_INT(_amountAlign)); + persistMgr->transfer(TMEMBER(_amountString)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdItem::getExtendedFlag(const char *flagName) { + if (!flagName) { + return false; + } else if (strcmp(flagName, "usable") == 0) { + return true; + } else { + return AdObject::getExtendedFlag(flagName); + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_item.h b/engines/wintermute/ad/ad_item.h index e06266f8b750..6047c542c1a5 100644 --- a/engines/wintermute/ad/ad_item.h +++ b/engines/wintermute/ad/ad_item.h @@ -1,69 +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_ADITEM_H -#define WINTERMUTE_ADITEM_H - - -#include "engines/wintermute/ad/ad_talk_holder.h" - -namespace Wintermute { - -class AdItem : public AdTalkHolder { -public: - bool update(); - DECLARE_PERSISTENT(AdItem, AdTalkHolder) - bool display(int x, int y); - bool getExtendedFlag(const char *flagName); - bool _inInventory; - bool _cursorCombined; - BaseSprite *_spriteHover; - BaseSprite *_cursorNormal; - BaseSprite *_cursorHover; - AdItem(BaseGame *inGame); - virtual ~AdItem(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - - // 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: - bool _displayAmount; - int _amount; - int _amountOffsetX; - int _amountOffsetY; - TTextAlign _amountAlign; - char *_amountString; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADITEM_H +#define WINTERMUTE_ADITEM_H + + +#include "engines/wintermute/ad/ad_talk_holder.h" + +namespace Wintermute { + +class AdItem : public AdTalkHolder { +public: + bool update(); + DECLARE_PERSISTENT(AdItem, AdTalkHolder) + bool display(int x, int y); + bool getExtendedFlag(const char *flagName); + bool _inInventory; + bool _cursorCombined; + BaseSprite *_spriteHover; + BaseSprite *_cursorNormal; + BaseSprite *_cursorHover; + AdItem(BaseGame *inGame); + virtual ~AdItem(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + + // 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: + bool _displayAmount; + int _amount; + int _amountOffsetX; + int _amountOffsetY; + TTextAlign _amountAlign; + char *_amountString; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_layer.cpp b/engines/wintermute/ad/ad_layer.cpp index 709ab50b58f0..46b75b8b21e4 100644 --- a/engines/wintermute/ad/ad_layer.cpp +++ b/engines/wintermute/ad/ad_layer.cpp @@ -1,564 +1,564 @@ -/* 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/ad/ad_layer.h" -#include "engines/wintermute/ad/ad_scene_node.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_dynamic_buffer.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/base_file_manager.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdLayer, false) - -////////////////////////////////////////////////////////////////////////// -AdLayer::AdLayer(BaseGame *inGame) : BaseObject(inGame) { - _main = false; - _width = _height = 0; - _active = true; - _closeUp = false; -} - - -////////////////////////////////////////////////////////////////////////// -AdLayer::~AdLayer() { - for (uint32 i = 0; i < _nodes.size(); i++) { - delete _nodes[i]; - } - _nodes.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdLayer::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdLayer::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 LAYER file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(LAYER) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(NAME) -TOKEN_DEF(WIDTH) -TOKEN_DEF(HEIGHT) -TOKEN_DEF(MAIN) -TOKEN_DEF(ENTITY) -TOKEN_DEF(REGION) -TOKEN_DEF(ACTIVE) -TOKEN_DEF(EDITOR_SELECTED) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(CLOSE_UP) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdLayer::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(LAYER) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(WIDTH) - TOKEN_TABLE(HEIGHT) - TOKEN_TABLE(MAIN) - TOKEN_TABLE(ENTITY) - TOKEN_TABLE(REGION) - TOKEN_TABLE(ACTIVE) - TOKEN_TABLE(EDITOR_SELECTED) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(CLOSE_UP) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_LAYER) { - _gameRef->LOG(0, "'LAYER' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_MAIN: - parser.scanStr((char *)params, "%b", &_main); - break; - - case TOKEN_CLOSE_UP: - parser.scanStr((char *)params, "%b", &_closeUp); - break; - - case TOKEN_WIDTH: - parser.scanStr((char *)params, "%d", &_width); - break; - - case TOKEN_HEIGHT: - parser.scanStr((char *)params, "%d", &_height); - break; - - case TOKEN_ACTIVE: - parser.scanStr((char *)params, "%b", &_active); - break; - - case TOKEN_REGION: { - AdRegion *region = new AdRegion(_gameRef); - AdSceneNode *node = new AdSceneNode(_gameRef); - if (!region || !node || DID_FAIL(region->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete region; - delete node; - region = NULL; - node = NULL; - } else { - node->setRegion(region); - _nodes.add(node); - } - } - break; - - case TOKEN_ENTITY: { - AdEntity *entity = new AdEntity(_gameRef); - AdSceneNode *node = new AdSceneNode(_gameRef); - if (entity) { - entity->_zoomable = false; // scene entites default to NOT zoom - } - if (!entity || !node || DID_FAIL(entity->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete entity; - delete node; - entity = NULL; - node = NULL; - } else { - node->setEntity(entity); - _nodes.add(node); - } - } - break; - - case TOKEN_EDITOR_SELECTED: - parser.scanStr((char *)params, "%b", &_editorSelected); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in LAYER definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetNode - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetNode") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - int node = -1; - - if (val->_type == VAL_INT) { - node = val->getInt(); - } else { // get by name - for (uint32 i = 0; i < _nodes.size(); i++) { - if ((_nodes[i]->_type == OBJECT_ENTITY && scumm_stricmp(_nodes[i]->_entity->getName(), val->getString()) == 0) || - (_nodes[i]->_type == OBJECT_REGION && scumm_stricmp(_nodes[i]->_region->getName(), val->getString()) == 0)) { - node = i; - break; - } - } - } - - if (node < 0 || node >= (int32)_nodes.size()) { - stack->pushNULL(); - } else { - switch (_nodes[node]->_type) { - case OBJECT_ENTITY: - stack->pushNative(_nodes[node]->_entity, true); - break; - case OBJECT_REGION: - stack->pushNative(_nodes[node]->_region, true); - break; - default: - stack->pushNULL(); - } - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddRegion / AddEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddRegion") == 0 || strcmp(name, "AddEntity") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdSceneNode *node = new AdSceneNode(_gameRef); - if (strcmp(name, "AddRegion") == 0) { - AdRegion *region = new AdRegion(_gameRef); - if (!val->isNULL()) { - region->setName(val->getString()); - } - node->setRegion(region); - stack->pushNative(region, true); - } else { - AdEntity *entity = new AdEntity(_gameRef); - if (!val->isNULL()) { - entity->setName(val->getString()); - } - node->setEntity(entity); - stack->pushNative(entity, true); - } - _nodes.add(node); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InsertRegion / InsertEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InsertRegion") == 0 || strcmp(name, "InsertEntity") == 0) { - stack->correctParams(2); - int index = stack->pop()->getInt(); - ScValue *val = stack->pop(); - - AdSceneNode *node = new AdSceneNode(_gameRef); - if (strcmp(name, "InsertRegion") == 0) { - AdRegion *region = new AdRegion(_gameRef); - if (!val->isNULL()) { - region->setName(val->getString()); - } - node->setRegion(region); - stack->pushNative(region, true); - } else { - AdEntity *entity = new AdEntity(_gameRef); - if (!val->isNULL()) { - entity->setName(val->getString()); - } - node->setEntity(entity); - stack->pushNative(entity, true); - } - if (index < 0) { - index = 0; - } - if (index <= (int32)_nodes.size() - 1) { - _nodes.insert_at(index, node); - } else { - _nodes.add(node); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteNode - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteNode") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdSceneNode *toDelete = NULL; - if (val->isNative()) { - BaseScriptable *temp = val->getNative(); - for (uint32 i = 0; i < _nodes.size(); i++) { - if (_nodes[i]->_region == temp || _nodes[i]->_entity == temp) { - toDelete = _nodes[i]; - break; - } - } - } else { - int index = val->getInt(); - if (index >= 0 && index < (int32)_nodes.size()) { - toDelete = _nodes[index]; - } - } - if (toDelete == NULL) { - stack->pushBool(false); - return STATUS_OK; - } - - for (uint32 i = 0; i < _nodes.size(); i++) { - if (_nodes[i] == toDelete) { - delete _nodes[i]; - _nodes[i] = NULL; - _nodes.remove_at(i); - break; - } - } - stack->pushBool(true); - return STATUS_OK; - } else { - return BaseObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdLayer::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("layer"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumNodes (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumNodes") == 0) { - _scValue->setInt(_nodes.size()); - 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; - } - - ////////////////////////////////////////////////////////////////////////// - // Main (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Main") == 0) { - _scValue->setBool(_main); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // CloseUp - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CloseUp") == 0) { - _scValue->setBool(_closeUp); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Active") == 0) { - _scValue->setBool(_active); - return _scValue; - } else { - return BaseObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdLayer::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CloseUp - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CloseUp") == 0) { - _closeUp = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Width - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Width") == 0) { - _width = value->getInt(); - if (_width < 0) { - _width = 0; - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Height - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Height") == 0) { - _height = value->getInt(); - if (_height < 0) { - _height = 0; - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Active") == 0) { - bool b = value->getBool(); - if (b == false && _main) { - _gameRef->LOG(0, "Warning: cannot deactivate scene's main layer"); - } else { - _active = b; - } - return STATUS_OK; - } else { - return BaseObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdLayer::scToString() { - return "[layer]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdLayer::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "LAYER {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - buffer->putTextIndent(indent + 2, "MAIN=%s\n", _main ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); - buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); - buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); - if (_closeUp) { - buffer->putTextIndent(indent + 2, "CLOSE_UP=%s\n", _closeUp ? "TRUE" : "FALSE"); - } - - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_scProp) { - _scProp->saveAsText(buffer, indent + 2); - } - - for (uint32 i = 0; i < _nodes.size(); i++) { - switch (_nodes[i]->_type) { - case OBJECT_ENTITY: - _nodes[i]->_entity->saveAsText(buffer, indent + 2); - break; - case OBJECT_REGION: - _nodes[i]->_region->saveAsText(buffer, indent + 2); - break; - default: - error("AdLayer::SaveAsText - Unhandled enum"); - break; - } - } - - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdLayer::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_active)); - persistMgr->transfer(TMEMBER(_closeUp)); - persistMgr->transfer(TMEMBER(_height)); - persistMgr->transfer(TMEMBER(_main)); - _nodes.persist(persistMgr); - persistMgr->transfer(TMEMBER(_width)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ad/ad_layer.h" +#include "engines/wintermute/ad/ad_scene_node.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_dynamic_buffer.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/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdLayer, false) + +////////////////////////////////////////////////////////////////////////// +AdLayer::AdLayer(BaseGame *inGame) : BaseObject(inGame) { + _main = false; + _width = _height = 0; + _active = true; + _closeUp = false; +} + + +////////////////////////////////////////////////////////////////////////// +AdLayer::~AdLayer() { + for (uint32 i = 0; i < _nodes.size(); i++) { + delete _nodes[i]; + } + _nodes.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdLayer::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdLayer::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 LAYER file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(LAYER) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(WIDTH) +TOKEN_DEF(HEIGHT) +TOKEN_DEF(MAIN) +TOKEN_DEF(ENTITY) +TOKEN_DEF(REGION) +TOKEN_DEF(ACTIVE) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(CLOSE_UP) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdLayer::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(LAYER) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(WIDTH) + TOKEN_TABLE(HEIGHT) + TOKEN_TABLE(MAIN) + TOKEN_TABLE(ENTITY) + TOKEN_TABLE(REGION) + TOKEN_TABLE(ACTIVE) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(CLOSE_UP) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_LAYER) { + _gameRef->LOG(0, "'LAYER' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_MAIN: + parser.scanStr((char *)params, "%b", &_main); + break; + + case TOKEN_CLOSE_UP: + parser.scanStr((char *)params, "%b", &_closeUp); + break; + + case TOKEN_WIDTH: + parser.scanStr((char *)params, "%d", &_width); + break; + + case TOKEN_HEIGHT: + parser.scanStr((char *)params, "%d", &_height); + break; + + case TOKEN_ACTIVE: + parser.scanStr((char *)params, "%b", &_active); + break; + + case TOKEN_REGION: { + AdRegion *region = new AdRegion(_gameRef); + AdSceneNode *node = new AdSceneNode(_gameRef); + if (!region || !node || DID_FAIL(region->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete region; + delete node; + region = NULL; + node = NULL; + } else { + node->setRegion(region); + _nodes.add(node); + } + } + break; + + case TOKEN_ENTITY: { + AdEntity *entity = new AdEntity(_gameRef); + AdSceneNode *node = new AdSceneNode(_gameRef); + if (entity) { + entity->_zoomable = false; // scene entites default to NOT zoom + } + if (!entity || !node || DID_FAIL(entity->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete entity; + delete node; + entity = NULL; + node = NULL; + } else { + node->setEntity(entity); + _nodes.add(node); + } + } + break; + + case TOKEN_EDITOR_SELECTED: + parser.scanStr((char *)params, "%b", &_editorSelected); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in LAYER definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdLayer::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetNode + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetNode") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + int node = -1; + + if (val->_type == VAL_INT) { + node = val->getInt(); + } else { // get by name + for (uint32 i = 0; i < _nodes.size(); i++) { + if ((_nodes[i]->_type == OBJECT_ENTITY && scumm_stricmp(_nodes[i]->_entity->getName(), val->getString()) == 0) || + (_nodes[i]->_type == OBJECT_REGION && scumm_stricmp(_nodes[i]->_region->getName(), val->getString()) == 0)) { + node = i; + break; + } + } + } + + if (node < 0 || node >= (int32)_nodes.size()) { + stack->pushNULL(); + } else { + switch (_nodes[node]->_type) { + case OBJECT_ENTITY: + stack->pushNative(_nodes[node]->_entity, true); + break; + case OBJECT_REGION: + stack->pushNative(_nodes[node]->_region, true); + break; + default: + stack->pushNULL(); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddRegion / AddEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddRegion") == 0 || strcmp(name, "AddEntity") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdSceneNode *node = new AdSceneNode(_gameRef); + if (strcmp(name, "AddRegion") == 0) { + AdRegion *region = new AdRegion(_gameRef); + if (!val->isNULL()) { + region->setName(val->getString()); + } + node->setRegion(region); + stack->pushNative(region, true); + } else { + AdEntity *entity = new AdEntity(_gameRef); + if (!val->isNULL()) { + entity->setName(val->getString()); + } + node->setEntity(entity); + stack->pushNative(entity, true); + } + _nodes.add(node); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InsertRegion / InsertEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InsertRegion") == 0 || strcmp(name, "InsertEntity") == 0) { + stack->correctParams(2); + int index = stack->pop()->getInt(); + ScValue *val = stack->pop(); + + AdSceneNode *node = new AdSceneNode(_gameRef); + if (strcmp(name, "InsertRegion") == 0) { + AdRegion *region = new AdRegion(_gameRef); + if (!val->isNULL()) { + region->setName(val->getString()); + } + node->setRegion(region); + stack->pushNative(region, true); + } else { + AdEntity *entity = new AdEntity(_gameRef); + if (!val->isNULL()) { + entity->setName(val->getString()); + } + node->setEntity(entity); + stack->pushNative(entity, true); + } + if (index < 0) { + index = 0; + } + if (index <= (int32)_nodes.size() - 1) { + _nodes.insert_at(index, node); + } else { + _nodes.add(node); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteNode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteNode") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdSceneNode *toDelete = NULL; + if (val->isNative()) { + BaseScriptable *temp = val->getNative(); + for (uint32 i = 0; i < _nodes.size(); i++) { + if (_nodes[i]->_region == temp || _nodes[i]->_entity == temp) { + toDelete = _nodes[i]; + break; + } + } + } else { + int index = val->getInt(); + if (index >= 0 && index < (int32)_nodes.size()) { + toDelete = _nodes[index]; + } + } + if (toDelete == NULL) { + stack->pushBool(false); + return STATUS_OK; + } + + for (uint32 i = 0; i < _nodes.size(); i++) { + if (_nodes[i] == toDelete) { + delete _nodes[i]; + _nodes[i] = NULL; + _nodes.remove_at(i); + break; + } + } + stack->pushBool(true); + return STATUS_OK; + } else { + return BaseObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdLayer::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("layer"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumNodes (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumNodes") == 0) { + _scValue->setInt(_nodes.size()); + 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; + } + + ////////////////////////////////////////////////////////////////////////// + // Main (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Main") == 0) { + _scValue->setBool(_main); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CloseUp + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CloseUp") == 0) { + _scValue->setBool(_closeUp); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Active") == 0) { + _scValue->setBool(_active); + return _scValue; + } else { + return BaseObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdLayer::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CloseUp + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CloseUp") == 0) { + _closeUp = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Width + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Width") == 0) { + _width = value->getInt(); + if (_width < 0) { + _width = 0; + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Height + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Height") == 0) { + _height = value->getInt(); + if (_height < 0) { + _height = 0; + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Active") == 0) { + bool b = value->getBool(); + if (b == false && _main) { + _gameRef->LOG(0, "Warning: cannot deactivate scene's main layer"); + } else { + _active = b; + } + return STATUS_OK; + } else { + return BaseObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdLayer::scToString() { + return "[layer]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdLayer::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "LAYER {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + buffer->putTextIndent(indent + 2, "MAIN=%s\n", _main ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); + buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); + buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); + if (_closeUp) { + buffer->putTextIndent(indent + 2, "CLOSE_UP=%s\n", _closeUp ? "TRUE" : "FALSE"); + } + + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_scProp) { + _scProp->saveAsText(buffer, indent + 2); + } + + for (uint32 i = 0; i < _nodes.size(); i++) { + switch (_nodes[i]->_type) { + case OBJECT_ENTITY: + _nodes[i]->_entity->saveAsText(buffer, indent + 2); + break; + case OBJECT_REGION: + _nodes[i]->_region->saveAsText(buffer, indent + 2); + break; + default: + error("AdLayer::SaveAsText - Unhandled enum"); + break; + } + } + + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdLayer::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_active)); + persistMgr->transfer(TMEMBER(_closeUp)); + persistMgr->transfer(TMEMBER(_height)); + persistMgr->transfer(TMEMBER(_main)); + _nodes.persist(persistMgr); + persistMgr->transfer(TMEMBER(_width)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_layer.h b/engines/wintermute/ad/ad_layer.h index b01079c09190..bb5f73b13a0f 100644 --- a/engines/wintermute/ad/ad_layer.h +++ b/engines/wintermute/ad/ad_layer.h @@ -1,58 +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_ADLAYER_H -#define WINTERMUTE_ADLAYER_H - -namespace Wintermute { -class AdSceneNode; -class AdLayer : public BaseObject { -public: - bool _closeUp; - DECLARE_PERSISTENT(AdLayer, BaseObject) - bool _active; - int _height; - int _width; - bool _main; - AdLayer(BaseGame *inGame); - virtual ~AdLayer(); - BaseArray _nodes; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual 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 +/* 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_ADLAYER_H +#define WINTERMUTE_ADLAYER_H + +namespace Wintermute { +class AdSceneNode; +class AdLayer : public BaseObject { +public: + bool _closeUp; + DECLARE_PERSISTENT(AdLayer, BaseObject) + bool _active; + int _height; + int _width; + bool _main; + AdLayer(BaseGame *inGame); + virtual ~AdLayer(); + BaseArray _nodes; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual 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/ad/ad_node_state.cpp b/engines/wintermute/ad/ad_node_state.cpp index fb2dfed0f517..493156c7500c 100644 --- a/engines/wintermute/ad/ad_node_state.cpp +++ b/engines/wintermute/ad/ad_node_state.cpp @@ -1,196 +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/base/base_game.h" -#include "engines/wintermute/ad/ad_node_state.h" -#include "engines/wintermute/ad/ad_entity.h" -#include "engines/wintermute/base/base_string_table.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 { - -IMPLEMENT_PERSISTENT(AdNodeState, false) - - -////////////////////////////////////////////////////////////////////////// -AdNodeState::AdNodeState(BaseGame *inGame) : BaseClass(inGame) { - _name = NULL; - _active = false; - for (int i = 0; i < 7; i++) { - _caption[i] = NULL; - } - _alphaColor = 0; - _filename = NULL; - _cursor = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdNodeState::~AdNodeState() { - delete[] _name; - delete[] _filename; - delete[] _cursor; - _name = NULL; - _filename = NULL; - _cursor = NULL; - for (int i = 0; i < 7; i++) { - delete[] _caption[i]; - _caption[i] = NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdNodeState::setName(const char *name) { - delete[] _name; - _name = NULL; - BaseUtils::setString(&_name, name); -} - - -////////////////////////////////////////////////////////////////////////// -void AdNodeState::setFilename(const char *filename) { - delete[] _filename; - _filename = NULL; - BaseUtils::setString(&_filename, filename); -} - - -////////////////////////////////////////////////////////////////////////// -void AdNodeState::setCursor(const char *filename) { - delete[] _cursor; - _cursor = NULL; - BaseUtils::setString(&_cursor, filename); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdNodeState::persist(BasePersistenceManager *persistMgr) { - persistMgr->transfer(TMEMBER(_gameRef)); - - persistMgr->transfer(TMEMBER(_active)); - persistMgr->transfer(TMEMBER(_name)); - persistMgr->transfer(TMEMBER(_filename)); - persistMgr->transfer(TMEMBER(_cursor)); - persistMgr->transfer(TMEMBER(_alphaColor)); - for (int i = 0; i < 7; i++) { - persistMgr->transfer(TMEMBER(_caption[i])); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdNodeState::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 *AdNodeState::getCaption(int caseVal) { - if (caseVal == 0) { - caseVal = 1; - } - if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) { - return ""; - } else { - return _caption[caseVal - 1]; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdNodeState::transferEntity(AdEntity *entity, bool includingSprites, bool saving) { - if (!entity) { - return STATUS_FAILED; - } - - // HACK! - if (this->_gameRef != entity->_gameRef) { - this->_gameRef = entity->_gameRef; - } - - if (saving) { - for (int i = 0; i < 7; i++) { - if (entity->_caption[i]) { - setCaption(entity->_caption[i], i); - } - } - if (!entity->_region && entity->_sprite && entity->_sprite->getFilename()) { - if (includingSprites) { - setFilename(entity->_sprite->getFilename()); - } else { - setFilename(""); - } - } - if (entity->_cursor && entity->_cursor->getFilename()) { - setCursor(entity->_cursor->getFilename()); - } - _alphaColor = entity->_alphaColor; - _active = entity->_active; - } else { - for (int i = 0; i < 7; i++) { - if (_caption[i]) { - entity->setCaption(_caption[i], i); - } - } - if (_filename && !entity->_region && includingSprites && strcmp(_filename, "") != 0) { - if (!entity->_sprite || !entity->_sprite->getFilename() || scumm_stricmp(entity->_sprite->getFilename(), _filename) != 0) { - entity->setSprite(_filename); - } - } - if (_cursor) { - if (!entity->_cursor || !entity->_cursor->getFilename() || scumm_stricmp(entity->_cursor->getFilename(), _cursor) != 0) { - entity->setCursor(_cursor); - } - } - - entity->_active = _active; - entity->_alphaColor = _alphaColor; - } - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ad/ad_node_state.h" +#include "engines/wintermute/ad/ad_entity.h" +#include "engines/wintermute/base/base_string_table.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 { + +IMPLEMENT_PERSISTENT(AdNodeState, false) + + +////////////////////////////////////////////////////////////////////////// +AdNodeState::AdNodeState(BaseGame *inGame) : BaseClass(inGame) { + _name = NULL; + _active = false; + for (int i = 0; i < 7; i++) { + _caption[i] = NULL; + } + _alphaColor = 0; + _filename = NULL; + _cursor = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdNodeState::~AdNodeState() { + delete[] _name; + delete[] _filename; + delete[] _cursor; + _name = NULL; + _filename = NULL; + _cursor = NULL; + for (int i = 0; i < 7; i++) { + delete[] _caption[i]; + _caption[i] = NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdNodeState::setName(const char *name) { + delete[] _name; + _name = NULL; + BaseUtils::setString(&_name, name); +} + + +////////////////////////////////////////////////////////////////////////// +void AdNodeState::setFilename(const char *filename) { + delete[] _filename; + _filename = NULL; + BaseUtils::setString(&_filename, filename); +} + + +////////////////////////////////////////////////////////////////////////// +void AdNodeState::setCursor(const char *filename) { + delete[] _cursor; + _cursor = NULL; + BaseUtils::setString(&_cursor, filename); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdNodeState::persist(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER(_active)); + persistMgr->transfer(TMEMBER(_name)); + persistMgr->transfer(TMEMBER(_filename)); + persistMgr->transfer(TMEMBER(_cursor)); + persistMgr->transfer(TMEMBER(_alphaColor)); + for (int i = 0; i < 7; i++) { + persistMgr->transfer(TMEMBER(_caption[i])); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdNodeState::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 *AdNodeState::getCaption(int caseVal) { + if (caseVal == 0) { + caseVal = 1; + } + if (caseVal < 1 || caseVal > 7 || _caption[caseVal - 1] == NULL) { + return ""; + } else { + return _caption[caseVal - 1]; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdNodeState::transferEntity(AdEntity *entity, bool includingSprites, bool saving) { + if (!entity) { + return STATUS_FAILED; + } + + // HACK! + if (this->_gameRef != entity->_gameRef) { + this->_gameRef = entity->_gameRef; + } + + if (saving) { + for (int i = 0; i < 7; i++) { + if (entity->_caption[i]) { + setCaption(entity->_caption[i], i); + } + } + if (!entity->_region && entity->_sprite && entity->_sprite->getFilename()) { + if (includingSprites) { + setFilename(entity->_sprite->getFilename()); + } else { + setFilename(""); + } + } + if (entity->_cursor && entity->_cursor->getFilename()) { + setCursor(entity->_cursor->getFilename()); + } + _alphaColor = entity->_alphaColor; + _active = entity->_active; + } else { + for (int i = 0; i < 7; i++) { + if (_caption[i]) { + entity->setCaption(_caption[i], i); + } + } + if (_filename && !entity->_region && includingSprites && strcmp(_filename, "") != 0) { + if (!entity->_sprite || !entity->_sprite->getFilename() || scumm_stricmp(entity->_sprite->getFilename(), _filename) != 0) { + entity->setSprite(_filename); + } + } + if (_cursor) { + if (!entity->_cursor || !entity->_cursor->getFilename() || scumm_stricmp(entity->_cursor->getFilename(), _cursor) != 0) { + entity->setCursor(_cursor); + } + } + + entity->_active = _active; + entity->_alphaColor = _alphaColor; + } + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_node_state.h b/engines/wintermute/ad/ad_node_state.h index 0008d4b3ee70..e2050815a73c 100644 --- a/engines/wintermute/ad/ad_node_state.h +++ b/engines/wintermute/ad/ad_node_state.h @@ -1,60 +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_ADNODESTATE_H -#define WINTERMUTE_ADNODESTATE_H - -namespace Wintermute { - -class AdEntity; - -class AdNodeState : public BaseClass { -public: - bool _active; - bool transferEntity(AdEntity *entity, bool includingSprites, bool saving); - void setName(const char *name); - void setFilename(const char *filename); - void setCursor(const char *filename); - DECLARE_PERSISTENT(AdNodeState, BaseClass) - AdNodeState(BaseGame *inGame); - virtual ~AdNodeState(); - const char *getName() const { return _name; } -private: - char *_name; - char *_caption[7]; - void setCaption(const char *caption, int caseVal); - const char *getCaption(int caseVal); - uint32 _alphaColor; - char *_filename; - char *_cursor; - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADNODESTATE_H +#define WINTERMUTE_ADNODESTATE_H + +namespace Wintermute { + +class AdEntity; + +class AdNodeState : public BaseClass { +public: + bool _active; + bool transferEntity(AdEntity *entity, bool includingSprites, bool saving); + void setName(const char *name); + void setFilename(const char *filename); + void setCursor(const char *filename); + DECLARE_PERSISTENT(AdNodeState, BaseClass) + AdNodeState(BaseGame *inGame); + virtual ~AdNodeState(); + const char *getName() const { return _name; } +private: + char *_name; + char *_caption[7]; + void setCaption(const char *caption, int caseVal); + const char *getCaption(int caseVal); + uint32 _alphaColor; + char *_filename; + char *_cursor; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_object.cpp b/engines/wintermute/ad/ad_object.cpp index a02decebdbb7..6c779179791a 100644 --- a/engines/wintermute/ad/ad_object.cpp +++ b/engines/wintermute/ad/ad_object.cpp @@ -1,1299 +1,1299 @@ -/* 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/ad/ad_item.h" -#include "engines/wintermute/ad/ad_object.h" -#include "engines/wintermute/ad/ad_inventory.h" -#include "engines/wintermute/ad/ad_layer.h" -#include "engines/wintermute/ad/ad_scene.h" -#include "engines/wintermute/ad/ad_scene_node.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/ad/ad_waypoint_group.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_surface_storage.h" -#include "engines/wintermute/base/base_sub_frame.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/scriptables/script_engine.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/particles/part_emitter.h" -#include "common/str.h" -#include "common/util.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdObject, false) - -////////////////////////////////////////////////////////////////////////// -AdObject::AdObject(BaseGame *inGame) : BaseObject(inGame) { - _type = OBJECT_NONE; - _state = _nextState = STATE_NONE; - - _active = true; - _drawn = false; - - _currentSprite = NULL; - _animSprite = NULL; - _tempSprite2 = NULL; - - _font = NULL; - - _sentence = NULL; - - _forcedTalkAnimName = NULL; - _forcedTalkAnimUsed = false; - - _blockRegion = NULL; - _wptGroup = NULL; - - _currentBlockRegion = NULL; - _currentWptGroup = NULL; - - _ignoreItems = false; - _sceneIndependent = false; - - _stickRegion = NULL; - - _subtitlesModRelative = true; - _subtitlesModX = 0; - _subtitlesModY = 0; - _subtitlesWidth = 0; - _subtitlesModXCenter = true; - - _inventory = NULL; - - for (int i = 0; i < MAX_NUM_REGIONS; i++) { - _currentRegions[i] = NULL; - } - - _partEmitter = NULL; - _partFollowParent = false; - _partOffsetX = _partOffsetY = 0; - - _registerAlias = this; -} - - -////////////////////////////////////////////////////////////////////////// -AdObject::~AdObject() { - _currentSprite = NULL; // reference only, don't delete - delete _animSprite; - _animSprite = NULL; - delete _sentence; - _sentence = NULL; - delete[] _forcedTalkAnimName; - _forcedTalkAnimName = NULL; - - delete _blockRegion; - _blockRegion = NULL; - delete _wptGroup; - _wptGroup = NULL; - - delete _currentBlockRegion; - _currentBlockRegion = NULL; - delete _currentWptGroup; - _currentWptGroup = NULL; - - _tempSprite2 = NULL; // reference only - _stickRegion = NULL; - - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - - if (_inventory) { - ((AdGame *)_gameRef)->unregisterInventory(_inventory); - _inventory = NULL; - } - - if (_partEmitter) { - _gameRef->unregisterObject(_partEmitter); - } - - - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - _gameRef->unregisterObject(_attachmentsPre[i]); - } - _attachmentsPre.clear(); - - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - _gameRef->unregisterObject(_attachmentsPost[i]); - } - _attachmentsPost.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::playAnim(const char *filename) { - delete _animSprite; - _animSprite = NULL; - _animSprite = new BaseSprite(_gameRef, this); - if (!_animSprite) { - _gameRef->LOG(0, "AdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); - return STATUS_FAILED; - } - bool res = _animSprite->loadFile(filename); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "AdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); - delete _animSprite; - _animSprite = NULL; - return res; - } - _state = STATE_PLAYING_ANIM; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::display() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::update() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - - ////////////////////////////////////////////////////////////////////////// - // PlayAnim / PlayAnimAsync - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "PlayAnim") == 0 || strcmp(name, "PlayAnimAsync") == 0) { - stack->correctParams(1); - if (DID_FAIL(playAnim(stack->pop()->getString()))) { - stack->pushBool(false); - } else { - if (strcmp(name, "PlayAnimAsync") != 0) { - script->waitFor(this); - } - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Reset - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Reset") == 0) { - stack->correctParams(0); - reset(); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsTalking - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsTalking") == 0) { - stack->correctParams(0); - stack->pushBool(_state == STATE_TALKING); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // StopTalk / StopTalking - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StopTalk") == 0 || strcmp(name, "StopTalking") == 0) { - stack->correctParams(0); - if (_sentence) { - _sentence->finish(); - } - if (_state == STATE_TALKING) { - _state = _nextState; - _nextState = STATE_READY; - stack->pushBool(true); - } else { - stack->pushBool(false); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ForceTalkAnim - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ForceTalkAnim") == 0) { - stack->correctParams(1); - const char *animName = stack->pop()->getString(); - delete[] _forcedTalkAnimName; - _forcedTalkAnimName = new char[strlen(animName) + 1]; - strcpy(_forcedTalkAnimName, animName); - _forcedTalkAnimUsed = false; - stack->pushBool(true); - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // Talk / TalkAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Talk") == 0 || strcmp(name, "TalkAsync") == 0) { - stack->correctParams(5); - - const char *text = stack->pop()->getString(); - ScValue *soundVal = stack->pop(); - int duration = stack->pop()->getInt(); - ScValue *valStances = stack->pop(); - - const char *stances = valStances->isNULL() ? NULL : valStances->getString(); - - int align = 0; - ScValue *val = stack->pop(); - if (val->isNULL()) { - align = TAL_CENTER; - } else { - align = val->getInt(); - } - - align = MIN(MAX(0, align), NUM_TEXT_ALIGN - 1); - - const char *sound = soundVal->isNULL() ? NULL : soundVal->getString(); - - talk(text, sound, duration, stances, (TTextAlign)align); - if (strcmp(name, "TalkAsync") != 0) { - script->waitForExclusive(this); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // StickToRegion - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "StickToRegion") == 0) { - stack->correctParams(1); - - AdLayer *main = ((AdGame *)_gameRef)->_scene->_mainLayer; - bool regFound = false; - - uint32 i; - ScValue *val = stack->pop(); - if (val->isNULL() || !main) { - _stickRegion = NULL; - regFound = true; - } else if (val->isString()) { - const char *regionName = val->getString(); - for (i = 0; i < main->_nodes.size(); i++) { - if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region->getName() && scumm_stricmp(main->_nodes[i]->_region->getName(), regionName) == 0) { - _stickRegion = main->_nodes[i]->_region; - regFound = true; - break; - } - } - } else if (val->isNative()) { - BaseScriptable *obj = val->getNative(); - - for (i = 0; i < main->_nodes.size(); i++) { - if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region == obj) { - _stickRegion = main->_nodes[i]->_region; - regFound = true; - break; - } - } - - } - - if (!regFound) { - _stickRegion = NULL; - } - stack->pushBool(regFound); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (val->isNULL()) { - setFont(NULL); - } else { - setFont(val->getString()); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetFont") == 0) { - stack->correctParams(0); - if (_font && _font->getFilename()) { - stack->pushString(_font->getFilename()); - } else { - stack->pushNULL(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // TakeItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TakeItem") == 0) { - stack->correctParams(2); - - if (!_inventory) { - _inventory = new AdInventory(_gameRef); - ((AdGame *)_gameRef)->registerInventory(_inventory); - } - - ScValue *val = stack->pop(); - if (!val->isNULL()) { - const char *itemName = val->getString(); - val = stack->pop(); - const char *insertAfter = val->isNULL() ? NULL : val->getString(); - if (DID_FAIL(_inventory->insertItem(itemName, insertAfter))) { - script->runtimeError("Cannot add item '%s' to inventory", itemName); - } else { - // hide associated entities - ((AdGame *)_gameRef)->_scene->handleItemAssociations(itemName, false); - } - - } else { - script->runtimeError("TakeItem: item name expected"); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DropItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DropItem") == 0) { - stack->correctParams(1); - - if (!_inventory) { - _inventory = new AdInventory(_gameRef); - ((AdGame *)_gameRef)->registerInventory(_inventory); - } - - ScValue *val = stack->pop(); - if (!val->isNULL()) { - if (DID_FAIL(_inventory->removeItem(val->getString()))) { - script->runtimeError("Cannot remove item '%s' from inventory", val->getString()); - } else { - // show associated entities - ((AdGame *)_gameRef)->_scene->handleItemAssociations(val->getString(), true); - } - } else { - script->runtimeError("DropItem: item name expected"); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetItem") == 0) { - stack->correctParams(1); - - if (!_inventory) { - _inventory = new AdInventory(_gameRef); - ((AdGame *)_gameRef)->registerInventory(_inventory); - } - - ScValue *val = stack->pop(); - if (val->_type == VAL_STRING) { - AdItem *item = ((AdGame *)_gameRef)->getItemByName(val->getString()); - if (item) { - stack->pushNative(item, true); - } else { - stack->pushNULL(); - } - } else if (val->isNULL() || val->getInt() < 0 || val->getInt() >= (int32)_inventory->_takenItems.size()) { - stack->pushNULL(); - } else { - stack->pushNative(_inventory->_takenItems[val->getInt()], true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // HasItem - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "HasItem") == 0) { - stack->correctParams(1); - - if (!_inventory) { - _inventory = new AdInventory(_gameRef); - ((AdGame *)_gameRef)->registerInventory(_inventory); - } - - ScValue *val = stack->pop(); - if (!val->isNULL()) { - for (uint32 i = 0; i < _inventory->_takenItems.size(); i++) { - if (val->getNative() == _inventory->_takenItems[i]) { - stack->pushBool(true); - return STATUS_OK; - } else if (scumm_stricmp(val->getString(), _inventory->_takenItems[i]->getName()) == 0) { - stack->pushBool(true); - return STATUS_OK; - } - } - } else { - script->runtimeError("HasItem: item name expected"); - } - - stack->pushBool(false); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateParticleEmitter - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateParticleEmitter") == 0) { - stack->correctParams(3); - bool followParent = stack->pop()->getBool(); - int offsetX = stack->pop()->getInt(); - int offsetY = stack->pop()->getInt(); - - PartEmitter *emitter = createParticleEmitter(followParent, offsetX, offsetY); - if (emitter) { - stack->pushNative(_partEmitter, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteParticleEmitter - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteParticleEmitter") == 0) { - stack->correctParams(0); - if (_partEmitter) { - _gameRef->unregisterObject(_partEmitter); - _partEmitter = NULL; - } - stack->pushNULL(); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddAttachment - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddAttachment") == 0) { - stack->correctParams(4); - const char *filename = stack->pop()->getString(); - bool preDisplay = stack->pop()->getBool(true); - int offsetX = stack->pop()->getInt(); - int offsetY = stack->pop()->getInt(); - - bool res; - AdEntity *ent = new AdEntity(_gameRef); - if (DID_FAIL(res = ent->loadFile(filename))) { - delete ent; - ent = NULL; - script->runtimeError("AddAttachment() failed loading entity '%s'", filename); - stack->pushBool(false); - } else { - _gameRef->registerObject(ent); - - ent->_posX = offsetX; - ent->_posY = offsetY; - ent->_active = true; - - if (preDisplay) { - _attachmentsPre.add(ent); - } else { - _attachmentsPost.add(ent); - } - - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // RemoveAttachment - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "RemoveAttachment") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - bool found = false; - if (val->isNative()) { - BaseScriptable *obj = val->getNative(); - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - if (_attachmentsPre[i] == obj) { - found = true; - _gameRef->unregisterObject(_attachmentsPre[i]); - _attachmentsPre.remove_at(i); - i--; - } - } - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - if (_attachmentsPost[i] == obj) { - found = true; - _gameRef->unregisterObject(_attachmentsPost[i]); - _attachmentsPost.remove_at(i); - i--; - } - } - } else { - const char *attachmentName = val->getString(); - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { - found = true; - _gameRef->unregisterObject(_attachmentsPre[i]); - _attachmentsPre.remove_at(i); - i--; - } - } - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { - found = true; - _gameRef->unregisterObject(_attachmentsPost[i]); - _attachmentsPost.remove_at(i); - i--; - } - } - } - stack->pushBool(found); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetAttachment - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetAttachment") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdObject *ret = NULL; - if (val->isInt()) { - int index = val->getInt(); - int currIndex = 0; - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - if (currIndex == index) { - ret = _attachmentsPre[i]; - } - currIndex++; - } - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - if (currIndex == index) { - ret = _attachmentsPost[i]; - } - currIndex++; - } - } else { - const char *attachmentName = val->getString(); - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { - ret = _attachmentsPre[i]; - break; - } - } - if (!ret) { - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { - ret = _attachmentsPre[i]; - break; - } - } - } - } - - if (ret != NULL) { - stack->pushNative(ret, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } else { - return BaseObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdObject::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("object"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Active") == 0) { - _scValue->setBool(_active); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // IgnoreItems - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IgnoreItems") == 0) { - _scValue->setBool(_ignoreItems); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SceneIndependent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SceneIndependent") == 0) { - _scValue->setBool(_sceneIndependent); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesWidth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesWidth") == 0) { - _scValue->setInt(_subtitlesWidth); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosRelative - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosRelative") == 0) { - _scValue->setBool(_subtitlesModRelative); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosX") == 0) { - _scValue->setInt(_subtitlesModX); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosY") == 0) { - _scValue->setInt(_subtitlesModY); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosXCenter - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosXCenter") == 0) { - _scValue->setBool(_subtitlesModXCenter); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumItems (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumItems") == 0) { - _scValue->setInt(getInventory()->_takenItems.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ParticleEmitter (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ParticleEmitter") == 0) { - if (_partEmitter) { - _scValue->setNative(_partEmitter, true); - } else { - _scValue->setNULL(); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumAttachments (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumAttachments") == 0) { - _scValue->setInt(_attachmentsPre.size() + _attachmentsPost.size()); - return _scValue; - } else { - return BaseObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::scSetProperty(const char *name, ScValue *value) { - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Active") == 0) { - _active = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IgnoreItems - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IgnoreItems") == 0) { - _ignoreItems = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SceneIndependent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SceneIndependent") == 0) { - _sceneIndependent = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesWidth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesWidth") == 0) { - _subtitlesWidth = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosRelative - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosRelative") == 0) { - _subtitlesModRelative = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosX") == 0) { - _subtitlesModX = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosY") == 0) { - _subtitlesModY = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SubtitlesPosXCenter - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SubtitlesPosXCenter") == 0) { - _subtitlesModXCenter = value->getBool(); - return STATUS_OK; - } else { - return BaseObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdObject::scToString() { - return "[ad object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::setFont(const char *filename) { - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - if (filename) { - _font = _gameRef->_fontStorage->addFont(filename); - return _font == NULL ? STATUS_FAILED : STATUS_OK; - } else { - _font = NULL; - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -int AdObject::getHeight() { - if (!_currentSprite) { - return 0; - } else { - BaseFrame *frame = _currentSprite->_frames[_currentSprite->_currentFrame]; - int ret = 0; - for (uint32 i = 0; i < frame->_subframes.size(); i++) { - ret = MAX(ret, frame->_subframes[i]->_hotspotY); - } - - if (_zoomable) { - float zoom = ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY); - ret = (int)(ret * zoom / 100); - } - return ret; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdObject::talk(const char *text, const char *sound, uint32 duration, const char *stances, TTextAlign Align) { - if (!_sentence) { - _sentence = new AdSentence(_gameRef); - } - if (!_sentence) { - return; - } - - if (_forcedTalkAnimName && _forcedTalkAnimUsed) { - delete[] _forcedTalkAnimName; - _forcedTalkAnimName = NULL; - _forcedTalkAnimUsed = false; - } - - delete(_sentence->_sound); - _sentence->_sound = NULL; - - _sentence->setText(text); - _gameRef->_stringTable->expand(&_sentence->_text); - _sentence->setStances(stances); - _sentence->_duration = duration; - _sentence->_align = Align; - _sentence->_startTime = _gameRef->_timer; - _sentence->_currentStance = -1; - _sentence->_font = _font == NULL ? _gameRef->_systemFont : _font; - _sentence->_freezable = _freezable; - - // try to locate speech file automatically - bool deleteSound = false; - if (!sound) { - char *key = _gameRef->_stringTable->getKey(text); - if (key) { - sound = ((AdGame *)_gameRef)->findSpeechFile(key); - delete[] key; - - if (sound) { - deleteSound = true; - } - } - } - - // load sound and set duration appropriately - if (sound) { - BaseSound *snd = new BaseSound(_gameRef); - if (snd && DID_SUCCEED(snd->setSound(sound, Audio::Mixer::kSpeechSoundType, true))) { - _sentence->setSound(snd); - if (_sentence->_duration <= 0) { - uint32 length = snd->getLength(); - if (length != 0) { - _sentence->_duration = length; - } - } - } else { - delete snd; - } - } - - // set duration by text length - if (_sentence->_duration <= 0) {// TODO: Avoid longs. - _sentence->_duration = MAX((size_t)1000, _gameRef->_subtitlesSpeed * strlen(_sentence->_text)); - } - - - int x, y, width, height; - - x = _posX; - y = _posY; - - if (!_sceneIndependent && _subtitlesModRelative) { - x -= ((AdGame *)_gameRef)->_scene->getOffsetLeft(); - y -= ((AdGame *)_gameRef)->_scene->getOffsetTop(); - } - - - if (_subtitlesWidth > 0) { - width = _subtitlesWidth; - } else { - if ((x < _gameRef->_renderer->_width / 4 || x > _gameRef->_renderer->_width * 0.75) && !_gameRef->_touchInterface) { - width = MAX(_gameRef->_renderer->_width / 4, MIN(x * 2, (_gameRef->_renderer->_width - x) * 2)); - } else { - width = _gameRef->_renderer->_width / 2; - } - } - - height = _sentence->_font->getTextHeight((byte *)_sentence->_text, width); - - y = y - height - getHeight() - 5; - if (_subtitlesModRelative) { - x += _subtitlesModX; - y += _subtitlesModY; - } else { - x = _subtitlesModX; - y = _subtitlesModY; - } - if (_subtitlesModXCenter) { - x = x - width / 2; - } - - - x = MIN(MAX(0, x), _gameRef->_renderer->_width - width); - y = MIN(MAX(0, y), _gameRef->_renderer->_height - height); - - _sentence->_width = width; - - - _sentence->_pos.x = x; - _sentence->_pos.y = y; - - - if (_subtitlesModRelative) { - _sentence->_pos.x += ((AdGame *)_gameRef)->_scene->getOffsetLeft(); - _sentence->_pos.y += ((AdGame *)_gameRef)->_scene->getOffsetTop(); - } - - _sentence->_fixedPos = !_subtitlesModRelative; - - - _sentence->setupTalkFile(sound); - - _state = STATE_TALKING; - - if (deleteSound) { - delete[] sound; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::reset() { - if (_state == STATE_PLAYING_ANIM && _animSprite != NULL) { - delete _animSprite; - _animSprite = NULL; - } else if (_state == STATE_TALKING && _sentence) { - _sentence->finish(); - } - - _state = _nextState = STATE_READY; - - _gameRef->_scEngine->resetObject(this); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::persist(BasePersistenceManager *persistMgr) { - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_active)); - persistMgr->transfer(TMEMBER(_blockRegion)); - persistMgr->transfer(TMEMBER(_currentBlockRegion)); - persistMgr->transfer(TMEMBER(_currentWptGroup)); - persistMgr->transfer(TMEMBER(_currentSprite)); - persistMgr->transfer(TMEMBER(_drawn)); - persistMgr->transfer(TMEMBER(_font)); - persistMgr->transfer(TMEMBER(_ignoreItems)); - persistMgr->transfer(TMEMBER_INT(_nextState)); - persistMgr->transfer(TMEMBER(_sentence)); - persistMgr->transfer(TMEMBER_INT(_state)); - persistMgr->transfer(TMEMBER(_animSprite)); - persistMgr->transfer(TMEMBER(_sceneIndependent)); - persistMgr->transfer(TMEMBER(_forcedTalkAnimName)); - persistMgr->transfer(TMEMBER(_forcedTalkAnimUsed)); - persistMgr->transfer(TMEMBER(_tempSprite2)); - persistMgr->transfer(TMEMBER_INT(_type)); - persistMgr->transfer(TMEMBER(_wptGroup)); - persistMgr->transfer(TMEMBER(_stickRegion)); - persistMgr->transfer(TMEMBER(_subtitlesModRelative)); - persistMgr->transfer(TMEMBER(_subtitlesModX)); - persistMgr->transfer(TMEMBER(_subtitlesModY)); - persistMgr->transfer(TMEMBER(_subtitlesModXCenter)); - persistMgr->transfer(TMEMBER(_subtitlesWidth)); - persistMgr->transfer(TMEMBER(_inventory)); - persistMgr->transfer(TMEMBER(_partEmitter)); - - for (int i = 0; i < MAX_NUM_REGIONS; i++) { - persistMgr->transfer(TMEMBER(_currentRegions[i])); - } - - _attachmentsPre.persist(persistMgr); - _attachmentsPost.persist(persistMgr); - persistMgr->transfer(TMEMBER(_registerAlias)); - - persistMgr->transfer(TMEMBER(_partFollowParent)); - persistMgr->transfer(TMEMBER(_partOffsetX)); - persistMgr->transfer(TMEMBER(_partOffsetY)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::updateSounds() { - if (_sentence && _sentence->_sound) { - updateOneSound(_sentence->_sound); - } - - return BaseObject::updateSounds(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::resetSoundPan() { - if (_sentence && _sentence->_sound) { - _sentence->_sound->setPan(0.0f); - } - return BaseObject::resetSoundPan(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::getExtendedFlag(const char *flagName) { - if (!flagName) { - return false; - } else if (strcmp(flagName, "usable") == 0) { - return true; - } else { - return BaseObject::getExtendedFlag(flagName); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::saveAsText(BaseDynamicBuffer *buffer, int indent) { - if (_blockRegion) { - _blockRegion->saveAsText(buffer, indent + 2, "BLOCKED_REGION"); - } - if (_wptGroup) { - _wptGroup->saveAsText(buffer, indent + 2); - } - - BaseClass::saveAsText(buffer, indent + 2); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::updateBlockRegion() { - AdGame *adGame = (AdGame *)_gameRef; - if (adGame->_scene) { - if (_blockRegion && _currentBlockRegion) { - _currentBlockRegion->mimic(_blockRegion, _zoomable ? adGame->_scene->getScaleAt(_posY) : 100.0f, _posX, _posY); - } - - if (_wptGroup && _currentWptGroup) { - _currentWptGroup->mimic(_wptGroup, _zoomable ? adGame->_scene->getScaleAt(_posY) : 100.0f, _posX, _posY); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -AdInventory *AdObject::getInventory() { - if (!_inventory) { - _inventory = new AdInventory(_gameRef); - ((AdGame *)_gameRef)->registerInventory(_inventory); - } - return _inventory; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::afterMove() { - AdRegion *newRegions[MAX_NUM_REGIONS]; - - ((AdGame *)_gameRef)->_scene->getRegionsAt(_posX, _posY, newRegions, MAX_NUM_REGIONS); - for (int i = 0; i < MAX_NUM_REGIONS; i++) { - if (!newRegions[i]) { - break; - } - bool regFound = false; - for (int j = 0; j < MAX_NUM_REGIONS; j++) { - if (_currentRegions[j] == newRegions[i]) { - _currentRegions[j] = NULL; - regFound = true; - break; - } - } - if (!regFound) { - newRegions[i]->applyEvent("ActorEntry"); - } - } - - for (int i = 0; i < MAX_NUM_REGIONS; i++) { - if (_currentRegions[i] && _gameRef->validObject(_currentRegions[i])) { - _currentRegions[i]->applyEvent("ActorLeave"); - } - _currentRegions[i] = newRegions[i]; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdObject::invalidateCurrRegions() { - for (int i = 0; i < MAX_NUM_REGIONS; i++) { - _currentRegions[i] = NULL; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdObject::getScale(float *scaleX, float *scaleY) { - if (_zoomable) { - if (_scaleX >= 0 || _scaleY >= 0) { - *scaleX = _scaleX < 0 ? 100 : _scaleX; - *scaleY = _scaleY < 0 ? 100 : _scaleY; - } else if (_scale >= 0) { - *scaleX = *scaleY = _scale; - } else { - *scaleX = *scaleY = ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) + _relativeScale; - } - } else { - *scaleX = *scaleY = 100; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdObject::updateSpriteAttachments() { - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - _attachmentsPre[i]->update(); - } - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - _attachmentsPost[i]->update(); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdObject::displaySpriteAttachments(bool preDisplay) { - if (preDisplay) { - for (uint32 i = 0; i < _attachmentsPre.size(); i++) { - displaySpriteAttachment(_attachmentsPre[i]); - } - } else { - for (uint32 i = 0; i < _attachmentsPost.size(); i++) { - displaySpriteAttachment(_attachmentsPost[i]); - } - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdObject::displaySpriteAttachment(AdObject *attachment) { - if (!attachment->_active) { - return STATUS_OK; - } - - float scaleX, scaleY; - getScale(&scaleX, &scaleY); - - int origX = attachment->_posX; - int origY = attachment->_posY; - - // inherit position from owner - attachment->_posX = (int)(this->_posX + attachment->_posX * scaleX / 100.0f); - attachment->_posY = (int)(this->_posY + attachment->_posY * scaleY / 100.0f); - - // inherit other props - attachment->_alphaColor = this->_alphaColor; - attachment->_blendMode = this->_blendMode; - - attachment->_scale = this->_scale; - attachment->_relativeScale = this->_relativeScale; - attachment->_scaleX = this->_scaleX; - attachment->_scaleY = this->_scaleY; - - attachment->_rotate = this->_rotate; - attachment->_relativeRotate = this->_relativeRotate; - attachment->_rotateValid = this->_rotateValid; - - attachment->_registerAlias = this; - attachment->_registrable = this->_registrable; - - bool ret = attachment->display(); - - attachment->_posX = origX; - attachment->_posY = origY; - - return ret; -} - -////////////////////////////////////////////////////////////////////////// -PartEmitter *AdObject::createParticleEmitter(bool followParent, int offsetX, int offsetY) { - _partFollowParent = followParent; - _partOffsetX = offsetX; - _partOffsetY = offsetY; - - if (!_partEmitter) { - _partEmitter = new PartEmitter(_gameRef, this); - if (_partEmitter) { - _gameRef->registerObject(_partEmitter); - } - } - updatePartEmitter(); - return _partEmitter; -} - -////////////////////////////////////////////////////////////////////////// -bool AdObject::updatePartEmitter() { - if (!_partEmitter) { - return STATUS_FAILED; - } - - if (_partFollowParent) { - float scaleX, scaleY; - getScale(&scaleX, &scaleY); - - _partEmitter->_posX = (int)(_posX + (scaleX / 100.0f) * _partOffsetX); - _partEmitter->_posY = (int)(_posY + (scaleY / 100.0f) * _partOffsetY); - } - return _partEmitter->update(); -} - -} // end of namespace Wintermute +/* 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/ad/ad_item.h" +#include "engines/wintermute/ad/ad_object.h" +#include "engines/wintermute/ad/ad_inventory.h" +#include "engines/wintermute/ad/ad_layer.h" +#include "engines/wintermute/ad/ad_scene.h" +#include "engines/wintermute/ad/ad_scene_node.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/ad/ad_waypoint_group.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_surface_storage.h" +#include "engines/wintermute/base/base_sub_frame.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/scriptables/script_engine.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/particles/part_emitter.h" +#include "common/str.h" +#include "common/util.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdObject, false) + +////////////////////////////////////////////////////////////////////////// +AdObject::AdObject(BaseGame *inGame) : BaseObject(inGame) { + _type = OBJECT_NONE; + _state = _nextState = STATE_NONE; + + _active = true; + _drawn = false; + + _currentSprite = NULL; + _animSprite = NULL; + _tempSprite2 = NULL; + + _font = NULL; + + _sentence = NULL; + + _forcedTalkAnimName = NULL; + _forcedTalkAnimUsed = false; + + _blockRegion = NULL; + _wptGroup = NULL; + + _currentBlockRegion = NULL; + _currentWptGroup = NULL; + + _ignoreItems = false; + _sceneIndependent = false; + + _stickRegion = NULL; + + _subtitlesModRelative = true; + _subtitlesModX = 0; + _subtitlesModY = 0; + _subtitlesWidth = 0; + _subtitlesModXCenter = true; + + _inventory = NULL; + + for (int i = 0; i < MAX_NUM_REGIONS; i++) { + _currentRegions[i] = NULL; + } + + _partEmitter = NULL; + _partFollowParent = false; + _partOffsetX = _partOffsetY = 0; + + _registerAlias = this; +} + + +////////////////////////////////////////////////////////////////////////// +AdObject::~AdObject() { + _currentSprite = NULL; // reference only, don't delete + delete _animSprite; + _animSprite = NULL; + delete _sentence; + _sentence = NULL; + delete[] _forcedTalkAnimName; + _forcedTalkAnimName = NULL; + + delete _blockRegion; + _blockRegion = NULL; + delete _wptGroup; + _wptGroup = NULL; + + delete _currentBlockRegion; + _currentBlockRegion = NULL; + delete _currentWptGroup; + _currentWptGroup = NULL; + + _tempSprite2 = NULL; // reference only + _stickRegion = NULL; + + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + + if (_inventory) { + ((AdGame *)_gameRef)->unregisterInventory(_inventory); + _inventory = NULL; + } + + if (_partEmitter) { + _gameRef->unregisterObject(_partEmitter); + } + + + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + _gameRef->unregisterObject(_attachmentsPre[i]); + } + _attachmentsPre.clear(); + + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + _gameRef->unregisterObject(_attachmentsPost[i]); + } + _attachmentsPost.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::playAnim(const char *filename) { + delete _animSprite; + _animSprite = NULL; + _animSprite = new BaseSprite(_gameRef, this); + if (!_animSprite) { + _gameRef->LOG(0, "AdObject::PlayAnim: error creating temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); + return STATUS_FAILED; + } + bool res = _animSprite->loadFile(filename); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "AdObject::PlayAnim: error loading temp sprite (object:\"%s\" sprite:\"%s\")", getName(), filename); + delete _animSprite; + _animSprite = NULL; + return res; + } + _state = STATE_PLAYING_ANIM; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::display() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::update() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + + ////////////////////////////////////////////////////////////////////////// + // PlayAnim / PlayAnimAsync + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "PlayAnim") == 0 || strcmp(name, "PlayAnimAsync") == 0) { + stack->correctParams(1); + if (DID_FAIL(playAnim(stack->pop()->getString()))) { + stack->pushBool(false); + } else { + if (strcmp(name, "PlayAnimAsync") != 0) { + script->waitFor(this); + } + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Reset + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Reset") == 0) { + stack->correctParams(0); + reset(); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsTalking + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsTalking") == 0) { + stack->correctParams(0); + stack->pushBool(_state == STATE_TALKING); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StopTalk / StopTalking + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StopTalk") == 0 || strcmp(name, "StopTalking") == 0) { + stack->correctParams(0); + if (_sentence) { + _sentence->finish(); + } + if (_state == STATE_TALKING) { + _state = _nextState; + _nextState = STATE_READY; + stack->pushBool(true); + } else { + stack->pushBool(false); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ForceTalkAnim + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ForceTalkAnim") == 0) { + stack->correctParams(1); + const char *animName = stack->pop()->getString(); + delete[] _forcedTalkAnimName; + _forcedTalkAnimName = new char[strlen(animName) + 1]; + strcpy(_forcedTalkAnimName, animName); + _forcedTalkAnimUsed = false; + stack->pushBool(true); + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // Talk / TalkAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Talk") == 0 || strcmp(name, "TalkAsync") == 0) { + stack->correctParams(5); + + const char *text = stack->pop()->getString(); + ScValue *soundVal = stack->pop(); + int duration = stack->pop()->getInt(); + ScValue *valStances = stack->pop(); + + const char *stances = valStances->isNULL() ? NULL : valStances->getString(); + + int align = 0; + ScValue *val = stack->pop(); + if (val->isNULL()) { + align = TAL_CENTER; + } else { + align = val->getInt(); + } + + align = MIN(MAX(0, align), NUM_TEXT_ALIGN - 1); + + const char *sound = soundVal->isNULL() ? NULL : soundVal->getString(); + + talk(text, sound, duration, stances, (TTextAlign)align); + if (strcmp(name, "TalkAsync") != 0) { + script->waitForExclusive(this); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // StickToRegion + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "StickToRegion") == 0) { + stack->correctParams(1); + + AdLayer *main = ((AdGame *)_gameRef)->_scene->_mainLayer; + bool regFound = false; + + uint32 i; + ScValue *val = stack->pop(); + if (val->isNULL() || !main) { + _stickRegion = NULL; + regFound = true; + } else if (val->isString()) { + const char *regionName = val->getString(); + for (i = 0; i < main->_nodes.size(); i++) { + if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region->getName() && scumm_stricmp(main->_nodes[i]->_region->getName(), regionName) == 0) { + _stickRegion = main->_nodes[i]->_region; + regFound = true; + break; + } + } + } else if (val->isNative()) { + BaseScriptable *obj = val->getNative(); + + for (i = 0; i < main->_nodes.size(); i++) { + if (main->_nodes[i]->_type == OBJECT_REGION && main->_nodes[i]->_region == obj) { + _stickRegion = main->_nodes[i]->_region; + regFound = true; + break; + } + } + + } + + if (!regFound) { + _stickRegion = NULL; + } + stack->pushBool(regFound); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (val->isNULL()) { + setFont(NULL); + } else { + setFont(val->getString()); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFont") == 0) { + stack->correctParams(0); + if (_font && _font->getFilename()) { + stack->pushString(_font->getFilename()); + } else { + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // TakeItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TakeItem") == 0) { + stack->correctParams(2); + + if (!_inventory) { + _inventory = new AdInventory(_gameRef); + ((AdGame *)_gameRef)->registerInventory(_inventory); + } + + ScValue *val = stack->pop(); + if (!val->isNULL()) { + const char *itemName = val->getString(); + val = stack->pop(); + const char *insertAfter = val->isNULL() ? NULL : val->getString(); + if (DID_FAIL(_inventory->insertItem(itemName, insertAfter))) { + script->runtimeError("Cannot add item '%s' to inventory", itemName); + } else { + // hide associated entities + ((AdGame *)_gameRef)->_scene->handleItemAssociations(itemName, false); + } + + } else { + script->runtimeError("TakeItem: item name expected"); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DropItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DropItem") == 0) { + stack->correctParams(1); + + if (!_inventory) { + _inventory = new AdInventory(_gameRef); + ((AdGame *)_gameRef)->registerInventory(_inventory); + } + + ScValue *val = stack->pop(); + if (!val->isNULL()) { + if (DID_FAIL(_inventory->removeItem(val->getString()))) { + script->runtimeError("Cannot remove item '%s' from inventory", val->getString()); + } else { + // show associated entities + ((AdGame *)_gameRef)->_scene->handleItemAssociations(val->getString(), true); + } + } else { + script->runtimeError("DropItem: item name expected"); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetItem") == 0) { + stack->correctParams(1); + + if (!_inventory) { + _inventory = new AdInventory(_gameRef); + ((AdGame *)_gameRef)->registerInventory(_inventory); + } + + ScValue *val = stack->pop(); + if (val->_type == VAL_STRING) { + AdItem *item = ((AdGame *)_gameRef)->getItemByName(val->getString()); + if (item) { + stack->pushNative(item, true); + } else { + stack->pushNULL(); + } + } else if (val->isNULL() || val->getInt() < 0 || val->getInt() >= (int32)_inventory->_takenItems.size()) { + stack->pushNULL(); + } else { + stack->pushNative(_inventory->_takenItems[val->getInt()], true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HasItem + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HasItem") == 0) { + stack->correctParams(1); + + if (!_inventory) { + _inventory = new AdInventory(_gameRef); + ((AdGame *)_gameRef)->registerInventory(_inventory); + } + + ScValue *val = stack->pop(); + if (!val->isNULL()) { + for (uint32 i = 0; i < _inventory->_takenItems.size(); i++) { + if (val->getNative() == _inventory->_takenItems[i]) { + stack->pushBool(true); + return STATUS_OK; + } else if (scumm_stricmp(val->getString(), _inventory->_takenItems[i]->getName()) == 0) { + stack->pushBool(true); + return STATUS_OK; + } + } + } else { + script->runtimeError("HasItem: item name expected"); + } + + stack->pushBool(false); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateParticleEmitter + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateParticleEmitter") == 0) { + stack->correctParams(3); + bool followParent = stack->pop()->getBool(); + int offsetX = stack->pop()->getInt(); + int offsetY = stack->pop()->getInt(); + + PartEmitter *emitter = createParticleEmitter(followParent, offsetX, offsetY); + if (emitter) { + stack->pushNative(_partEmitter, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteParticleEmitter + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteParticleEmitter") == 0) { + stack->correctParams(0); + if (_partEmitter) { + _gameRef->unregisterObject(_partEmitter); + _partEmitter = NULL; + } + stack->pushNULL(); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddAttachment + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddAttachment") == 0) { + stack->correctParams(4); + const char *filename = stack->pop()->getString(); + bool preDisplay = stack->pop()->getBool(true); + int offsetX = stack->pop()->getInt(); + int offsetY = stack->pop()->getInt(); + + bool res; + AdEntity *ent = new AdEntity(_gameRef); + if (DID_FAIL(res = ent->loadFile(filename))) { + delete ent; + ent = NULL; + script->runtimeError("AddAttachment() failed loading entity '%s'", filename); + stack->pushBool(false); + } else { + _gameRef->registerObject(ent); + + ent->_posX = offsetX; + ent->_posY = offsetY; + ent->_active = true; + + if (preDisplay) { + _attachmentsPre.add(ent); + } else { + _attachmentsPost.add(ent); + } + + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveAttachment + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveAttachment") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + bool found = false; + if (val->isNative()) { + BaseScriptable *obj = val->getNative(); + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + if (_attachmentsPre[i] == obj) { + found = true; + _gameRef->unregisterObject(_attachmentsPre[i]); + _attachmentsPre.remove_at(i); + i--; + } + } + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + if (_attachmentsPost[i] == obj) { + found = true; + _gameRef->unregisterObject(_attachmentsPost[i]); + _attachmentsPost.remove_at(i); + i--; + } + } + } else { + const char *attachmentName = val->getString(); + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { + found = true; + _gameRef->unregisterObject(_attachmentsPre[i]); + _attachmentsPre.remove_at(i); + i--; + } + } + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { + found = true; + _gameRef->unregisterObject(_attachmentsPost[i]); + _attachmentsPost.remove_at(i); + i--; + } + } + } + stack->pushBool(found); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetAttachment + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetAttachment") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdObject *ret = NULL; + if (val->isInt()) { + int index = val->getInt(); + int currIndex = 0; + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + if (currIndex == index) { + ret = _attachmentsPre[i]; + } + currIndex++; + } + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + if (currIndex == index) { + ret = _attachmentsPost[i]; + } + currIndex++; + } + } else { + const char *attachmentName = val->getString(); + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + if (_attachmentsPre[i]->getName() && scumm_stricmp(_attachmentsPre[i]->getName(), attachmentName) == 0) { + ret = _attachmentsPre[i]; + break; + } + } + if (!ret) { + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + if (_attachmentsPost[i]->getName() && scumm_stricmp(_attachmentsPost[i]->getName(), attachmentName) == 0) { + ret = _attachmentsPre[i]; + break; + } + } + } + } + + if (ret != NULL) { + stack->pushNative(ret, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } else { + return BaseObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdObject::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("object"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Active") == 0) { + _scValue->setBool(_active); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // IgnoreItems + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IgnoreItems") == 0) { + _scValue->setBool(_ignoreItems); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SceneIndependent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SceneIndependent") == 0) { + _scValue->setBool(_sceneIndependent); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesWidth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesWidth") == 0) { + _scValue->setInt(_subtitlesWidth); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosRelative + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosRelative") == 0) { + _scValue->setBool(_subtitlesModRelative); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosX") == 0) { + _scValue->setInt(_subtitlesModX); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosY") == 0) { + _scValue->setInt(_subtitlesModY); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosXCenter + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosXCenter") == 0) { + _scValue->setBool(_subtitlesModXCenter); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumItems (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumItems") == 0) { + _scValue->setInt(getInventory()->_takenItems.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ParticleEmitter (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ParticleEmitter") == 0) { + if (_partEmitter) { + _scValue->setNative(_partEmitter, true); + } else { + _scValue->setNULL(); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumAttachments (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumAttachments") == 0) { + _scValue->setInt(_attachmentsPre.size() + _attachmentsPost.size()); + return _scValue; + } else { + return BaseObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::scSetProperty(const char *name, ScValue *value) { + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Active") == 0) { + _active = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IgnoreItems + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IgnoreItems") == 0) { + _ignoreItems = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SceneIndependent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SceneIndependent") == 0) { + _sceneIndependent = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesWidth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesWidth") == 0) { + _subtitlesWidth = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosRelative + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosRelative") == 0) { + _subtitlesModRelative = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosX") == 0) { + _subtitlesModX = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosY") == 0) { + _subtitlesModY = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SubtitlesPosXCenter + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SubtitlesPosXCenter") == 0) { + _subtitlesModXCenter = value->getBool(); + return STATUS_OK; + } else { + return BaseObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdObject::scToString() { + return "[ad object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::setFont(const char *filename) { + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + if (filename) { + _font = _gameRef->_fontStorage->addFont(filename); + return _font == NULL ? STATUS_FAILED : STATUS_OK; + } else { + _font = NULL; + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +int AdObject::getHeight() { + if (!_currentSprite) { + return 0; + } else { + BaseFrame *frame = _currentSprite->_frames[_currentSprite->_currentFrame]; + int ret = 0; + for (uint32 i = 0; i < frame->_subframes.size(); i++) { + ret = MAX(ret, frame->_subframes[i]->_hotspotY); + } + + if (_zoomable) { + float zoom = ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY); + ret = (int)(ret * zoom / 100); + } + return ret; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdObject::talk(const char *text, const char *sound, uint32 duration, const char *stances, TTextAlign Align) { + if (!_sentence) { + _sentence = new AdSentence(_gameRef); + } + if (!_sentence) { + return; + } + + if (_forcedTalkAnimName && _forcedTalkAnimUsed) { + delete[] _forcedTalkAnimName; + _forcedTalkAnimName = NULL; + _forcedTalkAnimUsed = false; + } + + delete(_sentence->_sound); + _sentence->_sound = NULL; + + _sentence->setText(text); + _gameRef->_stringTable->expand(&_sentence->_text); + _sentence->setStances(stances); + _sentence->_duration = duration; + _sentence->_align = Align; + _sentence->_startTime = _gameRef->_timer; + _sentence->_currentStance = -1; + _sentence->_font = _font == NULL ? _gameRef->_systemFont : _font; + _sentence->_freezable = _freezable; + + // try to locate speech file automatically + bool deleteSound = false; + if (!sound) { + char *key = _gameRef->_stringTable->getKey(text); + if (key) { + sound = ((AdGame *)_gameRef)->findSpeechFile(key); + delete[] key; + + if (sound) { + deleteSound = true; + } + } + } + + // load sound and set duration appropriately + if (sound) { + BaseSound *snd = new BaseSound(_gameRef); + if (snd && DID_SUCCEED(snd->setSound(sound, Audio::Mixer::kSpeechSoundType, true))) { + _sentence->setSound(snd); + if (_sentence->_duration <= 0) { + uint32 length = snd->getLength(); + if (length != 0) { + _sentence->_duration = length; + } + } + } else { + delete snd; + } + } + + // set duration by text length + if (_sentence->_duration <= 0) {// TODO: Avoid longs. + _sentence->_duration = MAX((size_t)1000, _gameRef->_subtitlesSpeed * strlen(_sentence->_text)); + } + + + int x, y, width, height; + + x = _posX; + y = _posY; + + if (!_sceneIndependent && _subtitlesModRelative) { + x -= ((AdGame *)_gameRef)->_scene->getOffsetLeft(); + y -= ((AdGame *)_gameRef)->_scene->getOffsetTop(); + } + + + if (_subtitlesWidth > 0) { + width = _subtitlesWidth; + } else { + if ((x < _gameRef->_renderer->_width / 4 || x > _gameRef->_renderer->_width * 0.75) && !_gameRef->_touchInterface) { + width = MAX(_gameRef->_renderer->_width / 4, MIN(x * 2, (_gameRef->_renderer->_width - x) * 2)); + } else { + width = _gameRef->_renderer->_width / 2; + } + } + + height = _sentence->_font->getTextHeight((byte *)_sentence->_text, width); + + y = y - height - getHeight() - 5; + if (_subtitlesModRelative) { + x += _subtitlesModX; + y += _subtitlesModY; + } else { + x = _subtitlesModX; + y = _subtitlesModY; + } + if (_subtitlesModXCenter) { + x = x - width / 2; + } + + + x = MIN(MAX(0, x), _gameRef->_renderer->_width - width); + y = MIN(MAX(0, y), _gameRef->_renderer->_height - height); + + _sentence->_width = width; + + + _sentence->_pos.x = x; + _sentence->_pos.y = y; + + + if (_subtitlesModRelative) { + _sentence->_pos.x += ((AdGame *)_gameRef)->_scene->getOffsetLeft(); + _sentence->_pos.y += ((AdGame *)_gameRef)->_scene->getOffsetTop(); + } + + _sentence->_fixedPos = !_subtitlesModRelative; + + + _sentence->setupTalkFile(sound); + + _state = STATE_TALKING; + + if (deleteSound) { + delete[] sound; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::reset() { + if (_state == STATE_PLAYING_ANIM && _animSprite != NULL) { + delete _animSprite; + _animSprite = NULL; + } else if (_state == STATE_TALKING && _sentence) { + _sentence->finish(); + } + + _state = _nextState = STATE_READY; + + _gameRef->_scEngine->resetObject(this); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_active)); + persistMgr->transfer(TMEMBER(_blockRegion)); + persistMgr->transfer(TMEMBER(_currentBlockRegion)); + persistMgr->transfer(TMEMBER(_currentWptGroup)); + persistMgr->transfer(TMEMBER(_currentSprite)); + persistMgr->transfer(TMEMBER(_drawn)); + persistMgr->transfer(TMEMBER(_font)); + persistMgr->transfer(TMEMBER(_ignoreItems)); + persistMgr->transfer(TMEMBER_INT(_nextState)); + persistMgr->transfer(TMEMBER(_sentence)); + persistMgr->transfer(TMEMBER_INT(_state)); + persistMgr->transfer(TMEMBER(_animSprite)); + persistMgr->transfer(TMEMBER(_sceneIndependent)); + persistMgr->transfer(TMEMBER(_forcedTalkAnimName)); + persistMgr->transfer(TMEMBER(_forcedTalkAnimUsed)); + persistMgr->transfer(TMEMBER(_tempSprite2)); + persistMgr->transfer(TMEMBER_INT(_type)); + persistMgr->transfer(TMEMBER(_wptGroup)); + persistMgr->transfer(TMEMBER(_stickRegion)); + persistMgr->transfer(TMEMBER(_subtitlesModRelative)); + persistMgr->transfer(TMEMBER(_subtitlesModX)); + persistMgr->transfer(TMEMBER(_subtitlesModY)); + persistMgr->transfer(TMEMBER(_subtitlesModXCenter)); + persistMgr->transfer(TMEMBER(_subtitlesWidth)); + persistMgr->transfer(TMEMBER(_inventory)); + persistMgr->transfer(TMEMBER(_partEmitter)); + + for (int i = 0; i < MAX_NUM_REGIONS; i++) { + persistMgr->transfer(TMEMBER(_currentRegions[i])); + } + + _attachmentsPre.persist(persistMgr); + _attachmentsPost.persist(persistMgr); + persistMgr->transfer(TMEMBER(_registerAlias)); + + persistMgr->transfer(TMEMBER(_partFollowParent)); + persistMgr->transfer(TMEMBER(_partOffsetX)); + persistMgr->transfer(TMEMBER(_partOffsetY)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::updateSounds() { + if (_sentence && _sentence->_sound) { + updateOneSound(_sentence->_sound); + } + + return BaseObject::updateSounds(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::resetSoundPan() { + if (_sentence && _sentence->_sound) { + _sentence->_sound->setPan(0.0f); + } + return BaseObject::resetSoundPan(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::getExtendedFlag(const char *flagName) { + if (!flagName) { + return false; + } else if (strcmp(flagName, "usable") == 0) { + return true; + } else { + return BaseObject::getExtendedFlag(flagName); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::saveAsText(BaseDynamicBuffer *buffer, int indent) { + if (_blockRegion) { + _blockRegion->saveAsText(buffer, indent + 2, "BLOCKED_REGION"); + } + if (_wptGroup) { + _wptGroup->saveAsText(buffer, indent + 2); + } + + BaseClass::saveAsText(buffer, indent + 2); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::updateBlockRegion() { + AdGame *adGame = (AdGame *)_gameRef; + if (adGame->_scene) { + if (_blockRegion && _currentBlockRegion) { + _currentBlockRegion->mimic(_blockRegion, _zoomable ? adGame->_scene->getScaleAt(_posY) : 100.0f, _posX, _posY); + } + + if (_wptGroup && _currentWptGroup) { + _currentWptGroup->mimic(_wptGroup, _zoomable ? adGame->_scene->getScaleAt(_posY) : 100.0f, _posX, _posY); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +AdInventory *AdObject::getInventory() { + if (!_inventory) { + _inventory = new AdInventory(_gameRef); + ((AdGame *)_gameRef)->registerInventory(_inventory); + } + return _inventory; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::afterMove() { + AdRegion *newRegions[MAX_NUM_REGIONS]; + + ((AdGame *)_gameRef)->_scene->getRegionsAt(_posX, _posY, newRegions, MAX_NUM_REGIONS); + for (int i = 0; i < MAX_NUM_REGIONS; i++) { + if (!newRegions[i]) { + break; + } + bool regFound = false; + for (int j = 0; j < MAX_NUM_REGIONS; j++) { + if (_currentRegions[j] == newRegions[i]) { + _currentRegions[j] = NULL; + regFound = true; + break; + } + } + if (!regFound) { + newRegions[i]->applyEvent("ActorEntry"); + } + } + + for (int i = 0; i < MAX_NUM_REGIONS; i++) { + if (_currentRegions[i] && _gameRef->validObject(_currentRegions[i])) { + _currentRegions[i]->applyEvent("ActorLeave"); + } + _currentRegions[i] = newRegions[i]; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdObject::invalidateCurrRegions() { + for (int i = 0; i < MAX_NUM_REGIONS; i++) { + _currentRegions[i] = NULL; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdObject::getScale(float *scaleX, float *scaleY) { + if (_zoomable) { + if (_scaleX >= 0 || _scaleY >= 0) { + *scaleX = _scaleX < 0 ? 100 : _scaleX; + *scaleY = _scaleY < 0 ? 100 : _scaleY; + } else if (_scale >= 0) { + *scaleX = *scaleY = _scale; + } else { + *scaleX = *scaleY = ((AdGame *)_gameRef)->_scene->getZoomAt(_posX, _posY) + _relativeScale; + } + } else { + *scaleX = *scaleY = 100; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdObject::updateSpriteAttachments() { + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + _attachmentsPre[i]->update(); + } + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + _attachmentsPost[i]->update(); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdObject::displaySpriteAttachments(bool preDisplay) { + if (preDisplay) { + for (uint32 i = 0; i < _attachmentsPre.size(); i++) { + displaySpriteAttachment(_attachmentsPre[i]); + } + } else { + for (uint32 i = 0; i < _attachmentsPost.size(); i++) { + displaySpriteAttachment(_attachmentsPost[i]); + } + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdObject::displaySpriteAttachment(AdObject *attachment) { + if (!attachment->_active) { + return STATUS_OK; + } + + float scaleX, scaleY; + getScale(&scaleX, &scaleY); + + int origX = attachment->_posX; + int origY = attachment->_posY; + + // inherit position from owner + attachment->_posX = (int)(this->_posX + attachment->_posX * scaleX / 100.0f); + attachment->_posY = (int)(this->_posY + attachment->_posY * scaleY / 100.0f); + + // inherit other props + attachment->_alphaColor = this->_alphaColor; + attachment->_blendMode = this->_blendMode; + + attachment->_scale = this->_scale; + attachment->_relativeScale = this->_relativeScale; + attachment->_scaleX = this->_scaleX; + attachment->_scaleY = this->_scaleY; + + attachment->_rotate = this->_rotate; + attachment->_relativeRotate = this->_relativeRotate; + attachment->_rotateValid = this->_rotateValid; + + attachment->_registerAlias = this; + attachment->_registrable = this->_registrable; + + bool ret = attachment->display(); + + attachment->_posX = origX; + attachment->_posY = origY; + + return ret; +} + +////////////////////////////////////////////////////////////////////////// +PartEmitter *AdObject::createParticleEmitter(bool followParent, int offsetX, int offsetY) { + _partFollowParent = followParent; + _partOffsetX = offsetX; + _partOffsetY = offsetY; + + if (!_partEmitter) { + _partEmitter = new PartEmitter(_gameRef, this); + if (_partEmitter) { + _gameRef->registerObject(_partEmitter); + } + } + updatePartEmitter(); + return _partEmitter; +} + +////////////////////////////////////////////////////////////////////////// +bool AdObject::updatePartEmitter() { + if (!_partEmitter) { + return STATUS_FAILED; + } + + if (_partFollowParent) { + float scaleX, scaleY; + getScale(&scaleX, &scaleY); + + _partEmitter->_posX = (int)(_posX + (scaleX / 100.0f) * _partOffsetX); + _partEmitter->_posY = (int)(_posY + (scaleY / 100.0f) * _partOffsetY); + } + return _partEmitter->update(); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_object.h b/engines/wintermute/ad/ad_object.h index 9451707445fa..8395f58cff90 100644 --- a/engines/wintermute/ad/ad_object.h +++ b/engines/wintermute/ad/ad_object.h @@ -1,124 +1,124 @@ -/* 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_ADOBJECT_H -#define WINTERMUTE_ADOBJECT_H - -#include "engines/wintermute/ad/ad_types.h" -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { - -class AdWaypointGroup; -class AdRegion; -class AdSentence; -class BaseFont; -class BaseRegion; -class AdInventory; -class PartEmitter; - -#define MAX_NUM_REGIONS 10 - -class AdObject : public BaseObject { -public: - PartEmitter *_partEmitter; - virtual PartEmitter *createParticleEmitter(bool followParent = false, int offsetX = 0, int offsetY = 0); - virtual bool updatePartEmitter(); - bool _partFollowParent; - int _partOffsetX; - int _partOffsetY; - - bool invalidateCurrRegions(); - bool _subtitlesModRelative; - bool _subtitlesModXCenter; - int _subtitlesModX; - int _subtitlesModY; - int _subtitlesWidth; - AdRegion *_stickRegion; - bool _sceneIndependent; - bool _ignoreItems; - bool updateBlockRegion(); - bool _forcedTalkAnimUsed; - char *_forcedTalkAnimName; - virtual bool getExtendedFlag(const char *flagName); - virtual bool resetSoundPan(); - virtual bool updateSounds(); - bool reset(); - DECLARE_PERSISTENT(AdObject, BaseObject) - virtual void talk(const char *text, const char *sound = NULL, uint32 duration = 0, const char *stances = NULL, TTextAlign align = TAL_CENTER); - virtual int getHeight(); - AdSentence *_sentence; - bool setFont(const char *filename); - virtual bool update(); - virtual bool display(); - bool _drawn; - bool _active; - virtual bool playAnim(const char *filename); - BaseSprite *_animSprite; - BaseSprite *_currentSprite; - TObjectState _state; - TObjectState _nextState; - TObjectType _type; - AdObject(BaseGame *inGame); - virtual ~AdObject(); - BaseFont *_font; - BaseSprite *_tempSprite2; - BaseRegion *_blockRegion; - AdWaypointGroup *_wptGroup; - BaseRegion *_currentBlockRegion; - AdWaypointGroup *_currentWptGroup; - AdInventory *getInventory(); - - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - - virtual bool afterMove(); - AdRegion *_currentRegions[MAX_NUM_REGIONS]; - - // 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(); - - BaseArray _attachmentsPre; - BaseArray _attachmentsPost; - - bool updateSpriteAttachments(); - bool displaySpriteAttachments(bool preDisplay); - AdObject *_registerAlias; -private: - bool displaySpriteAttachment(AdObject *attachment); - AdInventory *_inventory; - -protected: - bool getScale(float *scaleX, float *scaleY); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADOBJECT_H +#define WINTERMUTE_ADOBJECT_H + +#include "engines/wintermute/ad/ad_types.h" +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class AdWaypointGroup; +class AdRegion; +class AdSentence; +class BaseFont; +class BaseRegion; +class AdInventory; +class PartEmitter; + +#define MAX_NUM_REGIONS 10 + +class AdObject : public BaseObject { +public: + PartEmitter *_partEmitter; + virtual PartEmitter *createParticleEmitter(bool followParent = false, int offsetX = 0, int offsetY = 0); + virtual bool updatePartEmitter(); + bool _partFollowParent; + int _partOffsetX; + int _partOffsetY; + + bool invalidateCurrRegions(); + bool _subtitlesModRelative; + bool _subtitlesModXCenter; + int _subtitlesModX; + int _subtitlesModY; + int _subtitlesWidth; + AdRegion *_stickRegion; + bool _sceneIndependent; + bool _ignoreItems; + bool updateBlockRegion(); + bool _forcedTalkAnimUsed; + char *_forcedTalkAnimName; + virtual bool getExtendedFlag(const char *flagName); + virtual bool resetSoundPan(); + virtual bool updateSounds(); + bool reset(); + DECLARE_PERSISTENT(AdObject, BaseObject) + virtual void talk(const char *text, const char *sound = NULL, uint32 duration = 0, const char *stances = NULL, TTextAlign align = TAL_CENTER); + virtual int getHeight(); + AdSentence *_sentence; + bool setFont(const char *filename); + virtual bool update(); + virtual bool display(); + bool _drawn; + bool _active; + virtual bool playAnim(const char *filename); + BaseSprite *_animSprite; + BaseSprite *_currentSprite; + TObjectState _state; + TObjectState _nextState; + TObjectType _type; + AdObject(BaseGame *inGame); + virtual ~AdObject(); + BaseFont *_font; + BaseSprite *_tempSprite2; + BaseRegion *_blockRegion; + AdWaypointGroup *_wptGroup; + BaseRegion *_currentBlockRegion; + AdWaypointGroup *_currentWptGroup; + AdInventory *getInventory(); + + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + + virtual bool afterMove(); + AdRegion *_currentRegions[MAX_NUM_REGIONS]; + + // 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(); + + BaseArray _attachmentsPre; + BaseArray _attachmentsPost; + + bool updateSpriteAttachments(); + bool displaySpriteAttachments(bool preDisplay); + AdObject *_registerAlias; +private: + bool displaySpriteAttachment(AdObject *attachment); + AdInventory *_inventory; + +protected: + bool getScale(float *scaleX, float *scaleY); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_path.cpp b/engines/wintermute/ad/ad_path.cpp index 21b68f4d4827..c931213456cc 100644 --- a/engines/wintermute/ad/ad_path.cpp +++ b/engines/wintermute/ad/ad_path.cpp @@ -1,120 +1,120 @@ -/* 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_path.h" -#include "engines/wintermute/base/base_point.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdPath, false) - -////////////////////////////////////////////////////////////////////////// -AdPath::AdPath(BaseGame *inGame) : BaseClass(inGame) { - _currIndex = -1; - _ready = false; -} - - -////////////////////////////////////////////////////////////////////////// -AdPath::~AdPath() { - reset(); -} - - -////////////////////////////////////////////////////////////////////////// -void AdPath::reset() { - for (uint32 i = 0; i < _points.size(); i++) { - delete _points[i]; - } - - _points.clear(); - _currIndex = -1; - _ready = false; -} - - -////////////////////////////////////////////////////////////////////////// -BasePoint *AdPath::getFirst() { - if (_points.size() > 0) { - _currIndex = 0; - return _points[_currIndex]; - } else { - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -BasePoint *AdPath::getNext() { - _currIndex++; - if (_currIndex < (int32)_points.size()) { - return _points[_currIndex]; - } else { - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -BasePoint *AdPath::getCurrent() { - if (_currIndex >= 0 && _currIndex < (int32)_points.size()) { - return _points[_currIndex]; - } else { - return NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdPath::addPoint(BasePoint *point) { - _points.add(point); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdPath::setReady(bool ready) { - bool orig = _ready; - _ready = ready; - - return orig; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdPath::persist(BasePersistenceManager *persistMgr) { - - persistMgr->transfer(TMEMBER(_gameRef)); - - persistMgr->transfer(TMEMBER(_currIndex)); - _points.persist(persistMgr); - persistMgr->transfer(TMEMBER(_ready)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_path.h" +#include "engines/wintermute/base/base_point.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdPath, false) + +////////////////////////////////////////////////////////////////////////// +AdPath::AdPath(BaseGame *inGame) : BaseClass(inGame) { + _currIndex = -1; + _ready = false; +} + + +////////////////////////////////////////////////////////////////////////// +AdPath::~AdPath() { + reset(); +} + + +////////////////////////////////////////////////////////////////////////// +void AdPath::reset() { + for (uint32 i = 0; i < _points.size(); i++) { + delete _points[i]; + } + + _points.clear(); + _currIndex = -1; + _ready = false; +} + + +////////////////////////////////////////////////////////////////////////// +BasePoint *AdPath::getFirst() { + if (_points.size() > 0) { + _currIndex = 0; + return _points[_currIndex]; + } else { + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +BasePoint *AdPath::getNext() { + _currIndex++; + if (_currIndex < (int32)_points.size()) { + return _points[_currIndex]; + } else { + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +BasePoint *AdPath::getCurrent() { + if (_currIndex >= 0 && _currIndex < (int32)_points.size()) { + return _points[_currIndex]; + } else { + return NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdPath::addPoint(BasePoint *point) { + _points.add(point); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdPath::setReady(bool ready) { + bool orig = _ready; + _ready = ready; + + return orig; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdPath::persist(BasePersistenceManager *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER(_currIndex)); + _points.persist(persistMgr); + persistMgr->transfer(TMEMBER(_ready)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_path.h b/engines/wintermute/ad/ad_path.h index de115b261aba..6b043197aa0f 100644 --- a/engines/wintermute/ad/ad_path.h +++ b/engines/wintermute/ad/ad_path.h @@ -1,56 +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_ADPATH_H -#define WINTERMUTE_ADPATH_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/base.h" - -namespace Wintermute { -class BasePoint; -class AdPath : public BaseClass { -public: - DECLARE_PERSISTENT(AdPath, BaseClass) - BasePoint *getCurrent(); - bool setReady(bool ready = true); - void addPoint(BasePoint *point); - BasePoint *getNext(); - BasePoint *getFirst(); - void reset(); - AdPath(BaseGame *inGame); - virtual ~AdPath(); - BaseArray _points; - int _currIndex; - bool _ready; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADPATH_H +#define WINTERMUTE_ADPATH_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base.h" + +namespace Wintermute { +class BasePoint; +class AdPath : public BaseClass { +public: + DECLARE_PERSISTENT(AdPath, BaseClass) + BasePoint *getCurrent(); + bool setReady(bool ready = true); + void addPoint(BasePoint *point); + BasePoint *getNext(); + BasePoint *getFirst(); + void reset(); + AdPath(BaseGame *inGame); + virtual ~AdPath(); + BaseArray _points; + int _currIndex; + bool _ready; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_path_point.cpp b/engines/wintermute/ad/ad_path_point.cpp index 1fb954c6686b..a36648eb69fd 100644 --- a/engines/wintermute/ad/ad_path_point.cpp +++ b/engines/wintermute/ad/ad_path_point.cpp @@ -1,75 +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 - */ - -#include "engines/wintermute/ad/ad_path_point.h" -#include "engines/wintermute/base/base_persistence_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdPathPoint, false) - -////////////////////////////////////////////////////////////////////////// -AdPathPoint::AdPathPoint() { - x = y = 0; - _distance = 0; - - _marked = false; - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdPathPoint::AdPathPoint(int initX, int initY, int initDistance) { - x = initX; - y = initY; - _distance = initDistance; - - _marked = false; - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdPathPoint::~AdPathPoint() { - _origin = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdPathPoint::persist(BasePersistenceManager *persistMgr) { - - BasePoint::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_distance)); - persistMgr->transfer(TMEMBER(_marked)); - persistMgr->transfer(TMEMBER(_origin)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_path_point.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdPathPoint, false) + +////////////////////////////////////////////////////////////////////////// +AdPathPoint::AdPathPoint() { + x = y = 0; + _distance = 0; + + _marked = false; + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdPathPoint::AdPathPoint(int initX, int initY, int initDistance) { + x = initX; + y = initY; + _distance = initDistance; + + _marked = false; + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdPathPoint::~AdPathPoint() { + _origin = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdPathPoint::persist(BasePersistenceManager *persistMgr) { + + BasePoint::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_distance)); + persistMgr->transfer(TMEMBER(_marked)); + persistMgr->transfer(TMEMBER(_origin)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_path_point.h b/engines/wintermute/ad/ad_path_point.h index 8201750cef25..58457976c8fa 100644 --- a/engines/wintermute/ad/ad_path_point.h +++ b/engines/wintermute/ad/ad_path_point.h @@ -1,50 +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_ADPATHPOINT_H -#define WINTERMUTE_ADPATHPOINT_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/base_point.h" - -namespace Wintermute { - -class AdPathPoint : public BasePoint { -public: - DECLARE_PERSISTENT(AdPathPoint, BasePoint) - AdPathPoint(int initX, int initY, int initDistance); - AdPathPoint(); - virtual ~AdPathPoint(); - AdPathPoint *_origin; - bool _marked; - int _distance; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADPATHPOINT_H +#define WINTERMUTE_ADPATHPOINT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base_point.h" + +namespace Wintermute { + +class AdPathPoint : public BasePoint { +public: + DECLARE_PERSISTENT(AdPathPoint, BasePoint) + AdPathPoint(int initX, int initY, int initDistance); + AdPathPoint(); + virtual ~AdPathPoint(); + AdPathPoint *_origin; + bool _marked; + int _distance; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_region.cpp b/engines/wintermute/ad/ad_region.cpp index 3e5f91524de2..88bd8201a214 100644 --- a/engines/wintermute/ad/ad_region.cpp +++ b/engines/wintermute/ad/ad_region.cpp @@ -1,397 +1,397 @@ -/* 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_region.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#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/base_file_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdRegion, false) - -////////////////////////////////////////////////////////////////////////// -AdRegion::AdRegion(BaseGame *inGame) : BaseRegion(inGame) { - _blocked = false; - _decoration = false; - _zoom = 0; - _alpha = 0xFFFFFFFF; -} - - -////////////////////////////////////////////////////////////////////////// -AdRegion::~AdRegion() { -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRegion::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdRegion::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(ZOOM) -TOKEN_DEF(SCALE) -TOKEN_DEF(BLOCKED) -TOKEN_DEF(DECORATION) -TOKEN_DEF(POINT) -TOKEN_DEF(ALPHA_COLOR) -TOKEN_DEF(ALPHA) -TOKEN_DEF(EDITOR_SELECTED_POINT) -TOKEN_DEF(EDITOR_SELECTED) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdRegion::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(REGION) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(ACTIVE) - TOKEN_TABLE(ZOOM) - TOKEN_TABLE(SCALE) - TOKEN_TABLE(BLOCKED) - TOKEN_TABLE(DECORATION) - TOKEN_TABLE(POINT) - TOKEN_TABLE(ALPHA_COLOR) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(EDITOR_SELECTED_POINT) - TOKEN_TABLE(EDITOR_SELECTED) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != 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(); - - int ar = 255, ag = 255, ab = 255, alpha = 255; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BLOCKED: - parser.scanStr((char *)params, "%b", &_blocked); - break; - - case TOKEN_DECORATION: - parser.scanStr((char *)params, "%b", &_decoration); - break; - - case TOKEN_ZOOM: - case TOKEN_SCALE: { - int j; - parser.scanStr((char *)params, "%d", &j); - _zoom = (float)j; - } - break; - - case TOKEN_POINT: { - int x, y; - parser.scanStr((char *)params, "%d,%d", &x, &y); - _points.add(new BasePoint(x, y)); - } - break; - - case TOKEN_ALPHA_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); - break; - - case TOKEN_ALPHA: - parser.scanStr((char *)params, "%d", &alpha); - break; - - case TOKEN_EDITOR_SELECTED: - parser.scanStr((char *)params, "%b", &_editorSelected); - break; - - case TOKEN_EDITOR_SELECTED_POINT: - parser.scanStr((char *)params, "%d", &_editorSelectedPoint); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in REGION definition"); - return STATUS_FAILED; - } - - createRegion(); - - _alpha = BYTETORGBA(ar, ag, ab, alpha); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdRegion::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(); - stack->pushNULL(); - - return STATUS_OK; - } - - else*/ return BaseRegion::scCallMethod(script, stack, thisStack, name); -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdRegion::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("ad region"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Name") == 0) { - _scValue->setString(getName()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Blocked - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Blocked") == 0) { - _scValue->setBool(_blocked); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Decoration - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Decoration") == 0) { - _scValue->setBool(_decoration); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Scale - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale") == 0) { - _scValue->setFloat(_zoom); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AlphaColor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AlphaColor") == 0) { - _scValue->setInt((int)_alpha); - return _scValue; - } else { - return BaseRegion::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRegion::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Blocked - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Blocked") == 0) { - _blocked = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Decoration - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Decoration") == 0) { - _decoration = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Scale - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Scale") == 0) { - _zoom = value->getFloat(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AlphaColor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AlphaColor") == 0) { - _alpha = (uint32)value->getInt(); - return STATUS_OK; - } else { - return BaseRegion::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdRegion::scToString() { - return "[ad region]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRegion::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "REGION {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - buffer->putTextIndent(indent + 2, "BLOCKED=%s\n", _blocked ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "DECORATION=%s\n", _decoration ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "SCALE=%d\n", (int)_zoom); - 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)); - buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); - - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - if (_scProp) { - _scProp->saveAsText(buffer, indent + 2); - } - - for (uint32 i = 0; i < _points.size(); i++) { - buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); - } - - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRegion::persist(BasePersistenceManager *persistMgr) { - BaseRegion::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_alpha)); - persistMgr->transfer(TMEMBER(_blocked)); - persistMgr->transfer(TMEMBER(_decoration)); - persistMgr->transfer(TMEMBER(_zoom)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_region.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#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/base_file_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdRegion, false) + +////////////////////////////////////////////////////////////////////////// +AdRegion::AdRegion(BaseGame *inGame) : BaseRegion(inGame) { + _blocked = false; + _decoration = false; + _zoom = 0; + _alpha = 0xFFFFFFFF; +} + + +////////////////////////////////////////////////////////////////////////// +AdRegion::~AdRegion() { +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRegion::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdRegion::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(ZOOM) +TOKEN_DEF(SCALE) +TOKEN_DEF(BLOCKED) +TOKEN_DEF(DECORATION) +TOKEN_DEF(POINT) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(EDITOR_SELECTED_POINT) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdRegion::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(REGION) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(ACTIVE) + TOKEN_TABLE(ZOOM) + TOKEN_TABLE(SCALE) + TOKEN_TABLE(BLOCKED) + TOKEN_TABLE(DECORATION) + TOKEN_TABLE(POINT) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(EDITOR_SELECTED_POINT) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != 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(); + + int ar = 255, ag = 255, ab = 255, alpha = 255; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BLOCKED: + parser.scanStr((char *)params, "%b", &_blocked); + break; + + case TOKEN_DECORATION: + parser.scanStr((char *)params, "%b", &_decoration); + break; + + case TOKEN_ZOOM: + case TOKEN_SCALE: { + int j; + parser.scanStr((char *)params, "%d", &j); + _zoom = (float)j; + } + break; + + case TOKEN_POINT: { + int x, y; + parser.scanStr((char *)params, "%d,%d", &x, &y); + _points.add(new BasePoint(x, y)); + } + break; + + case TOKEN_ALPHA_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.scanStr((char *)params, "%d", &alpha); + break; + + case TOKEN_EDITOR_SELECTED: + parser.scanStr((char *)params, "%b", &_editorSelected); + break; + + case TOKEN_EDITOR_SELECTED_POINT: + parser.scanStr((char *)params, "%d", &_editorSelectedPoint); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in REGION definition"); + return STATUS_FAILED; + } + + createRegion(); + + _alpha = BYTETORGBA(ar, ag, ab, alpha); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdRegion::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(); + stack->pushNULL(); + + return STATUS_OK; + } + + else*/ return BaseRegion::scCallMethod(script, stack, thisStack, name); +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdRegion::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("ad region"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Name") == 0) { + _scValue->setString(getName()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Blocked + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Blocked") == 0) { + _scValue->setBool(_blocked); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Decoration + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Decoration") == 0) { + _scValue->setBool(_decoration); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Scale + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale") == 0) { + _scValue->setFloat(_zoom); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AlphaColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AlphaColor") == 0) { + _scValue->setInt((int)_alpha); + return _scValue; + } else { + return BaseRegion::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRegion::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Blocked + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Blocked") == 0) { + _blocked = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Decoration + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Decoration") == 0) { + _decoration = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Scale + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Scale") == 0) { + _zoom = value->getFloat(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AlphaColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AlphaColor") == 0) { + _alpha = (uint32)value->getInt(); + return STATUS_OK; + } else { + return BaseRegion::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdRegion::scToString() { + return "[ad region]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRegion::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "REGION {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + buffer->putTextIndent(indent + 2, "BLOCKED=%s\n", _blocked ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "DECORATION=%s\n", _decoration ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "ACTIVE=%s\n", _active ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "SCALE=%d\n", (int)_zoom); + 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)); + buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); + + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + if (_scProp) { + _scProp->saveAsText(buffer, indent + 2); + } + + for (uint32 i = 0; i < _points.size(); i++) { + buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); + } + + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRegion::persist(BasePersistenceManager *persistMgr) { + BaseRegion::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_alpha)); + persistMgr->transfer(TMEMBER(_blocked)); + persistMgr->transfer(TMEMBER(_decoration)); + persistMgr->transfer(TMEMBER(_zoom)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_region.h b/engines/wintermute/ad/ad_region.h index 5c33291a8842..a60cb9a3f237 100644 --- a/engines/wintermute/ad/ad_region.h +++ b/engines/wintermute/ad/ad_region.h @@ -1,58 +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_ADREGION_H -#define WINTERMUTE_ADREGION_H - -#include "engines/wintermute/base/base_region.h" - -namespace Wintermute { - -class AdRegion : public BaseRegion { -public: - DECLARE_PERSISTENT(AdRegion, BaseRegion) - uint32 _alpha; - float _zoom; - bool _blocked; - bool _decoration; - AdRegion(BaseGame *inGame); - virtual ~AdRegion(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual 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 +/* 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_ADREGION_H +#define WINTERMUTE_ADREGION_H + +#include "engines/wintermute/base/base_region.h" + +namespace Wintermute { + +class AdRegion : public BaseRegion { +public: + DECLARE_PERSISTENT(AdRegion, BaseRegion) + uint32 _alpha; + float _zoom; + bool _blocked; + bool _decoration; + AdRegion(BaseGame *inGame); + virtual ~AdRegion(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual 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/ad/ad_response.cpp b/engines/wintermute/ad/ad_response.cpp index f7886bba5a00..37f46118bf32 100644 --- a/engines/wintermute/ad/ad_response.cpp +++ b/engines/wintermute/ad/ad_response.cpp @@ -1,146 +1,146 @@ -/* 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_response.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/utils/utils.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdResponse, false) - -////////////////////////////////////////////////////////////////////////// -AdResponse::AdResponse(BaseGame *inGame) : BaseObject(inGame) { - _text = NULL; - _textOrig = NULL; - _icon = _iconHover = _iconPressed = NULL; - _font = NULL; - _iD = 0; - _responseType = RESPONSE_ALWAYS; -} - - -////////////////////////////////////////////////////////////////////////// -AdResponse::~AdResponse() { - delete[] _text; - delete[] _textOrig; - delete _icon; - delete _iconHover; - delete _iconPressed; - _text = NULL; - _textOrig = NULL; - _icon = NULL; - _iconHover = NULL; - _iconPressed = NULL; - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdResponse::setText(const char *text) { - BaseUtils::setString(&_text, text); - BaseUtils::setString(&_textOrig, text); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponse::setIcon(const char *filename) { - delete _icon; - _icon = new BaseSprite(_gameRef); - if (!_icon || DID_FAIL(_icon->loadFile(filename))) { - _gameRef->LOG(0, "AdResponse::setIcon failed for file '%s'", filename); - delete _icon; - _icon = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdResponse::setFont(const char *filename) { - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont(filename); - if (!_font) { - _gameRef->LOG(0, "AdResponse::setFont failed for file '%s'", filename); - return STATUS_FAILED; - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdResponse::setIconHover(const char *filename) { - delete _iconHover; - _iconHover = new BaseSprite(_gameRef); - if (!_iconHover || DID_FAIL(_iconHover->loadFile(filename))) { - _gameRef->LOG(0, "AdResponse::setIconHover failed for file '%s'", filename); - delete _iconHover; - _iconHover = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponse::setIconPressed(const char *filename) { - delete _iconPressed; - _iconPressed = new BaseSprite(_gameRef); - if (!_iconPressed || DID_FAIL(_iconPressed->loadFile(filename))) { - _gameRef->LOG(0, "AdResponse::setIconPressed failed for file '%s'", filename); - delete _iconPressed; - _iconPressed = NULL; - return STATUS_FAILED; - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponse::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_icon)); - persistMgr->transfer(TMEMBER(_iconHover)); - persistMgr->transfer(TMEMBER(_iconPressed)); - persistMgr->transfer(TMEMBER(_iD)); - persistMgr->transfer(TMEMBER(_text)); - persistMgr->transfer(TMEMBER(_textOrig)); - persistMgr->transfer(TMEMBER_INT(_responseType)); - persistMgr->transfer(TMEMBER(_font)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_response.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/utils/utils.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdResponse, false) + +////////////////////////////////////////////////////////////////////////// +AdResponse::AdResponse(BaseGame *inGame) : BaseObject(inGame) { + _text = NULL; + _textOrig = NULL; + _icon = _iconHover = _iconPressed = NULL; + _font = NULL; + _iD = 0; + _responseType = RESPONSE_ALWAYS; +} + + +////////////////////////////////////////////////////////////////////////// +AdResponse::~AdResponse() { + delete[] _text; + delete[] _textOrig; + delete _icon; + delete _iconHover; + delete _iconPressed; + _text = NULL; + _textOrig = NULL; + _icon = NULL; + _iconHover = NULL; + _iconPressed = NULL; + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdResponse::setText(const char *text) { + BaseUtils::setString(&_text, text); + BaseUtils::setString(&_textOrig, text); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponse::setIcon(const char *filename) { + delete _icon; + _icon = new BaseSprite(_gameRef); + if (!_icon || DID_FAIL(_icon->loadFile(filename))) { + _gameRef->LOG(0, "AdResponse::setIcon failed for file '%s'", filename); + delete _icon; + _icon = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdResponse::setFont(const char *filename) { + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont(filename); + if (!_font) { + _gameRef->LOG(0, "AdResponse::setFont failed for file '%s'", filename); + return STATUS_FAILED; + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdResponse::setIconHover(const char *filename) { + delete _iconHover; + _iconHover = new BaseSprite(_gameRef); + if (!_iconHover || DID_FAIL(_iconHover->loadFile(filename))) { + _gameRef->LOG(0, "AdResponse::setIconHover failed for file '%s'", filename); + delete _iconHover; + _iconHover = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponse::setIconPressed(const char *filename) { + delete _iconPressed; + _iconPressed = new BaseSprite(_gameRef); + if (!_iconPressed || DID_FAIL(_iconPressed->loadFile(filename))) { + _gameRef->LOG(0, "AdResponse::setIconPressed failed for file '%s'", filename); + delete _iconPressed; + _iconPressed = NULL; + return STATUS_FAILED; + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponse::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_icon)); + persistMgr->transfer(TMEMBER(_iconHover)); + persistMgr->transfer(TMEMBER(_iconPressed)); + persistMgr->transfer(TMEMBER(_iD)); + persistMgr->transfer(TMEMBER(_text)); + persistMgr->transfer(TMEMBER(_textOrig)); + persistMgr->transfer(TMEMBER_INT(_responseType)); + persistMgr->transfer(TMEMBER(_font)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response.h b/engines/wintermute/ad/ad_response.h index 0678ef5a371c..0ba88cf2e892 100644 --- a/engines/wintermute/ad/ad_response.h +++ b/engines/wintermute/ad/ad_response.h @@ -1,61 +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_ADRESPONSE_H -#define WINTERMUTE_ADRESPONSE_H - - -#include "engines/wintermute/base/base_object.h" -#include "engines/wintermute/ad/ad_types.h" - -namespace Wintermute { -class BaseFont; -class AdResponse : public BaseObject { -public: - DECLARE_PERSISTENT(AdResponse, BaseObject) - bool setIcon(const char *filename); - bool setFont(const char *filename); - bool setIconHover(const char *filename); - bool setIconPressed(const char *filename); - void setText(const char *text); - int _iD; - BaseSprite *_icon; - BaseSprite *_iconHover; - BaseSprite *_iconPressed; - BaseFont *_font; - char *_text; - char *_textOrig; - AdResponse(BaseGame *inGame); - virtual ~AdResponse(); - TResponseType _responseType; - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADRESPONSE_H +#define WINTERMUTE_ADRESPONSE_H + + +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/ad/ad_types.h" + +namespace Wintermute { +class BaseFont; +class AdResponse : public BaseObject { +public: + DECLARE_PERSISTENT(AdResponse, BaseObject) + bool setIcon(const char *filename); + bool setFont(const char *filename); + bool setIconHover(const char *filename); + bool setIconPressed(const char *filename); + void setText(const char *text); + int _iD; + BaseSprite *_icon; + BaseSprite *_iconHover; + BaseSprite *_iconPressed; + BaseFont *_font; + char *_text; + char *_textOrig; + AdResponse(BaseGame *inGame); + virtual ~AdResponse(); + TResponseType _responseType; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_response_box.cpp b/engines/wintermute/ad/ad_response_box.cpp index 76510e2f3e87..a27f1ca54b62 100644 --- a/engines/wintermute/ad/ad_response_box.cpp +++ b/engines/wintermute/ad/ad_response_box.cpp @@ -1,712 +1,712 @@ -/* 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/ad/ad_response_box.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_surface_storage.h" -#include "engines/wintermute/ui/ui_button.h" -#include "engines/wintermute/ui/ui_window.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/ad/ad_response.h" -#include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/base_sprite.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 "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdResponseBox, false) - -////////////////////////////////////////////////////////////////////////// -AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) { - _font = _fontHover = NULL; - - _window = NULL; - _shieldWindow = new UIWindow(_gameRef); - - _horizontal = false; - BasePlatform::setRectEmpty(&_responseArea); - _scrollOffset = 0; - _spacing = 0; - - _waitingScript = NULL; - _lastResponseText = NULL; - _lastResponseTextOrig = NULL; - - _verticalAlign = VAL_BOTTOM; - _align = TAL_LEFT; -} - - -////////////////////////////////////////////////////////////////////////// -AdResponseBox::~AdResponseBox() { - - delete _window; - _window = NULL; - delete _shieldWindow; - _shieldWindow = NULL; - delete[] _lastResponseText; - _lastResponseText = NULL; - delete[] _lastResponseTextOrig; - _lastResponseTextOrig = NULL; - - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - if (_fontHover) { - _gameRef->_fontStorage->removeFont(_fontHover); - } - - clearResponses(); - clearButtons(); - - _waitingScript = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void AdResponseBox::clearResponses() { - for (uint32 i = 0; i < _responses.size(); i++) { - delete _responses[i]; - } - _responses.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -void AdResponseBox::clearButtons() { - for (uint32 i = 0; i < _respButtons.size(); i++) { - delete _respButtons[i]; - } - _respButtons.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::invalidateButtons() { - for (uint32 i = 0; i < _respButtons.size(); i++) { - _respButtons[i]->_image = NULL; - _respButtons[i]->_cursor = NULL; - _respButtons[i]->_font = NULL; - _respButtons[i]->_fontHover = NULL; - _respButtons[i]->_fontPress = NULL; - _respButtons[i]->setText(""); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::createButtons() { - clearButtons(); - - _scrollOffset = 0; - for (uint32 i = 0; i < _responses.size(); i++) { - UIButton *btn = new UIButton(_gameRef); - if (btn) { - btn->_parent = _window; - btn->_sharedFonts = btn->_sharedImages = true; - btn->_sharedCursors = true; - // iconic - if (_responses[i]->_icon) { - btn->_image = _responses[i]->_icon; - if (_responses[i]->_iconHover) { - btn->_imageHover = _responses[i]->_iconHover; - } - if (_responses[i]->_iconPressed) { - btn->_imagePress = _responses[i]->_iconPressed; - } - - btn->setCaption(_responses[i]->_text); - if (_cursor) { - btn->_cursor = _cursor; - } else if (_gameRef->_activeCursor) { - btn->_cursor = _gameRef->_activeCursor; - } - } - // textual - else { - btn->setText(_responses[i]->_text); - btn->_font = (_font == NULL) ? _gameRef->_systemFont : _font; - btn->_fontHover = (_fontHover == NULL) ? _gameRef->_systemFont : _fontHover; - btn->_fontPress = btn->_fontHover; - btn->_align = _align; - - if (_gameRef->_touchInterface) { - btn->_fontHover = btn->_font; - } - - - if (_responses[i]->_font) { - btn->_font = _responses[i]->_font; - } - - btn->_width = _responseArea.right - _responseArea.left; - if (btn->_width <= 0) { - btn->_width = _gameRef->_renderer->_width; - } - } - btn->setName("response"); - btn->correctSize(); - - // make the responses touchable - if (_gameRef->_touchInterface) { - btn->_height = MAX(btn->_height, 50); - } - - //btn->SetListener(this, btn, _responses[i]->_iD); - btn->setListener(this, btn, i); - btn->_visible = false; - _respButtons.add(btn); - - if (_responseArea.bottom - _responseArea.top < btn->_height) { - _gameRef->LOG(0, "Warning: Response '%s' is too high to be displayed within response box. Correcting.", _responses[i]->_text); - _responseArea.bottom += (btn->_height - (_responseArea.bottom - _responseArea.top)); - } - } - } - _ready = false; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdResponseBox::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 RESPONSE_BOX file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(RESPONSE_BOX) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(FONT_HOVER) -TOKEN_DEF(FONT) -TOKEN_DEF(AREA) -TOKEN_DEF(HORIZONTAL) -TOKEN_DEF(SPACING) -TOKEN_DEF(WINDOW) -TOKEN_DEF(CURSOR) -TOKEN_DEF(TEXT_ALIGN) -TOKEN_DEF(VERTICAL_ALIGN) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(RESPONSE_BOX) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(FONT_HOVER) - TOKEN_TABLE(FONT) - TOKEN_TABLE(AREA) - TOKEN_TABLE(HORIZONTAL) - TOKEN_TABLE(SPACING) - TOKEN_TABLE(WINDOW) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(TEXT_ALIGN) - TOKEN_TABLE(VERTICAL_ALIGN) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_RESPONSE_BOX) { - _gameRef->LOG(0, "'RESPONSE_BOX' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_WINDOW: - delete _window; - _window = new UIWindow(_gameRef); - if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { - delete _window; - _window = NULL; - cmd = PARSERR_GENERIC; - } else if (_shieldWindow) { - _shieldWindow->_parent = _window; - } - break; - - case TOKEN_FONT: - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont((char *)params); - if (!_font) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_HOVER: - if (_fontHover) { - _gameRef->_fontStorage->removeFont(_fontHover); - } - _fontHover = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontHover) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_AREA: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_responseArea.left, &_responseArea.top, &_responseArea.right, &_responseArea.bottom); - break; - - case TOKEN_HORIZONTAL: - parser.scanStr((char *)params, "%b", &_horizontal); - break; - - case TOKEN_TEXT_ALIGN: - if (scumm_stricmp((char *)params, "center") == 0) { - _align = TAL_CENTER; - } else if (scumm_stricmp((char *)params, "right") == 0) { - _align = TAL_RIGHT; - } else { - _align = TAL_LEFT; - } - break; - - case TOKEN_VERTICAL_ALIGN: - if (scumm_stricmp((char *)params, "top") == 0) { - _verticalAlign = VAL_TOP; - } else if (scumm_stricmp((char *)params, "center") == 0) { - _verticalAlign = VAL_CENTER; - } else { - _verticalAlign = VAL_BOTTOM; - } - break; - - case TOKEN_SPACING: - parser.scanStr((char *)params, "%d", &_spacing); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - 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; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in RESPONSE_BOX definition"); - return STATUS_FAILED; - } - - if (_window) { - for (uint32 i = 0; i < _window->_widgets.size(); i++) { - if (!_window->_widgets[i]->_listenerObject) { - _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); - } - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "RESPONSE_BOX\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "AREA { %d, %d, %d, %d }\n", _responseArea.left, _responseArea.top, _responseArea.right, _responseArea.bottom); - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - if (_fontHover && _fontHover->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - buffer->putTextIndent(indent + 2, "HORIZONTAL=%s\n", _horizontal ? "TRUE" : "FALSE"); - - switch (_align) { - case TAL_LEFT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); - break; - case TAL_RIGHT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); - break; - case TAL_CENTER: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); - break; - default: - error("AdResponseBox::SaveAsText - Unhandled enum"); - break; - } - - switch (_verticalAlign) { - case VAL_TOP: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top"); - break; - case VAL_BOTTOM: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom"); - break; - case VAL_CENTER: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center"); - break; - } - - buffer->putTextIndent(indent + 2, "SPACING=%d\n", _spacing); - - buffer->putTextIndent(indent + 2, "\n"); - - // window - if (_window) { - _window->saveAsText(buffer, indent + 2); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::display() { - Rect32 rect = _responseArea; - if (_window) { - rect.offsetRect(_window->_posX, _window->_posY); - //_window->display(); - } - - int xxx, yyy; - uint32 i; - - xxx = rect.left; - yyy = rect.top; - - // shift down if needed - if (!_horizontal) { - int totalHeight = 0; - for (i = 0; i < _respButtons.size(); i++) { - totalHeight += (_respButtons[i]->_height + _spacing); - } - totalHeight -= _spacing; - - switch (_verticalAlign) { - case VAL_BOTTOM: - if (yyy + totalHeight < rect.bottom) { - yyy = rect.bottom - totalHeight; - } - break; - - case VAL_CENTER: - if (yyy + totalHeight < rect.bottom) { - yyy += ((rect.bottom - rect.top) - totalHeight) / 2; - } - break; - - case VAL_TOP: - // do nothing - break; - } - } - - // prepare response buttons - bool scrollNeeded = false; - for (i = _scrollOffset; i < _respButtons.size(); i++) { - if ((_horizontal && xxx + _respButtons[i]->_width > rect.right) - || (!_horizontal && yyy + _respButtons[i]->_height > rect.bottom)) { - - scrollNeeded = true; - _respButtons[i]->_visible = false; - break; - } - - _respButtons[i]->_visible = true; - _respButtons[i]->_posX = xxx; - _respButtons[i]->_posY = yyy; - - if (_horizontal) { - xxx += (_respButtons[i]->_width + _spacing); - } else { - yyy += (_respButtons[i]->_height + _spacing); - } - } - - // show appropriate scroll buttons - if (_window) { - _window->showWidget("prev", _scrollOffset > 0); - _window->showWidget("next", scrollNeeded); - } - - // go exclusive - if (_shieldWindow) { - _shieldWindow->_posX = _shieldWindow->_posY = 0; - _shieldWindow->_width = _gameRef->_renderer->_width; - _shieldWindow->_height = _gameRef->_renderer->_height; - - _shieldWindow->display(); - } - - // display window - if (_window) { - _window->display(); - } - - - // display response buttons - for (i = _scrollOffset; i < _respButtons.size(); i++) { - _respButtons[i]->display(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::listen(BaseScriptHolder *param1, uint32 param2) { - UIObject *obj = (UIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->getName(), "prev") == 0) { - _scrollOffset--; - } else if (scumm_stricmp(obj->getName(), "next") == 0) { - _scrollOffset++; - } else if (scumm_stricmp(obj->getName(), "response") == 0) { - if (_waitingScript) { - _waitingScript->_stack->pushInt(_responses[param2]->_iD); - } - handleResponse(_responses[param2]); - _waitingScript = NULL; - _gameRef->_state = GAME_RUNNING; - ((AdGame *)_gameRef)->_stateEx = GAME_NORMAL; - _ready = true; - invalidateButtons(); - clearResponses(); - } else { - return BaseObject::listen(param1, param2); - } - break; - default: - error("AdResponseBox::Listen - Unhandled enum"); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::persist(BasePersistenceManager *persistMgr) { - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_font)); - persistMgr->transfer(TMEMBER(_fontHover)); - persistMgr->transfer(TMEMBER(_horizontal)); - persistMgr->transfer(TMEMBER(_lastResponseText)); - persistMgr->transfer(TMEMBER(_lastResponseTextOrig)); - _respButtons.persist(persistMgr); - persistMgr->transfer(TMEMBER(_responseArea)); - _responses.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scrollOffset)); - persistMgr->transfer(TMEMBER(_shieldWindow)); - persistMgr->transfer(TMEMBER(_spacing)); - persistMgr->transfer(TMEMBER(_waitingScript)); - persistMgr->transfer(TMEMBER(_window)); - - persistMgr->transfer(TMEMBER_INT(_verticalAlign)); - persistMgr->transfer(TMEMBER_INT(_align)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::weedResponses() { - AdGame *adGame = (AdGame *)_gameRef; - - for (uint32 i = 0; i < _responses.size(); i++) { - switch (_responses[i]->_responseType) { - case RESPONSE_ONCE: - if (adGame->branchResponseUsed(_responses[i]->_iD)) { - delete _responses[i]; - _responses.remove_at(i); - i--; - } - break; - - case RESPONSE_ONCE_GAME: - if (adGame->gameResponseUsed(_responses[i]->_iD)) { - delete _responses[i]; - _responses.remove_at(i); - i--; - } - break; - default: - debugC(kWintermuteDebugGeneral, "AdResponseBox::WeedResponses - Unhandled enum"); - break; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdResponseBox::setLastResponseText(const char *text, const char *textOrig) { - BaseUtils::setString(&_lastResponseText, text); - BaseUtils::setString(&_lastResponseTextOrig, textOrig); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::handleResponse(AdResponse *response) { - setLastResponseText(response->_text, response->_textOrig); - - AdGame *adGame = (AdGame *)_gameRef; - - switch (response->_responseType) { - case RESPONSE_ONCE: - adGame->addBranchResponse(response->_iD); - break; - - case RESPONSE_ONCE_GAME: - adGame->addGameResponse(response->_iD); - break; - default: - debugC(kWintermuteDebugGeneral, "AdResponseBox::HandleResponse - Unhandled enum"); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -BaseObject *AdResponseBox::getNextAccessObject(BaseObject *currObject) { - BaseArray objects; - getObjects(objects, true); - - if (objects.size() == 0) { - return NULL; - } else { - if (currObject != NULL) { - for (uint32 i = 0; i < objects.size(); i++) { - if (objects[i] == currObject) { - if (i < objects.size() - 1) { - return objects[i + 1]; - } else { - break; - } - } - } - } - return objects[0]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -BaseObject *AdResponseBox::getPrevAccessObject(BaseObject *currObject) { - BaseArray objects; - getObjects(objects, true); - - if (objects.size() == 0) { - return NULL; - } else { - if (currObject != NULL) { - for (int i = objects.size() - 1; i >= 0; i--) { - if (objects[i] == currObject) { - if (i > 0) { - return objects[i - 1]; - } else { - break; - } - } - } - } - return objects[objects.size() - 1]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -bool AdResponseBox::getObjects(BaseArray &objects, bool interactiveOnly) { - for (uint32 i = 0; i < _respButtons.size(); i++) { - objects.add(_respButtons[i]); - } - if (_window) { - _window->getWindowObjects(objects, interactiveOnly); - } - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ad/ad_response_box.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_surface_storage.h" +#include "engines/wintermute/ui/ui_button.h" +#include "engines/wintermute/ui/ui_window.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/ad/ad_response.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/base_sprite.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 "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdResponseBox, false) + +////////////////////////////////////////////////////////////////////////// +AdResponseBox::AdResponseBox(BaseGame *inGame) : BaseObject(inGame) { + _font = _fontHover = NULL; + + _window = NULL; + _shieldWindow = new UIWindow(_gameRef); + + _horizontal = false; + BasePlatform::setRectEmpty(&_responseArea); + _scrollOffset = 0; + _spacing = 0; + + _waitingScript = NULL; + _lastResponseText = NULL; + _lastResponseTextOrig = NULL; + + _verticalAlign = VAL_BOTTOM; + _align = TAL_LEFT; +} + + +////////////////////////////////////////////////////////////////////////// +AdResponseBox::~AdResponseBox() { + + delete _window; + _window = NULL; + delete _shieldWindow; + _shieldWindow = NULL; + delete[] _lastResponseText; + _lastResponseText = NULL; + delete[] _lastResponseTextOrig; + _lastResponseTextOrig = NULL; + + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + if (_fontHover) { + _gameRef->_fontStorage->removeFont(_fontHover); + } + + clearResponses(); + clearButtons(); + + _waitingScript = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void AdResponseBox::clearResponses() { + for (uint32 i = 0; i < _responses.size(); i++) { + delete _responses[i]; + } + _responses.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +void AdResponseBox::clearButtons() { + for (uint32 i = 0; i < _respButtons.size(); i++) { + delete _respButtons[i]; + } + _respButtons.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::invalidateButtons() { + for (uint32 i = 0; i < _respButtons.size(); i++) { + _respButtons[i]->_image = NULL; + _respButtons[i]->_cursor = NULL; + _respButtons[i]->_font = NULL; + _respButtons[i]->_fontHover = NULL; + _respButtons[i]->_fontPress = NULL; + _respButtons[i]->setText(""); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::createButtons() { + clearButtons(); + + _scrollOffset = 0; + for (uint32 i = 0; i < _responses.size(); i++) { + UIButton *btn = new UIButton(_gameRef); + if (btn) { + btn->_parent = _window; + btn->_sharedFonts = btn->_sharedImages = true; + btn->_sharedCursors = true; + // iconic + if (_responses[i]->_icon) { + btn->_image = _responses[i]->_icon; + if (_responses[i]->_iconHover) { + btn->_imageHover = _responses[i]->_iconHover; + } + if (_responses[i]->_iconPressed) { + btn->_imagePress = _responses[i]->_iconPressed; + } + + btn->setCaption(_responses[i]->_text); + if (_cursor) { + btn->_cursor = _cursor; + } else if (_gameRef->_activeCursor) { + btn->_cursor = _gameRef->_activeCursor; + } + } + // textual + else { + btn->setText(_responses[i]->_text); + btn->_font = (_font == NULL) ? _gameRef->_systemFont : _font; + btn->_fontHover = (_fontHover == NULL) ? _gameRef->_systemFont : _fontHover; + btn->_fontPress = btn->_fontHover; + btn->_align = _align; + + if (_gameRef->_touchInterface) { + btn->_fontHover = btn->_font; + } + + + if (_responses[i]->_font) { + btn->_font = _responses[i]->_font; + } + + btn->_width = _responseArea.right - _responseArea.left; + if (btn->_width <= 0) { + btn->_width = _gameRef->_renderer->_width; + } + } + btn->setName("response"); + btn->correctSize(); + + // make the responses touchable + if (_gameRef->_touchInterface) { + btn->_height = MAX(btn->_height, 50); + } + + //btn->SetListener(this, btn, _responses[i]->_iD); + btn->setListener(this, btn, i); + btn->_visible = false; + _respButtons.add(btn); + + if (_responseArea.bottom - _responseArea.top < btn->_height) { + _gameRef->LOG(0, "Warning: Response '%s' is too high to be displayed within response box. Correcting.", _responses[i]->_text); + _responseArea.bottom += (btn->_height - (_responseArea.bottom - _responseArea.top)); + } + } + } + _ready = false; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdResponseBox::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 RESPONSE_BOX file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(RESPONSE_BOX) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(FONT_HOVER) +TOKEN_DEF(FONT) +TOKEN_DEF(AREA) +TOKEN_DEF(HORIZONTAL) +TOKEN_DEF(SPACING) +TOKEN_DEF(WINDOW) +TOKEN_DEF(CURSOR) +TOKEN_DEF(TEXT_ALIGN) +TOKEN_DEF(VERTICAL_ALIGN) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(RESPONSE_BOX) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(FONT_HOVER) + TOKEN_TABLE(FONT) + TOKEN_TABLE(AREA) + TOKEN_TABLE(HORIZONTAL) + TOKEN_TABLE(SPACING) + TOKEN_TABLE(WINDOW) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(TEXT_ALIGN) + TOKEN_TABLE(VERTICAL_ALIGN) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_RESPONSE_BOX) { + _gameRef->LOG(0, "'RESPONSE_BOX' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_WINDOW: + delete _window; + _window = new UIWindow(_gameRef); + if (!_window || DID_FAIL(_window->loadBuffer(params, false))) { + delete _window; + _window = NULL; + cmd = PARSERR_GENERIC; + } else if (_shieldWindow) { + _shieldWindow->_parent = _window; + } + break; + + case TOKEN_FONT: + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont((char *)params); + if (!_font) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_HOVER: + if (_fontHover) { + _gameRef->_fontStorage->removeFont(_fontHover); + } + _fontHover = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontHover) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_AREA: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_responseArea.left, &_responseArea.top, &_responseArea.right, &_responseArea.bottom); + break; + + case TOKEN_HORIZONTAL: + parser.scanStr((char *)params, "%b", &_horizontal); + break; + + case TOKEN_TEXT_ALIGN: + if (scumm_stricmp((char *)params, "center") == 0) { + _align = TAL_CENTER; + } else if (scumm_stricmp((char *)params, "right") == 0) { + _align = TAL_RIGHT; + } else { + _align = TAL_LEFT; + } + break; + + case TOKEN_VERTICAL_ALIGN: + if (scumm_stricmp((char *)params, "top") == 0) { + _verticalAlign = VAL_TOP; + } else if (scumm_stricmp((char *)params, "center") == 0) { + _verticalAlign = VAL_CENTER; + } else { + _verticalAlign = VAL_BOTTOM; + } + break; + + case TOKEN_SPACING: + parser.scanStr((char *)params, "%d", &_spacing); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + 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; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in RESPONSE_BOX definition"); + return STATUS_FAILED; + } + + if (_window) { + for (uint32 i = 0; i < _window->_widgets.size(); i++) { + if (!_window->_widgets[i]->_listenerObject) { + _window->_widgets[i]->setListener(this, _window->_widgets[i], 0); + } + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "RESPONSE_BOX\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "AREA { %d, %d, %d, %d }\n", _responseArea.left, _responseArea.top, _responseArea.right, _responseArea.bottom); + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + if (_fontHover && _fontHover->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + buffer->putTextIndent(indent + 2, "HORIZONTAL=%s\n", _horizontal ? "TRUE" : "FALSE"); + + switch (_align) { + case TAL_LEFT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); + break; + case TAL_RIGHT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); + break; + case TAL_CENTER: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); + break; + default: + error("AdResponseBox::SaveAsText - Unhandled enum"); + break; + } + + switch (_verticalAlign) { + case VAL_TOP: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top"); + break; + case VAL_BOTTOM: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom"); + break; + case VAL_CENTER: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center"); + break; + } + + buffer->putTextIndent(indent + 2, "SPACING=%d\n", _spacing); + + buffer->putTextIndent(indent + 2, "\n"); + + // window + if (_window) { + _window->saveAsText(buffer, indent + 2); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::display() { + Rect32 rect = _responseArea; + if (_window) { + rect.offsetRect(_window->_posX, _window->_posY); + //_window->display(); + } + + int xxx, yyy; + uint32 i; + + xxx = rect.left; + yyy = rect.top; + + // shift down if needed + if (!_horizontal) { + int totalHeight = 0; + for (i = 0; i < _respButtons.size(); i++) { + totalHeight += (_respButtons[i]->_height + _spacing); + } + totalHeight -= _spacing; + + switch (_verticalAlign) { + case VAL_BOTTOM: + if (yyy + totalHeight < rect.bottom) { + yyy = rect.bottom - totalHeight; + } + break; + + case VAL_CENTER: + if (yyy + totalHeight < rect.bottom) { + yyy += ((rect.bottom - rect.top) - totalHeight) / 2; + } + break; + + case VAL_TOP: + // do nothing + break; + } + } + + // prepare response buttons + bool scrollNeeded = false; + for (i = _scrollOffset; i < _respButtons.size(); i++) { + if ((_horizontal && xxx + _respButtons[i]->_width > rect.right) + || (!_horizontal && yyy + _respButtons[i]->_height > rect.bottom)) { + + scrollNeeded = true; + _respButtons[i]->_visible = false; + break; + } + + _respButtons[i]->_visible = true; + _respButtons[i]->_posX = xxx; + _respButtons[i]->_posY = yyy; + + if (_horizontal) { + xxx += (_respButtons[i]->_width + _spacing); + } else { + yyy += (_respButtons[i]->_height + _spacing); + } + } + + // show appropriate scroll buttons + if (_window) { + _window->showWidget("prev", _scrollOffset > 0); + _window->showWidget("next", scrollNeeded); + } + + // go exclusive + if (_shieldWindow) { + _shieldWindow->_posX = _shieldWindow->_posY = 0; + _shieldWindow->_width = _gameRef->_renderer->_width; + _shieldWindow->_height = _gameRef->_renderer->_height; + + _shieldWindow->display(); + } + + // display window + if (_window) { + _window->display(); + } + + + // display response buttons + for (i = _scrollOffset; i < _respButtons.size(); i++) { + _respButtons[i]->display(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::listen(BaseScriptHolder *param1, uint32 param2) { + UIObject *obj = (UIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->getName(), "prev") == 0) { + _scrollOffset--; + } else if (scumm_stricmp(obj->getName(), "next") == 0) { + _scrollOffset++; + } else if (scumm_stricmp(obj->getName(), "response") == 0) { + if (_waitingScript) { + _waitingScript->_stack->pushInt(_responses[param2]->_iD); + } + handleResponse(_responses[param2]); + _waitingScript = NULL; + _gameRef->_state = GAME_RUNNING; + ((AdGame *)_gameRef)->_stateEx = GAME_NORMAL; + _ready = true; + invalidateButtons(); + clearResponses(); + } else { + return BaseObject::listen(param1, param2); + } + break; + default: + error("AdResponseBox::Listen - Unhandled enum"); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_font)); + persistMgr->transfer(TMEMBER(_fontHover)); + persistMgr->transfer(TMEMBER(_horizontal)); + persistMgr->transfer(TMEMBER(_lastResponseText)); + persistMgr->transfer(TMEMBER(_lastResponseTextOrig)); + _respButtons.persist(persistMgr); + persistMgr->transfer(TMEMBER(_responseArea)); + _responses.persist(persistMgr); + persistMgr->transfer(TMEMBER(_scrollOffset)); + persistMgr->transfer(TMEMBER(_shieldWindow)); + persistMgr->transfer(TMEMBER(_spacing)); + persistMgr->transfer(TMEMBER(_waitingScript)); + persistMgr->transfer(TMEMBER(_window)); + + persistMgr->transfer(TMEMBER_INT(_verticalAlign)); + persistMgr->transfer(TMEMBER_INT(_align)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::weedResponses() { + AdGame *adGame = (AdGame *)_gameRef; + + for (uint32 i = 0; i < _responses.size(); i++) { + switch (_responses[i]->_responseType) { + case RESPONSE_ONCE: + if (adGame->branchResponseUsed(_responses[i]->_iD)) { + delete _responses[i]; + _responses.remove_at(i); + i--; + } + break; + + case RESPONSE_ONCE_GAME: + if (adGame->gameResponseUsed(_responses[i]->_iD)) { + delete _responses[i]; + _responses.remove_at(i); + i--; + } + break; + default: + debugC(kWintermuteDebugGeneral, "AdResponseBox::WeedResponses - Unhandled enum"); + break; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdResponseBox::setLastResponseText(const char *text, const char *textOrig) { + BaseUtils::setString(&_lastResponseText, text); + BaseUtils::setString(&_lastResponseTextOrig, textOrig); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::handleResponse(AdResponse *response) { + setLastResponseText(response->_text, response->_textOrig); + + AdGame *adGame = (AdGame *)_gameRef; + + switch (response->_responseType) { + case RESPONSE_ONCE: + adGame->addBranchResponse(response->_iD); + break; + + case RESPONSE_ONCE_GAME: + adGame->addGameResponse(response->_iD); + break; + default: + debugC(kWintermuteDebugGeneral, "AdResponseBox::HandleResponse - Unhandled enum"); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +BaseObject *AdResponseBox::getNextAccessObject(BaseObject *currObject) { + BaseArray objects; + getObjects(objects, true); + + if (objects.size() == 0) { + return NULL; + } else { + if (currObject != NULL) { + for (uint32 i = 0; i < objects.size(); i++) { + if (objects[i] == currObject) { + if (i < objects.size() - 1) { + return objects[i + 1]; + } else { + break; + } + } + } + } + return objects[0]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +BaseObject *AdResponseBox::getPrevAccessObject(BaseObject *currObject) { + BaseArray objects; + getObjects(objects, true); + + if (objects.size() == 0) { + return NULL; + } else { + if (currObject != NULL) { + for (int i = objects.size() - 1; i >= 0; i--) { + if (objects[i] == currObject) { + if (i > 0) { + return objects[i - 1]; + } else { + break; + } + } + } + } + return objects[objects.size() - 1]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +bool AdResponseBox::getObjects(BaseArray &objects, bool interactiveOnly) { + for (uint32 i = 0; i < _respButtons.size(); i++) { + objects.add(_respButtons[i]); + } + if (_window) { + _window->getWindowObjects(objects, interactiveOnly); + } + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response_box.h b/engines/wintermute/ad/ad_response_box.h index 8c76b561c67c..35f8cb634797 100644 --- a/engines/wintermute/ad/ad_response_box.h +++ b/engines/wintermute/ad/ad_response_box.h @@ -1,87 +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_ADRESPONSEBOX_H -#define WINTERMUTE_ADRESPONSEBOX_H - - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { - -class UIButton; -class UIWindow; -class UIObject; -class AdResponse; -class AdResponseBox : public BaseObject { -public: - BaseObject *getNextAccessObject(BaseObject *CurrObject); - BaseObject *getPrevAccessObject(BaseObject *CurrObject); - bool getObjects(BaseArray &objects, bool interactiveOnly); - - bool handleResponse(AdResponse *response); - void setLastResponseText(const char *text, const char *textOrig); - char *_lastResponseText; - char *_lastResponseTextOrig; - DECLARE_PERSISTENT(AdResponseBox, BaseObject) - ScScript *_waitingScript; - virtual bool listen(BaseScriptHolder *param1, uint32 param2); - typedef enum { - EVENT_PREV, - EVENT_NEXT, - EVENT_RESPONSE - } TResponseEvent; - - bool weedResponses(); - bool display(); - int _spacing; - int _scrollOffset; - BaseFont *_fontHover; - BaseFont *_font; - bool createButtons(); - bool invalidateButtons(); - void clearButtons(); - void clearResponses(); - AdResponseBox(BaseGame *inGame); - virtual ~AdResponseBox(); - BaseArray _responses; - BaseArray _respButtons; - UIWindow *_window; - UIWindow *_shieldWindow; - bool _horizontal; - Rect32 _responseArea; - int _verticalAlign; - TTextAlign _align; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADRESPONSEBOX_H +#define WINTERMUTE_ADRESPONSEBOX_H + + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class UIButton; +class UIWindow; +class UIObject; +class AdResponse; +class AdResponseBox : public BaseObject { +public: + BaseObject *getNextAccessObject(BaseObject *CurrObject); + BaseObject *getPrevAccessObject(BaseObject *CurrObject); + bool getObjects(BaseArray &objects, bool interactiveOnly); + + bool handleResponse(AdResponse *response); + void setLastResponseText(const char *text, const char *textOrig); + char *_lastResponseText; + char *_lastResponseTextOrig; + DECLARE_PERSISTENT(AdResponseBox, BaseObject) + ScScript *_waitingScript; + virtual bool listen(BaseScriptHolder *param1, uint32 param2); + typedef enum { + EVENT_PREV, + EVENT_NEXT, + EVENT_RESPONSE + } TResponseEvent; + + bool weedResponses(); + bool display(); + int _spacing; + int _scrollOffset; + BaseFont *_fontHover; + BaseFont *_font; + bool createButtons(); + bool invalidateButtons(); + void clearButtons(); + void clearResponses(); + AdResponseBox(BaseGame *inGame); + virtual ~AdResponseBox(); + BaseArray _responses; + BaseArray _respButtons; + UIWindow *_window; + UIWindow *_shieldWindow; + bool _horizontal; + Rect32 _responseArea; + int _verticalAlign; + TTextAlign _align; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_response_context.cpp b/engines/wintermute/ad/ad_response_context.cpp index 0a2eff842dbd..ebfa03feea1a 100644 --- a/engines/wintermute/ad/ad_response_context.cpp +++ b/engines/wintermute/ad/ad_response_context.cpp @@ -1,71 +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/ad/ad_response_context.h" -#include "engines/wintermute/base/base_persistence_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdResponseContext, false) - -////////////////////////////////////////////////////////////////////////// -AdResponseContext::AdResponseContext(BaseGame *inGame) : BaseClass(inGame) { - _id = 0; - _context = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdResponseContext::~AdResponseContext() { - delete[] _context; - _context = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdResponseContext::persist(BasePersistenceManager *persistMgr) { - persistMgr->transfer(TMEMBER(_gameRef)); - persistMgr->transfer(TMEMBER(_context)); - persistMgr->transfer(TMEMBER(_id)); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void AdResponseContext::setContext(const char *context) { - delete[] _context; - _context = NULL; - if (context) { - _context = new char [strlen(context) + 1]; - if (_context) { - strcpy(_context, context); - } - } -} - -} // end of namespace Wintermute +/* 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_response_context.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdResponseContext, false) + +////////////////////////////////////////////////////////////////////////// +AdResponseContext::AdResponseContext(BaseGame *inGame) : BaseClass(inGame) { + _id = 0; + _context = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdResponseContext::~AdResponseContext() { + delete[] _context; + _context = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdResponseContext::persist(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_gameRef)); + persistMgr->transfer(TMEMBER(_context)); + persistMgr->transfer(TMEMBER(_id)); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void AdResponseContext::setContext(const char *context) { + delete[] _context; + _context = NULL; + if (context) { + _context = new char [strlen(context) + 1]; + if (_context) { + strcpy(_context, context); + } + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_response_context.h b/engines/wintermute/ad/ad_response_context.h index a630f975e4a1..14bc1abd939b 100644 --- a/engines/wintermute/ad/ad_response_context.h +++ b/engines/wintermute/ad/ad_response_context.h @@ -1,50 +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_ADRESPONSECONTEXT_H -#define WINTERMUTE_ADRESPONSECONTEXT_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/base.h" - -namespace Wintermute { - -class AdResponseContext : public BaseClass { -public: - void setContext(const char *context); - int _id; - char *_context; - DECLARE_PERSISTENT(AdResponseContext, BaseClass) - AdResponseContext(BaseGame *inGame); - virtual ~AdResponseContext(); - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADRESPONSECONTEXT_H +#define WINTERMUTE_ADRESPONSECONTEXT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" + +namespace Wintermute { + +class AdResponseContext : public BaseClass { +public: + void setContext(const char *context); + int _id; + char *_context; + DECLARE_PERSISTENT(AdResponseContext, BaseClass) + AdResponseContext(BaseGame *inGame); + virtual ~AdResponseContext(); + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_rot_level.cpp b/engines/wintermute/ad/ad_rot_level.cpp index 487e1f7067db..ca7ed693ade6 100644 --- a/engines/wintermute/ad/ad_rot_level.cpp +++ b/engines/wintermute/ad/ad_rot_level.cpp @@ -1,161 +1,161 @@ -/* 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_rot_level.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/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdRotLevel, false) - - -////////////////////////////////////////////////////////////////////////// -AdRotLevel::AdRotLevel(BaseGame *inGame) : BaseObject(inGame) { - _posX = 0; - _rotation = 0.0f; -} - - -////////////////////////////////////////////////////////////////////////// -AdRotLevel::~AdRotLevel() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRotLevel::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdRotLevel::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 ROTATION_LEVEL file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(ROTATION_LEVEL) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(X) -TOKEN_DEF(ROTATION) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdRotLevel::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ROTATION_LEVEL) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(X) - TOKEN_TABLE(ROTATION) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ROTATION_LEVEL) { - _gameRef->LOG(0, "'ROTATION_LEVEL' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_ROTATION: { - int i; - parser.scanStr((char *)params, "%d", &i); - _rotation = (float)i; - } - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ROTATION_LEVEL definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRotLevel::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ROTATION_LEVEL {\n"); - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "ROTATION=%d\n", (int)_rotation); - BaseClass::saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdRotLevel::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_rotation)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_rot_level.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/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdRotLevel, false) + + +////////////////////////////////////////////////////////////////////////// +AdRotLevel::AdRotLevel(BaseGame *inGame) : BaseObject(inGame) { + _posX = 0; + _rotation = 0.0f; +} + + +////////////////////////////////////////////////////////////////////////// +AdRotLevel::~AdRotLevel() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRotLevel::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdRotLevel::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 ROTATION_LEVEL file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(ROTATION_LEVEL) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(X) +TOKEN_DEF(ROTATION) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdRotLevel::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ROTATION_LEVEL) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(X) + TOKEN_TABLE(ROTATION) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ROTATION_LEVEL) { + _gameRef->LOG(0, "'ROTATION_LEVEL' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_ROTATION: { + int i; + parser.scanStr((char *)params, "%d", &i); + _rotation = (float)i; + } + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ROTATION_LEVEL definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRotLevel::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ROTATION_LEVEL {\n"); + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "ROTATION=%d\n", (int)_rotation); + BaseClass::saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdRotLevel::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_rotation)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_rot_level.h b/engines/wintermute/ad/ad_rot_level.h index 7951c7562d6b..d7f5f8edf03a 100644 --- a/engines/wintermute/ad/ad_rot_level.h +++ b/engines/wintermute/ad/ad_rot_level.h @@ -1,49 +1,49 @@ -/* 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_ADROTLEVEL_H -#define WINTERMUTE_ADROTLEVEL_H - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { - -class AdRotLevel : public BaseObject { -public: - DECLARE_PERSISTENT(AdRotLevel, BaseObject) - AdRotLevel(BaseGame *inGame); - virtual ~AdRotLevel(); - float _rotation; - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADROTLEVEL_H +#define WINTERMUTE_ADROTLEVEL_H + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class AdRotLevel : public BaseObject { +public: + DECLARE_PERSISTENT(AdRotLevel, BaseObject) + AdRotLevel(BaseGame *inGame); + virtual ~AdRotLevel(); + float _rotation; + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_scale_level.cpp b/engines/wintermute/ad/ad_scale_level.cpp index f3ec68dd6451..8b68cc5d3257 100644 --- a/engines/wintermute/ad/ad_scale_level.cpp +++ b/engines/wintermute/ad/ad_scale_level.cpp @@ -1,159 +1,159 @@ -/* 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_scale_level.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/base_file_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdScaleLevel, false) - -////////////////////////////////////////////////////////////////////////// -AdScaleLevel::AdScaleLevel(BaseGame *inGame) : BaseObject(inGame) { - _posY = 0; - _scale = 100; -} - - -////////////////////////////////////////////////////////////////////////// -AdScaleLevel::~AdScaleLevel() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScaleLevel::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdScaleLevel::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 SCALE_LEVEL file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(SCALE_LEVEL) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(Y) -TOKEN_DEF(SCALE) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdScaleLevel::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(SCALE_LEVEL) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(Y) - TOKEN_TABLE(SCALE) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SCALE_LEVEL) { - _gameRef->LOG(0, "'SCALE_LEVEL' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_SCALE: { - int i; - parser.scanStr((char *)params, "%d", &i); - _scale = (float)i; - } - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in SCALE_LEVEL definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScaleLevel::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "SCALE_LEVEL {\n"); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "SCALE=%d\n", (int)_scale); - BaseClass::saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScaleLevel::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_scale)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_scale_level.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/base_file_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdScaleLevel, false) + +////////////////////////////////////////////////////////////////////////// +AdScaleLevel::AdScaleLevel(BaseGame *inGame) : BaseObject(inGame) { + _posY = 0; + _scale = 100; +} + + +////////////////////////////////////////////////////////////////////////// +AdScaleLevel::~AdScaleLevel() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScaleLevel::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdScaleLevel::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 SCALE_LEVEL file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(SCALE_LEVEL) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(Y) +TOKEN_DEF(SCALE) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdScaleLevel::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(SCALE_LEVEL) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(Y) + TOKEN_TABLE(SCALE) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SCALE_LEVEL) { + _gameRef->LOG(0, "'SCALE_LEVEL' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_SCALE: { + int i; + parser.scanStr((char *)params, "%d", &i); + _scale = (float)i; + } + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in SCALE_LEVEL definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScaleLevel::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "SCALE_LEVEL {\n"); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "SCALE=%d\n", (int)_scale); + BaseClass::saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScaleLevel::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_scale)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scale_level.h b/engines/wintermute/ad/ad_scale_level.h index 41a2edf8c54c..628a385eb444 100644 --- a/engines/wintermute/ad/ad_scale_level.h +++ b/engines/wintermute/ad/ad_scale_level.h @@ -1,50 +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_ADSCALELEVEL_H -#define WINTERMUTE_ADSCALELEVEL_H - - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { - -class AdScaleLevel : public BaseObject { -public: - DECLARE_PERSISTENT(AdScaleLevel, BaseObject) - float _scale; - AdScaleLevel(BaseGame *inGame); - virtual ~AdScaleLevel(); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADSCALELEVEL_H +#define WINTERMUTE_ADSCALELEVEL_H + + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { + +class AdScaleLevel : public BaseObject { +public: + DECLARE_PERSISTENT(AdScaleLevel, BaseObject) + float _scale; + AdScaleLevel(BaseGame *inGame); + virtual ~AdScaleLevel(); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_scene.cpp b/engines/wintermute/ad/ad_scene.cpp index f67252350e37..e47acc63c97e 100644 --- a/engines/wintermute/ad/ad_scene.cpp +++ b/engines/wintermute/ad/ad_scene.cpp @@ -1,2986 +1,2986 @@ -/* 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_scene.h" -#include "engines/wintermute/ad/ad_actor.h" -#include "engines/wintermute/ad/ad_entity.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/ad/ad_layer.h" -#include "engines/wintermute/ad/ad_node_state.h" -#include "engines/wintermute/ad/ad_object.h" -#include "engines/wintermute/ad/ad_path.h" -#include "engines/wintermute/ad/ad_path_point.h" -#include "engines/wintermute/ad/ad_rot_level.h" -#include "engines/wintermute/ad/ad_scale_level.h" -#include "engines/wintermute/ad/ad_scene_node.h" -#include "engines/wintermute/ad/ad_scene_state.h" -#include "engines/wintermute/ad/ad_sentence.h" -#include "engines/wintermute/ad/ad_waypoint_group.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_object.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_point.h" -#include "engines/wintermute/base/base_region.h" -#include "engines/wintermute/base/base_scriptable.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_viewport.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/ui/ui_window.h" -#include "engines/wintermute/utils/utils.h" -#include "engines/wintermute/wintermute.h" -#include - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdScene, false) - -////////////////////////////////////////////////////////////////////////// -AdScene::AdScene(BaseGame *inGame) : BaseObject(inGame) { - _pfTarget = new BasePoint; - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -AdScene::~AdScene() { - cleanup(); - _gameRef->unregisterObject(_fader); - delete _pfTarget; - _pfTarget = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::setDefaults() { - _initialized = false; - _pfReady = true; - _pfTargetPath = NULL; - _pfRequester = NULL; - _mainLayer = NULL; - - _pfPointsNum = 0; - _persistentState = false; - _persistentStateSprites = true; - - _autoScroll = true; - _offsetLeft = _offsetTop = 0; - _targetOffsetLeft = _targetOffsetTop = 0; - - _lastTimeH = _lastTimeV = 0; - _scrollTimeH = _scrollTimeV = 10; - _scrollPixelsH = _scrollPixelsV = 1; - - _pfMaxTime = 15; - - _paralaxScrolling = true; - - // editor settings - _editorMarginH = _editorMarginV = 100; - - _editorColFrame = 0xE0888888; - _editorColEntity = 0xFF008000; - _editorColRegion = 0xFF0000FF; - _editorColBlocked = 0xFF800080; - _editorColWaypoints = 0xFF0000FF; - _editorColEntitySel = 0xFFFF0000; - _editorColRegionSel = 0xFFFF0000; - _editorColBlockedSel = 0xFFFF0000; - _editorColWaypointsSel = 0xFFFF0000; - _editorColScale = 0xFF00FF00; - _editorColDecor = 0xFF00FFFF; - _editorColDecorSel = 0xFFFF0000; - - _editorShowRegions = true; - _editorShowBlocked = true; - _editorShowDecor = true; - _editorShowEntities = true; - _editorShowScale = true; - - _shieldWindow = NULL; - - _fader = new BaseFader(_gameRef); - _gameRef->registerObject(_fader); - - _viewport = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::cleanup() { - BaseObject::cleanup(); - - _mainLayer = NULL; // reference only - - delete _shieldWindow; - _shieldWindow = NULL; - - _gameRef->unregisterObject(_fader); - _fader = NULL; - - for (uint32 i = 0; i < _layers.size(); i++) { - _gameRef->unregisterObject(_layers[i]); - } - _layers.clear(); - - - for (uint32 i = 0; i < _waypointGroups.size(); i++) { - _gameRef->unregisterObject(_waypointGroups[i]); - } - _waypointGroups.clear(); - - for (uint32 i = 0; i < _scaleLevels.size(); i++) { - _gameRef->unregisterObject(_scaleLevels[i]); - } - _scaleLevels.clear(); - - for (uint32 i = 0; i < _rotLevels.size(); i++) { - _gameRef->unregisterObject(_rotLevels[i]); - } - _rotLevels.clear(); - - - for (uint32 i = 0; i < _pfPath.size(); i++) { - delete _pfPath[i]; - } - _pfPath.clear(); - _pfPointsNum = 0; - - for (uint32 i = 0; i < _objects.size(); i++) { - _gameRef->unregisterObject(_objects[i]); - } - _objects.clear(); - - delete _viewport; - _viewport = NULL; - - setDefaults(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester) { - if (!_pfReady) { - return false; - } else { - _pfReady = false; - *_pfTarget = target; - _pfTargetPath = path; - _pfRequester = requester; - - _pfTargetPath->reset(); - _pfTargetPath->setReady(false); - - // prepare working path - pfPointsStart(); - - // first point - //_pfPath.add(new AdPathPoint(source.x, source.y, 0)); - - // if we're one pixel stuck, get unstuck - int startX = source.x; - int startY = source.y; - int bestDistance = 1000; - if (isBlockedAt(startX, startY, true, requester)) { - int tolerance = 2; - for (int xxx = startX - tolerance; xxx <= startX + tolerance; xxx++) { - for (int yyy = startY - tolerance; yyy <= startY + tolerance; yyy++) { - if (isWalkableAt(xxx, yyy, true, requester)) { - int distance = abs(xxx - source.x) + abs(yyy - source.y); - if (distance < bestDistance) { - startX = xxx; - startY = yyy; - - bestDistance = distance; - } - } - } - } - } - - pfPointsAdd(startX, startY, 0); - - //CorrectTargetPoint(&target.x, &target.y); - - // last point - //_pfPath.add(new AdPathPoint(target.x, target.y, INT_MAX)); - pfPointsAdd(target.x, target.y, INT_MAX); - - // active waypoints - for (uint32 i = 0; i < _waypointGroups.size(); i++) { - if (_waypointGroups[i]->_active) { - pfAddWaypointGroup(_waypointGroups[i], requester); - } - } - - - // free waypoints - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentWptGroup) { - pfAddWaypointGroup(_objects[i]->_currentWptGroup, requester); - } - } - AdGame *adGame = (AdGame *)_gameRef; - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentWptGroup) { - pfAddWaypointGroup(adGame->_objects[i]->_currentWptGroup, requester); - } - } - - return true; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::pfAddWaypointGroup(AdWaypointGroup *wpt, BaseObject *requester) { - if (!wpt->_active) { - return; - } - - for (uint32 i = 0; i < wpt->_points.size(); i++) { - if (isBlockedAt(wpt->_points[i]->x, wpt->_points[i]->y, true, requester)) { - continue; - } - - //_pfPath.add(new AdPathPoint(Wpt->_points[i]->x, Wpt->_points[i]->y, INT_MAX)); - pfPointsAdd(wpt->_points[i]->x, wpt->_points[i]->y, INT_MAX); - } -} - - -////////////////////////////////////////////////////////////////////////// -float AdScene::getZoomAt(int x, int y) { - float ret = 100; - - bool found = false; - if (_mainLayer) { - for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { - AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_blocked && node->_region->pointInRegion(x, y)) { - if (node->_region->_zoom != 0) { - ret = node->_region->_zoom; - found = true; - break; - } - } - } - } - if (!found) { - ret = getScaleAt(y); - } - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -uint32 AdScene::getAlphaAt(int x, int y, bool colorCheck) { - if (!_gameRef->_debugDebugMode) { - colorCheck = false; - } - - uint32 ret; - if (colorCheck) { - ret = 0xFFFF0000; - } else { - ret = 0xFFFFFFFF; - } - - if (_mainLayer) { - for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { - AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && (colorCheck || !node->_region->_blocked) && node->_region->pointInRegion(x, y)) { - if (!node->_region->_blocked) { - ret = node->_region->_alpha; - } - break; - } - } - } - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::isBlockedAt(int x, int y, bool checkFreeObjects, BaseObject *requester) { - bool ret = true; - - if (checkFreeObjects) { - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { - if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { - return true; - } - } - } - AdGame *adGame = (AdGame *)_gameRef; - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) { - if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { - return true; - } - } - } - } - - - if (_mainLayer) { - for (uint32 i = 0; i < _mainLayer->_nodes.size(); i++) { - AdSceneNode *node = _mainLayer->_nodes[i]; - /* - if (Node->_type == OBJECT_REGION && Node->_region->_active && Node->_region->_blocked && Node->_region->PointInRegion(X, Y)) - { - ret = true; - break; - } - */ - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { - if (node->_region->_blocked) { - ret = true; - break; - } else { - ret = false; - } - } - } - } - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::isWalkableAt(int x, int y, bool checkFreeObjects, BaseObject *requester) { - bool ret = false; - - if (checkFreeObjects) { - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { - if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { - return false; - } - } - } - AdGame *adGame = (AdGame *)_gameRef; - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) { - if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { - return false; - } - } - } - } - - - if (_mainLayer) { - for (uint32 i = 0; i < _mainLayer->_nodes.size(); i++) { - AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { - if (node->_region->_blocked) { - ret = false; - break; - } else { - ret = true; - } - } - } - } - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -int AdScene::getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester) { - double xStep, yStep, x, y; - int xLength, yLength, xCount, yCount; - int x1, y1, x2, y2; - - x1 = p1.x; - y1 = p1.y; - x2 = p2.x; - y2 = p2.y; - - xLength = abs(x2 - x1); - yLength = abs(y2 - y1); - - if (xLength > yLength) { - if (x1 > x2) { - BaseUtils::swap(&x1, &x2); - BaseUtils::swap(&y1, &y2); - } - - yStep = (double)(y2 - y1) / (double)(x2 - x1); - y = y1; - - for (xCount = x1; xCount < x2; xCount++) { - if (isBlockedAt(xCount, (int)y, true, requester)) { - return -1; - } - y += yStep; - } - } else { - if (y1 > y2) { - BaseUtils::swap(&x1, &x2); - BaseUtils::swap(&y1, &y2); - } - - xStep = (double)(x2 - x1) / (double)(y2 - y1); - x = x1; - - for (yCount = y1; yCount < y2; yCount++) { - if (isBlockedAt((int)x, yCount, true, requester)) { - return -1; - } - x += xStep; - } - } - return MAX(xLength, yLength); -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::pathFinderStep() { - int i; - // get lowest unmarked - int lowestDist = INT_MAX; - AdPathPoint *lowestPt = NULL; - - for (i = 0; i < _pfPointsNum; i++) - if (!_pfPath[i]->_marked && _pfPath[i]->_distance < lowestDist) { - lowestDist = _pfPath[i]->_distance; - lowestPt = _pfPath[i]; - } - - if (lowestPt == NULL) { // no path -> terminate PathFinder - _pfReady = true; - _pfTargetPath->setReady(true); - return; - } - - lowestPt->_marked = true; - - // target point marked, generate path and terminate - if (lowestPt->x == _pfTarget->x && lowestPt->y == _pfTarget->y) { - while (lowestPt != NULL) { - _pfTargetPath->_points.insert_at(0, new BasePoint(lowestPt->x, lowestPt->y)); - lowestPt = lowestPt->_origin; - } - - _pfReady = true; - _pfTargetPath->setReady(true); - return; - } - - // otherwise keep on searching - for (i = 0; i < _pfPointsNum; i++) - if (!_pfPath[i]->_marked) { - int j = getPointsDist(*lowestPt, *_pfPath[i], _pfRequester); - if (j != -1 && lowestPt->_distance + j < _pfPath[i]->_distance) { - _pfPath[i]->_distance = lowestPt->_distance + j; - _pfPath[i]->_origin = lowestPt; - } - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::initLoop() { -#ifdef _DEBUGxxxx - int nu_steps = 0; - uint32 start = _gameRef->_currentTime; - while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) { - PathFinderStep(); - nu_steps++; - } - if (nu_steps > 0) { - _gameRef->LOG(0, "STAT: PathFinder iterations in one loop: %d (%s) _pfMaxTime=%d", nu_steps, _pfReady ? "finished" : "not yet done", _pfMaxTime); - } -#else - uint32 start = _gameRef->_currentTime; - while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) { - pathFinderStep(); - } -#endif - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdScene::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 SCENE file '%s'", filename); - } - - setFilename(filename); - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(SCENE) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(NAME) -TOKEN_DEF(LAYER) -TOKEN_DEF(WAYPOINTS) -TOKEN_DEF(EVENTS) -TOKEN_DEF(CURSOR) -TOKEN_DEF(CAMERA) -TOKEN_DEF(ENTITY) -TOKEN_DEF(SCALE_LEVEL) -TOKEN_DEF(ROTATION_LEVEL) -TOKEN_DEF(EDITOR_MARGIN_H) -TOKEN_DEF(EDITOR_MARGIN_V) -TOKEN_DEF(EDITOR_COLOR_FRAME) -TOKEN_DEF(EDITOR_COLOR_ENTITY_SEL) -TOKEN_DEF(EDITOR_COLOR_REGION_SEL) -TOKEN_DEF(EDITOR_COLOR_DECORATION_SEL) -TOKEN_DEF(EDITOR_COLOR_BLOCKED_SEL) -TOKEN_DEF(EDITOR_COLOR_WAYPOINTS_SEL) -TOKEN_DEF(EDITOR_COLOR_REGION) -TOKEN_DEF(EDITOR_COLOR_DECORATION) -TOKEN_DEF(EDITOR_COLOR_BLOCKED) -TOKEN_DEF(EDITOR_COLOR_ENTITY) -TOKEN_DEF(EDITOR_COLOR_WAYPOINTS) -TOKEN_DEF(EDITOR_COLOR_SCALE) -TOKEN_DEF(EDITOR_SHOW_REGIONS) -TOKEN_DEF(EDITOR_SHOW_BLOCKED) -TOKEN_DEF(EDITOR_SHOW_DECORATION) -TOKEN_DEF(EDITOR_SHOW_ENTITIES) -TOKEN_DEF(EDITOR_SHOW_SCALE) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(VIEWPORT) -TOKEN_DEF(PERSISTENT_STATE_SPRITES) -TOKEN_DEF(PERSISTENT_STATE) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdScene::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(SCENE) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(LAYER) - TOKEN_TABLE(WAYPOINTS) - TOKEN_TABLE(EVENTS) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(CAMERA) - TOKEN_TABLE(ENTITY) - TOKEN_TABLE(SCALE_LEVEL) - TOKEN_TABLE(ROTATION_LEVEL) - TOKEN_TABLE(EDITOR_MARGIN_H) - TOKEN_TABLE(EDITOR_MARGIN_V) - TOKEN_TABLE(EDITOR_COLOR_FRAME) - TOKEN_TABLE(EDITOR_COLOR_ENTITY_SEL) - TOKEN_TABLE(EDITOR_COLOR_REGION_SEL) - TOKEN_TABLE(EDITOR_COLOR_DECORATION_SEL) - TOKEN_TABLE(EDITOR_COLOR_BLOCKED_SEL) - TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS_SEL) - TOKEN_TABLE(EDITOR_COLOR_REGION) - TOKEN_TABLE(EDITOR_COLOR_DECORATION) - TOKEN_TABLE(EDITOR_COLOR_BLOCKED) - TOKEN_TABLE(EDITOR_COLOR_ENTITY) - TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS) - TOKEN_TABLE(EDITOR_COLOR_SCALE) - TOKEN_TABLE(EDITOR_SHOW_REGIONS) - TOKEN_TABLE(EDITOR_SHOW_DECORATION) - TOKEN_TABLE(EDITOR_SHOW_BLOCKED) - TOKEN_TABLE(EDITOR_SHOW_ENTITIES) - TOKEN_TABLE(EDITOR_SHOW_SCALE) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(VIEWPORT) - TOKEN_TABLE(PERSISTENT_STATE_SPRITES) - TOKEN_TABLE(PERSISTENT_STATE) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - cleanup(); - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SCENE) { - _gameRef->LOG(0, "'SCENE' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - int ar, ag, ab, aa; - char camera[MAX_PATH_LENGTH] = ""; - /* float waypointHeight = -1.0f; */ - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_LAYER: { - AdLayer *layer = new AdLayer(_gameRef); - if (!layer || DID_FAIL(layer->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete layer; - layer = NULL; - } else { - _gameRef->registerObject(layer); - _layers.add(layer); - if (layer->_main) { - _mainLayer = layer; - _width = layer->_width; - _height = layer->_height; - } - } - } - break; - - case TOKEN_WAYPOINTS: { - AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); - if (!wpt || DID_FAIL(wpt->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete wpt; - wpt = NULL; - } else { - _gameRef->registerObject(wpt); - _waypointGroups.add(wpt); - } - } - break; - - case TOKEN_SCALE_LEVEL: { - AdScaleLevel *sl = new AdScaleLevel(_gameRef); - if (!sl || DID_FAIL(sl->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete sl; - sl = NULL; - } else { - _gameRef->registerObject(sl); - _scaleLevels.add(sl); - } - } - break; - - case TOKEN_ROTATION_LEVEL: { - AdRotLevel *rl = new AdRotLevel(_gameRef); - if (!rl || DID_FAIL(rl->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete rl; - rl = NULL; - } else { - _gameRef->registerObject(rl); - _rotLevels.add(rl); - } - } - break; - - case TOKEN_ENTITY: { - AdEntity *entity = new AdEntity(_gameRef); - if (!entity || DID_FAIL(entity->loadBuffer(params, false))) { - cmd = PARSERR_GENERIC; - delete entity; - entity = NULL; - } else { - addObject(entity); - } - } - 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_CAMERA: - strcpy(camera, (char *)params); - break; - - case TOKEN_EDITOR_MARGIN_H: - parser.scanStr((char *)params, "%d", &_editorMarginH); - break; - - case TOKEN_EDITOR_MARGIN_V: - parser.scanStr((char *)params, "%d", &_editorMarginV); - break; - - case TOKEN_EDITOR_COLOR_FRAME: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColFrame = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_ENTITY: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColEntity = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_ENTITY_SEL: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColEntitySel = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_REGION_SEL: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColRegionSel = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_DECORATION_SEL: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColDecorSel = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_BLOCKED_SEL: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColBlockedSel = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_WAYPOINTS_SEL: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColWaypointsSel = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_REGION: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColRegion = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_DECORATION: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColDecor = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_BLOCKED: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColBlocked = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_WAYPOINTS: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColWaypoints = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_COLOR_SCALE: - parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); - _editorColScale = BYTETORGBA(ar, ag, ab, aa); - break; - - case TOKEN_EDITOR_SHOW_REGIONS: - parser.scanStr((char *)params, "%b", &_editorShowRegions); - break; - - case TOKEN_EDITOR_SHOW_BLOCKED: - parser.scanStr((char *)params, "%b", &_editorShowBlocked); - break; - - case TOKEN_EDITOR_SHOW_DECORATION: - parser.scanStr((char *)params, "%b", &_editorShowDecor); - break; - - case TOKEN_EDITOR_SHOW_ENTITIES: - parser.scanStr((char *)params, "%b", &_editorShowEntities); - break; - - case TOKEN_EDITOR_SHOW_SCALE: - parser.scanStr((char *)params, "%b", &_editorShowScale); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_VIEWPORT: { - Rect32 rc; - parser.scanStr((char *)params, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom); - if (!_viewport) { - _viewport = new BaseViewport(_gameRef); - } - if (_viewport) { - _viewport->setRect(rc.left, rc.top, rc.right, rc.bottom, true); - } - } - - case TOKEN_PERSISTENT_STATE: - parser.scanStr((char *)params, "%b", &_persistentState); - break; - - case TOKEN_PERSISTENT_STATE_SPRITES: - parser.scanStr((char *)params, "%b", &_persistentStateSprites); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in SCENE definition"); - return STATUS_FAILED; - } - - if (_mainLayer == NULL) { - _gameRef->LOG(0, "Warning: scene '%s' has no main layer.", getFilename()); - } - - - sortScaleLevels(); - sortRotLevels(); - - _initialized = true; - - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::traverseNodes(bool doUpdate) { - if (!_initialized) { - return STATUS_OK; - } - - AdGame *adGame = (AdGame *)_gameRef; - - - ////////////////////////////////////////////////////////////////////////// - // prepare viewport - bool popViewport = false; - if (_viewport && !_gameRef->_editorMode) { - _gameRef->pushViewport(_viewport); - popViewport = true; - } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { - _gameRef->pushViewport(adGame->_sceneViewport); - popViewport = true; - } - - - ////////////////////////////////////////////////////////////////////////// - // *** adjust scroll offset - if (doUpdate) { - /* - if (_autoScroll && _gameRef->_mainObject != NULL) - { - ScrollToObject(_gameRef->_mainObject); - } - */ - - if (_autoScroll) { - // adjust horizontal scroll - if (_gameRef->_timer - _lastTimeH >= _scrollTimeH) { - _lastTimeH = _gameRef->_timer; - if (_offsetLeft < _targetOffsetLeft) { - _offsetLeft += _scrollPixelsH; - _offsetLeft = MIN(_offsetLeft, _targetOffsetLeft); - } else if (_offsetLeft > _targetOffsetLeft) { - _offsetLeft -= _scrollPixelsH; - _offsetLeft = MAX(_offsetLeft, _targetOffsetLeft); - } - } - - // adjust vertical scroll - if (_gameRef->_timer - _lastTimeV >= _scrollTimeV) { - _lastTimeV = _gameRef->_timer; - if (_offsetTop < _targetOffsetTop) { - _offsetTop += _scrollPixelsV; - _offsetTop = MIN(_offsetTop, _targetOffsetTop); - } else if (_offsetTop > _targetOffsetTop) { - _offsetTop -= _scrollPixelsV; - _offsetTop = MAX(_offsetTop, _targetOffsetTop); - } - } - - if (_offsetTop == _targetOffsetTop && _offsetLeft == _targetOffsetLeft) { - _ready = true; - } - } else { - _ready = true; // not scrolling, i.e. always ready - } - } - - - - - ////////////////////////////////////////////////////////////////////////// - int viewportWidth, viewportHeight; - getViewportSize(&viewportWidth, &viewportHeight); - - int viewportX, viewportY; - getViewportOffset(&viewportX, &viewportY); - - int scrollableX = _width - viewportWidth; - int scrollableY = _height - viewportHeight; - - double widthRatio = scrollableX <= 0 ? 0 : ((double)(_offsetLeft) / (double)scrollableX); - double heightRatio = scrollableY <= 0 ? 0 : ((double)(_offsetTop) / (double)scrollableY); - - int origX, origY; - _gameRef->getOffset(&origX, &origY); - - - - ////////////////////////////////////////////////////////////////////////// - // *** display/update everything - _gameRef->_renderer->setup2D(); - - // for each layer - /* int mainOffsetX = 0; */ - /* int mainOffsetY = 0; */ - - for (uint32 j = 0; j < _layers.size(); j++) { - if (!_layers[j]->_active) { - continue; - } - - // make layer exclusive - if (!doUpdate) { - if (_layers[j]->_closeUp && !_gameRef->_editorMode) { - if (!_shieldWindow) { - _shieldWindow = new UIWindow(_gameRef); - } - if (_shieldWindow) { - _shieldWindow->_posX = _shieldWindow->_posY = 0; - _shieldWindow->_width = _gameRef->_renderer->_width; - _shieldWindow->_height = _gameRef->_renderer->_height; - _shieldWindow->display(); - } - } - } - - if (_paralaxScrolling) { - int offsetX = (int)(widthRatio * (_layers[j]->_width - viewportWidth) - viewportX); - int offsetY = (int)(heightRatio * (_layers[j]->_height - viewportHeight) - viewportY); - _gameRef->setOffset(offsetX, offsetY); - - _gameRef->_offsetPercentX = (float)offsetX / ((float)_layers[j]->_width - viewportWidth) * 100.0f; - _gameRef->_offsetPercentY = (float)offsetY / ((float)_layers[j]->_height - viewportHeight) * 100.0f; - - //_gameRef->QuickMessageForm("%d %f", OffsetX+ViewportX, _gameRef->_offsetPercentX); - } else { - _gameRef->setOffset(_offsetLeft - viewportX, _offsetTop - viewportY); - - _gameRef->_offsetPercentX = (float)(_offsetLeft - viewportX) / ((float)_layers[j]->_width - viewportWidth) * 100.0f; - _gameRef->_offsetPercentY = (float)(_offsetTop - viewportY) / ((float)_layers[j]->_height - viewportHeight) * 100.0f; - } - - - // for each node - for (uint32 k = 0; k < _layers[j]->_nodes.size(); k++) { - AdSceneNode *node = _layers[j]->_nodes[k]; - switch (node->_type) { - case OBJECT_ENTITY: - if (node->_entity->_active && (_gameRef->_editorMode || !node->_entity->_editorOnly)) { - _gameRef->_renderer->setup2D(); - - if (doUpdate) { - node->_entity->update(); - } else { - node->_entity->display(); - } - } - break; - - case OBJECT_REGION: { - if (node->_region->_blocked) { - break; - } - if (node->_region->_decoration) { - break; - } - - if (!doUpdate) { - displayRegionContent(node->_region); - } - } - break; - default: - error("AdScene::TraverseNodes - Unhandled enum"); - break; - } // switch - } // each node - - // display/update all objects which are off-regions - if (_layers[j]->_main) { - if (doUpdate) { - updateFreeObjects(); - } else { - displayRegionContent(NULL); - } - } - } // each layer - - - // restore state - _gameRef->setOffset(origX, origY); - _gameRef->_renderer->setup2D(); - - // display/update fader - if (_fader) { - if (doUpdate) { - _fader->update(); - } else { - _fader->display(); - } - } - - if (popViewport) { - _gameRef->popViewport(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::display() { - return traverseNodes(false); -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::updateFreeObjects() { - AdGame *adGame = (AdGame *)_gameRef; - // 3D-code removed - // bool is3DSet; - - // *** update all active objects - // is3DSet = false; - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (!adGame->_objects[i]->_active) { - continue; - } - // 3D-code removed - adGame->_objects[i]->update(); - adGame->_objects[i]->_drawn = false; - } - - - for (uint32 i = 0; i < _objects.size(); i++) { - if (!_objects[i]->_active) { - continue; - } - - _objects[i]->update(); - _objects[i]->_drawn = false; - } - - - if (_autoScroll && _gameRef->_mainObject != NULL) { - scrollToObject(_gameRef->_mainObject); - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) { - AdGame *adGame = (AdGame *)_gameRef; - BaseArray objects; - AdObject *obj; - - // global objects - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - obj = adGame->_objects[i]; - if (obj->_active && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - objects.add(obj); - } - } - - // scene objects - for (uint32 i = 0; i < _objects.size(); i++) { - obj = _objects[i]; - if (obj->_active && !obj->_editorOnly && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - objects.add(obj); - } - } - - // sort by _posY - Common::sort(objects.begin(), objects.end(), AdScene::compareObjs); - - // display them - for (uint32 i = 0; i < objects.size(); i++) { - obj = objects[i]; - - if (display3DOnly && !obj->_is3D) { - continue; - } - - _gameRef->_renderer->setup2D(); - - if (_gameRef->_editorMode || !obj->_editorOnly) { - obj->display(); - } - obj->_drawn = true; - } - - - // display design only objects - if (!display3DOnly) { - if (_gameRef->_editorMode && region == NULL) { - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && _objects[i]->_editorOnly) { - _objects[i]->display(); - _objects[i]->_drawn = true; - } - } - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -int AdScene::compareObjs(const void *obj1, const void *obj2) { - const AdObject *object1 = *(const AdObject *const *)obj1; - const AdObject *object2 = *(const AdObject *const *)obj2; - - if (object1->_posY < object2->_posY) { - return -1; - } else if (object1->_posY > object2->_posY) { - return 1; - } else { - return 0; - } -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::displayRegionContentOld(AdRegion *region) { - AdGame *adGame = (AdGame *)_gameRef; - AdObject *obj; - - // display all objects in region sorted by _posY - do { - obj = NULL; - int minY = INT_MAX; - - // global objects - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - if (adGame->_objects[i]->_active && !adGame->_objects[i]->_drawn && adGame->_objects[i]->_posY < minY && (adGame->_objects[i]->_stickRegion == region || region == NULL || (adGame->_objects[i]->_stickRegion == NULL && region->pointInRegion(adGame->_objects[i]->_posX, adGame->_objects[i]->_posY)))) { - obj = adGame->_objects[i]; - minY = adGame->_objects[i]->_posY; - } - } - - // scene objects - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && !_objects[i]->_editorOnly && !_objects[i]->_drawn && _objects[i]->_posY < minY && (_objects[i]->_stickRegion == region || region == NULL || (_objects[i]->_stickRegion == NULL && region->pointInRegion(_objects[i]->_posX, _objects[i]->_posY)))) { - obj = _objects[i]; - minY = _objects[i]->_posY; - } - } - - - if (obj != NULL) { - _gameRef->_renderer->setup2D(); - - if (_gameRef->_editorMode || !obj->_editorOnly) { - obj->display(); - } - obj->_drawn = true; - } - } while (obj != NULL); - - - // design only objects - if (_gameRef->_editorMode && region == NULL) { - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_active && _objects[i]->_editorOnly) { - _objects[i]->display(); - _objects[i]->_drawn = true; - } - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::update() { - return traverseNodes(true); -} - -////////////////////////////////////////////////////////////////////////// -void AdScene::scrollTo(int offsetX, int offsetY) { - int viewportWidth, viewportHeight; - getViewportSize(&viewportWidth, &viewportHeight); - - int origOffsetLeft = _targetOffsetLeft; - int origOffsetTop = _targetOffsetTop; - - _targetOffsetLeft = MAX(0, offsetX - viewportWidth / 2); - _targetOffsetLeft = MIN(_targetOffsetLeft, _width - viewportWidth); - - _targetOffsetTop = MAX(0, offsetY - viewportHeight / 2); - _targetOffsetTop = MIN(_targetOffsetTop, _height - viewportHeight); - - - if (_gameRef->_mainObject && _gameRef->_mainObject->_is3D) { - if (abs(origOffsetLeft - _targetOffsetLeft) < 5) { - _targetOffsetLeft = origOffsetLeft; - } - if (abs(origOffsetTop - _targetOffsetTop) < 5) { - _targetOffsetTop = origOffsetTop; - } - //_targetOffsetTop = 0; - } - - _ready = false; -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::scrollToObject(BaseObject *object) { - if (object) { - scrollTo(object->_posX, object->_posY - object->getHeight() / 2); - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::skipToObject(BaseObject *object) { - if (object) { - skipTo(object->_posX, object->_posY - object->getHeight() / 2); - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::skipTo(int offsetX, int offsetY) { - int viewportWidth, viewportHeight; - getViewportSize(&viewportWidth, &viewportHeight); - - _offsetLeft = MAX(0, offsetX - viewportWidth / 2); - _offsetLeft = MIN(_offsetLeft, _width - viewportWidth); - - _offsetTop = MAX(0, offsetY - viewportHeight / 2); - _offsetTop = MIN(_offsetTop, _height - viewportHeight); - - _targetOffsetLeft = _offsetLeft; - _targetOffsetTop = _offsetTop; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // LoadActor - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "LoadActor") == 0) { - stack->correctParams(1); - AdActor *act = new AdActor(_gameRef); - if (act && DID_SUCCEED(act->loadFile(stack->pop()->getString()))) { - addObject(act); - stack->pushNative(act, true); - } else { - delete act; - act = NULL; - stack->pushNULL(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadEntity") == 0) { - stack->correctParams(1); - AdEntity *ent = new AdEntity(_gameRef); - if (ent && DID_SUCCEED(ent->loadFile(stack->pop()->getString()))) { - addObject(ent); - stack->pushNative(ent, true); - } else { - delete ent; - ent = NULL; - stack->pushNULL(); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateEntity") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdEntity *ent = new AdEntity(_gameRef); - addObject(ent); - if (!val->isNULL()) { - ent->setName(val->getString()); - } - stack->pushNative(ent, true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // UnloadObject / UnloadActor / UnloadEntity / UnloadActor3D / DeleteEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "UnloadObject") == 0 || strcmp(name, "UnloadActor") == 0 || strcmp(name, "UnloadEntity") == 0 || strcmp(name, "UnloadActor3D") == 0 || strcmp(name, "DeleteEntity") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - AdObject *obj = (AdObject *)val->getNative(); - removeObject(obj); - if (val->getType() == VAL_VARIABLE_REF) { - val->setNULL(); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SkipTo - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SkipTo") == 0) { - stack->correctParams(2); - ScValue *val1 = stack->pop(); - ScValue *val2 = stack->pop(); - if (val1->isNative()) { - skipToObject((BaseObject *)val1->getNative()); - } else { - skipTo(val1->getInt(), val2->getInt()); - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollTo / ScrollToAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollTo") == 0 || strcmp(name, "ScrollToAsync") == 0) { - stack->correctParams(2); - ScValue *val1 = stack->pop(); - ScValue *val2 = stack->pop(); - if (val1->isNative()) { - scrollToObject((BaseObject *)val1->getNative()); - } else { - scrollTo(val1->getInt(), val2->getInt()); - } - if (strcmp(name, "ScrollTo") == 0) { - script->waitForExclusive(this); - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetLayer - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetLayer") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - if (val->isInt()) { - int layer = val->getInt(); - if (layer < 0 || layer >= (int32)_layers.size()) { - stack->pushNULL(); - } else { - stack->pushNative(_layers[layer], true); - } - } else { - const char *layerName = val->getString(); - bool layerFound = false; - for (uint32 i = 0; i < _layers.size(); i++) { - if (scumm_stricmp(layerName, _layers[i]->getName()) == 0) { - stack->pushNative(_layers[i], true); - layerFound = true; - break; - } - } - if (!layerFound) { - stack->pushNULL(); - } - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetWaypointGroup - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetWaypointGroup") == 0) { - stack->correctParams(1); - int group = stack->pop()->getInt(); - if (group < 0 || group >= (int32)_waypointGroups.size()) { - stack->pushNULL(); - } else { - stack->pushNative(_waypointGroups[group], true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetNode - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetNode") == 0) { - stack->correctParams(1); - const char *nodeName = stack->pop()->getString(); - - BaseObject *node = getNodeByName(nodeName); - if (node) { - stack->pushNative((BaseScriptable *)node, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetFreeNode - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetFreeNode") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdObject *ret = NULL; - if (val->isInt()) { - int index = val->getInt(); - if (index >= 0 && index < (int32)_objects.size()) { - ret = _objects[index]; - } - } else { - const char *nodeName = val->getString(); - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i] && _objects[i]->getName() && scumm_stricmp(_objects[i]->getName(), nodeName) == 0) { - ret = _objects[i]; - break; - } - } - } - if (ret) { - stack->pushNative(ret, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetRegionAt - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetRegionAt") == 0) { - stack->correctParams(3); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - ScValue *val = stack->pop(); - - bool includeDecors = false; - if (!val->isNULL()) { - includeDecors = val->getBool(); - } - - if (_mainLayer) { - for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { - AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) { - if (node->_region->_decoration && !includeDecors) { - continue; - } - - stack->pushNative(node->_region, true); - return STATUS_OK; - } - } - } - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsBlockedAt - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsBlockedAt") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - - stack->pushBool(isBlockedAt(x, y)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsWalkableAt - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsWalkableAt") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - - stack->pushBool(isWalkableAt(x, y)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetScaleAt - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetScaleAt") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - - stack->pushFloat(getZoomAt(x, y)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetRotationAt - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetRotationAt") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - - stack->pushFloat(getRotationAt(x, y)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // IsScrolling - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsScrolling") == 0) { - stack->correctParams(0); - bool ret = false; - if (_autoScroll) { - if (_targetOffsetLeft != _offsetLeft || _targetOffsetTop != _offsetTop) { - ret = true; - } - } - - stack->pushBool(ret); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeOut / FadeOutAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeOut") == 0 || strcmp(name, "FadeOutAsync") == 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); - - _fader->fadeOut(BYTETORGBA(red, green, blue, alpha), duration); - if (strcmp(name, "FadeOutAsync") != 0) { - script->waitFor(_fader); - } - - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeIn / FadeInAsync - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeIn") == 0 || strcmp(name, "FadeInAsync") == 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); - - _fader->fadeIn(BYTETORGBA(red, green, blue, alpha), duration); - if (strcmp(name, "FadeInAsync") != 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; - } - - ////////////////////////////////////////////////////////////////////////// - // IsPointInViewport - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "IsPointInViewport") == 0) { - stack->correctParams(2); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - stack->pushBool(pointInViewport(x, y)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetViewport - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetViewport") == 0) { - stack->correctParams(4); - int x = stack->pop()->getInt(); - int y = stack->pop()->getInt(); - int width = stack->pop()->getInt(); - int height = stack->pop()->getInt(); - - if (width <= 0) { - width = _gameRef->_renderer->_width; - } - if (height <= 0) { - height = _gameRef->_renderer->_height; - } - - if (!_viewport) { - _viewport = new BaseViewport(_gameRef); - } - if (_viewport) { - _viewport->setRect(x, y, x + width, y + height); - } - - stack->pushBool(true); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddLayer - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddLayer") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdLayer *layer = new AdLayer(_gameRef); - if (!val->isNULL()) { - layer->setName(val->getString()); - } - if (_mainLayer) { - layer->_width = _mainLayer->_width; - layer->_height = _mainLayer->_height; - } - _layers.add(layer); - _gameRef->registerObject(layer); - - stack->pushNative(layer, true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InsertLayer - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InsertLayer") == 0) { - stack->correctParams(2); - int index = stack->pop()->getInt(); - ScValue *val = stack->pop(); - - AdLayer *layer = new AdLayer(_gameRef); - if (!val->isNULL()) { - layer->setName(val->getString()); - } - if (_mainLayer) { - layer->_width = _mainLayer->_width; - layer->_height = _mainLayer->_height; - } - if (index < 0) { - index = 0; - } - if (index <= (int32)_layers.size() - 1) { - _layers.insert_at(index, layer); - } else { - _layers.add(layer); - } - - _gameRef->registerObject(layer); - - stack->pushNative(layer, true); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteLayer - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteLayer") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - AdLayer *toDelete = NULL; - if (val->isNative()) { - BaseScriptable *temp = val->getNative(); - for (uint32 i = 0; i < _layers.size(); i++) { - if (_layers[i] == temp) { - toDelete = _layers[i]; - break; - } - } - } else { - int index = val->getInt(); - if (index >= 0 && index < (int32)_layers.size()) { - toDelete = _layers[index]; - } - } - if (toDelete == NULL) { - stack->pushBool(false); - return STATUS_OK; - } - - if (toDelete->_main) { - script->runtimeError("Scene.DeleteLayer - cannot delete main scene layer"); - stack->pushBool(false); - return STATUS_OK; - } - - for (uint32 i = 0; i < _layers.size(); i++) { - if (_layers[i] == toDelete) { - _layers.remove_at(i); - _gameRef->unregisterObject(toDelete); - break; - } - } - stack->pushBool(true); - return STATUS_OK; - } else { - return BaseObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdScene::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("scene"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumLayers (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumLayers") == 0) { - _scValue->setInt(_layers.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumWaypointGroups (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumWaypointGroups") == 0) { - _scValue->setInt(_waypointGroups.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // MainLayer (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MainLayer") == 0) { - if (_mainLayer) { - _scValue->setNative(_mainLayer, true); - } else { - _scValue->setNULL(); - } - - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumFreeNodes (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumFreeNodes") == 0) { - _scValue->setInt(_objects.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // MouseX (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MouseX") == 0) { - int viewportX; - getViewportOffset(&viewportX); - - _scValue->setInt(_gameRef->_mousePos.x + _offsetLeft - viewportX); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // MouseY (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MouseY") == 0) { - int viewportY; - getViewportOffset(NULL, &viewportY); - - _scValue->setInt(_gameRef->_mousePos.y + _offsetTop - viewportY); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // AutoScroll - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AutoScroll") == 0) { - _scValue->setBool(_autoScroll); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // PersistentState - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PersistentState") == 0) { - _scValue->setBool(_persistentState); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // PersistentStateSprites - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PersistentStateSprites") == 0) { - _scValue->setBool(_persistentStateSprites); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollPixelsX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollPixelsX") == 0) { - _scValue->setInt(_scrollPixelsH); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollPixelsY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollPixelsY") == 0) { - _scValue->setInt(_scrollPixelsV); - return _scValue; - } - - - ////////////////////////////////////////////////////////////////////////// - // ScrollSpeedX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollSpeedX") == 0) { - _scValue->setInt(_scrollTimeH); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollSpeedY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollSpeedY") == 0) { - _scValue->setInt(_scrollTimeV); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // OffsetX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "OffsetX") == 0) { - _scValue->setInt(_offsetLeft); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // OffsetY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "OffsetY") == 0) { - _scValue->setInt(_offsetTop); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Width (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Width") == 0) { - if (_mainLayer) { - _scValue->setInt(_mainLayer->_width); - } else { - _scValue->setInt(0); - } - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Height (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Height") == 0) { - if (_mainLayer) { - _scValue->setInt(_mainLayer->_height); - } else { - _scValue->setInt(0); - } - return _scValue; - } else { - return BaseObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AutoScroll - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AutoScroll") == 0) { - _autoScroll = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PersistentState - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PersistentState") == 0) { - _persistentState = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PersistentStateSprites - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PersistentStateSprites") == 0) { - _persistentStateSprites = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollPixelsX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollPixelsX") == 0) { - _scrollPixelsH = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollPixelsY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollPixelsY") == 0) { - _scrollPixelsV = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollSpeedX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollSpeedX") == 0) { - _scrollTimeH = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ScrollSpeedY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ScrollSpeedY") == 0) { - _scrollTimeV = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // OffsetX - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "OffsetX") == 0) { - _offsetLeft = value->getInt(); - - int viewportWidth, viewportHeight; - getViewportSize(&viewportWidth, &viewportHeight); - - _offsetLeft = MAX(0, _offsetLeft - viewportWidth / 2); - _offsetLeft = MIN(_offsetLeft, _width - viewportWidth); - _targetOffsetLeft = _offsetLeft; - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // OffsetY - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "OffsetY") == 0) { - _offsetTop = value->getInt(); - - int viewportWidth, viewportHeight; - getViewportSize(&viewportWidth, &viewportHeight); - - _offsetTop = MAX(0, _offsetTop - viewportHeight / 2); - _offsetTop = MIN(_offsetTop, _height - viewportHeight); - _targetOffsetTop = _offsetTop; - - return STATUS_OK; - } else { - return BaseObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdScene::scToString() { - return "[scene object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::addObject(AdObject *object) { - _objects.add(object); - return _gameRef->registerObject(object); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::removeObject(AdObject *object) { - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i] == object) { - _objects.remove_at(i); - return _gameRef->unregisterObject(object); - } - } - return STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "SCENE {\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - if (_persistentState) { - buffer->putTextIndent(indent + 2, "PERSISTENT_STATE=%s\n", _persistentState ? "TRUE" : "FALSE"); - } - - if (!_persistentStateSprites) { - buffer->putTextIndent(indent + 2, "PERSISTENT_STATE_SPRITES=%s\n", _persistentStateSprites ? "TRUE" : "FALSE"); - } - - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // properties - if (_scProp) { - _scProp->saveAsText(buffer, indent + 2); - } - - // viewport - if (_viewport) { - Rect32 *rc = _viewport->getRect(); - buffer->putTextIndent(indent + 2, "VIEWPORT { %d, %d, %d, %d }\n", rc->left, rc->top, rc->right, rc->bottom); - } - - - - // editor settings - buffer->putTextIndent(indent + 2, "; ----- editor settings\n"); - buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_H=%d\n", _editorMarginH); - buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_V=%d\n", _editorMarginV); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_FRAME { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColFrame), RGBCOLGetG(_editorColFrame), RGBCOLGetB(_editorColFrame), RGBCOLGetA(_editorColFrame)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntitySel), RGBCOLGetG(_editorColEntitySel), RGBCOLGetB(_editorColEntitySel), RGBCOLGetA(_editorColEntitySel)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegionSel), RGBCOLGetG(_editorColRegionSel), RGBCOLGetB(_editorColRegionSel), RGBCOLGetA(_editorColRegionSel)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlockedSel), RGBCOLGetG(_editorColBlockedSel), RGBCOLGetB(_editorColBlockedSel), RGBCOLGetA(_editorColBlockedSel)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecorSel), RGBCOLGetG(_editorColDecorSel), RGBCOLGetB(_editorColDecorSel), RGBCOLGetA(_editorColDecorSel)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypointsSel), RGBCOLGetG(_editorColWaypointsSel), RGBCOLGetB(_editorColWaypointsSel), RGBCOLGetA(_editorColWaypointsSel)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntity), RGBCOLGetG(_editorColEntity), RGBCOLGetB(_editorColEntity), RGBCOLGetA(_editorColEntity)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegion), RGBCOLGetG(_editorColRegion), RGBCOLGetB(_editorColRegion), RGBCOLGetA(_editorColRegion)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecor), RGBCOLGetG(_editorColDecor), RGBCOLGetB(_editorColDecor), RGBCOLGetA(_editorColDecor)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlocked), RGBCOLGetG(_editorColBlocked), RGBCOLGetB(_editorColBlocked), RGBCOLGetA(_editorColBlocked)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypoints), RGBCOLGetG(_editorColWaypoints), RGBCOLGetB(_editorColWaypoints), RGBCOLGetA(_editorColWaypoints)); - buffer->putTextIndent(indent + 2, "EDITOR_COLOR_SCALE { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColScale), RGBCOLGetG(_editorColScale), RGBCOLGetB(_editorColScale), RGBCOLGetA(_editorColScale)); - - buffer->putTextIndent(indent + 2, "EDITOR_SHOW_REGIONS=%s\n", _editorShowRegions ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SHOW_BLOCKED=%s\n", _editorShowBlocked ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SHOW_DECORATION=%s\n", _editorShowDecor ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SHOW_ENTITIES=%s\n", _editorShowEntities ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SHOW_SCALE=%s\n", _editorShowScale ? "TRUE" : "FALSE"); - - buffer->putTextIndent(indent + 2, "\n"); - - BaseClass::saveAsText(buffer, indent + 2); - - // waypoints - buffer->putTextIndent(indent + 2, "; ----- waypoints\n"); - for (uint32 i = 0; i < _waypointGroups.size(); i++) { - _waypointGroups[i]->saveAsText(buffer, indent + 2); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // layers - buffer->putTextIndent(indent + 2, "; ----- layers\n"); - for (uint32 i = 0; i < _layers.size(); i++) { - _layers[i]->saveAsText(buffer, indent + 2); - } - - // scale levels - buffer->putTextIndent(indent + 2, "; ----- scale levels\n"); - for (uint32 i = 0; i < _scaleLevels.size(); i++) { - _scaleLevels[i]->saveAsText(buffer, indent + 2); - } - - // rotation levels - buffer->putTextIndent(indent + 2, "; ----- rotation levels\n"); - for (uint32 i = 0; i < _rotLevels.size(); i++) { - _rotLevels[i]->saveAsText(buffer, indent + 2); - } - - - buffer->putTextIndent(indent + 2, "\n"); - - // free entities - buffer->putTextIndent(indent + 2, "; ----- free entities\n"); - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { - _objects[i]->saveAsText(buffer, indent + 2); - - } - } - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::sortScaleLevels() { - if (_scaleLevels.size() == 0) { - return STATUS_OK; - } - bool changed; - do { - changed = false; - for (uint32 i = 0; i < _scaleLevels.size() - 1; i++) { - if (_scaleLevels[i]->_posY > _scaleLevels[i + 1]->_posY) { - AdScaleLevel *sl = _scaleLevels[i]; - _scaleLevels[i] = _scaleLevels[i + 1]; - _scaleLevels[i + 1] = sl; - - changed = true; - } - } - - } while (changed); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::sortRotLevels() { - if (_rotLevels.size() == 0) { - return STATUS_OK; - } - bool changed; - do { - changed = false; - for (uint32 i = 0; i < _rotLevels.size() - 1; i++) { - if (_rotLevels[i]->_posX > _rotLevels[i + 1]->_posX) { - AdRotLevel *rl = _rotLevels[i]; - _rotLevels[i] = _rotLevels[i + 1]; - _rotLevels[i + 1] = rl; - - changed = true; - } - } - - } while (changed); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -float AdScene::getScaleAt(int Y) { - AdScaleLevel *prev = NULL; - AdScaleLevel *next = NULL; - - for (uint32 i = 0; i < _scaleLevels.size(); i++) { - /* AdScaleLevel *xxx = _scaleLevels[i];*/ - /* int j = _scaleLevels.size(); */ - if (_scaleLevels[i]->_posY < Y) { - prev = _scaleLevels[i]; - } else { - next = _scaleLevels[i]; - break; - } - } - - if (prev == NULL || next == NULL) { - return 100; - } - - int delta_y = next->_posY - prev->_posY; - float delta_scale = next->_scale - prev->_scale; - Y -= prev->_posY; - - float percent = (float)Y / ((float)delta_y / 100.0f); - return prev->_scale + delta_scale / 100 * percent; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::persist(BasePersistenceManager *persistMgr) { - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_autoScroll)); - persistMgr->transfer(TMEMBER(_editorColBlocked)); - persistMgr->transfer(TMEMBER(_editorColBlockedSel)); - persistMgr->transfer(TMEMBER(_editorColDecor)); - persistMgr->transfer(TMEMBER(_editorColDecorSel)); - persistMgr->transfer(TMEMBER(_editorColEntity)); - persistMgr->transfer(TMEMBER(_editorColEntitySel)); - persistMgr->transfer(TMEMBER(_editorColFrame)); - persistMgr->transfer(TMEMBER(_editorColRegion)); - persistMgr->transfer(TMEMBER(_editorColRegionSel)); - persistMgr->transfer(TMEMBER(_editorColScale)); - persistMgr->transfer(TMEMBER(_editorColWaypoints)); - persistMgr->transfer(TMEMBER(_editorColWaypointsSel)); - persistMgr->transfer(TMEMBER(_editorMarginH)); - persistMgr->transfer(TMEMBER(_editorMarginV)); - persistMgr->transfer(TMEMBER(_editorShowBlocked)); - persistMgr->transfer(TMEMBER(_editorShowDecor)); - persistMgr->transfer(TMEMBER(_editorShowEntities)); - persistMgr->transfer(TMEMBER(_editorShowRegions)); - persistMgr->transfer(TMEMBER(_editorShowScale)); - persistMgr->transfer(TMEMBER(_fader)); - persistMgr->transfer(TMEMBER(_height)); - persistMgr->transfer(TMEMBER(_initialized)); - persistMgr->transfer(TMEMBER(_lastTimeH)); - persistMgr->transfer(TMEMBER(_lastTimeV)); - _layers.persist(persistMgr); - persistMgr->transfer(TMEMBER(_mainLayer)); - _objects.persist(persistMgr); - persistMgr->transfer(TMEMBER(_offsetLeft)); - persistMgr->transfer(TMEMBER(_offsetTop)); - persistMgr->transfer(TMEMBER(_paralaxScrolling)); - persistMgr->transfer(TMEMBER(_persistentState)); - persistMgr->transfer(TMEMBER(_persistentStateSprites)); - persistMgr->transfer(TMEMBER(_pfMaxTime)); - _pfPath.persist(persistMgr); - persistMgr->transfer(TMEMBER(_pfPointsNum)); - persistMgr->transfer(TMEMBER(_pfReady)); - persistMgr->transfer(TMEMBER(_pfRequester)); - persistMgr->transfer(TMEMBER(_pfTarget)); - persistMgr->transfer(TMEMBER(_pfTargetPath)); - _rotLevels.persist(persistMgr); - _scaleLevels.persist(persistMgr); - persistMgr->transfer(TMEMBER(_scrollPixelsH)); - persistMgr->transfer(TMEMBER(_scrollPixelsV)); - persistMgr->transfer(TMEMBER(_scrollTimeH)); - persistMgr->transfer(TMEMBER(_scrollTimeV)); - persistMgr->transfer(TMEMBER(_shieldWindow)); - persistMgr->transfer(TMEMBER(_targetOffsetLeft)); - persistMgr->transfer(TMEMBER(_targetOffsetTop)); - _waypointGroups.persist(persistMgr); - persistMgr->transfer(TMEMBER(_viewport)); - persistMgr->transfer(TMEMBER(_width)); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::afterLoad() { - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester) { - double xStep, yStep, x, y; - int xLength, yLength, xCount, yCount; - int x1, y1, x2, y2; - - x1 = *targetX; - y1 = *targetY; - x2 = startX; - y2 = startY; - - - xLength = abs(x2 - x1); - yLength = abs(y2 - y1); - - if (xLength > yLength) { - - yStep = fabs((double)(y2 - y1) / (double)(x2 - x1)); - y = y1; - - for (xCount = x1; xCount < x2; xCount++) { - if (isWalkableAt(xCount, (int)y, checkFreeObjects, requester)) { - *targetX = xCount; - *targetY = (int)y; - return STATUS_OK; - } - y += yStep; - } - } else { - - xStep = fabs((double)(x2 - x1) / (double)(y2 - y1)); - x = x1; - - for (yCount = y1; yCount < y2; yCount++) { - if (isWalkableAt((int)x, yCount, checkFreeObjects, requester)) { - *targetX = (int)x; - *targetY = yCount; - return STATUS_OK; - } - x += xStep; - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::correctTargetPoint(int startX, int startY, int *argX, int *argY, bool checkFreeObjects, BaseObject *requester) { - int x = *argX; - int y = *argY; - - if (isWalkableAt(x, y, checkFreeObjects, requester) || !_mainLayer) { - return STATUS_OK; - } - - // right - int lengthRight = 0; - bool foundRight = false; - for (x = *argX, y = *argY; x < _mainLayer->_width; x++, lengthRight++) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x - 5, y, checkFreeObjects, requester)) { - foundRight = true; - break; - } - } - - // left - int lengthLeft = 0; - bool foundLeft = false; - for (x = *argX, y = *argY; x >= 0; x--, lengthLeft--) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x + 5, y, checkFreeObjects, requester)) { - foundLeft = true; - break; - } - } - - // up - int lengthUp = 0; - bool foundUp = false; - for (x = *argX, y = *argY; y >= 0; y--, lengthUp--) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y + 5, checkFreeObjects, requester)) { - foundUp = true; - break; - } - } - - // down - int lengthDown = 0; - bool foundDown = false; - for (x = *argX, y = *argY; y < _mainLayer->_height; y++, lengthDown++) { - if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y - 5, checkFreeObjects, requester)) { - foundDown = true; - break; - } - } - - if (!foundLeft && !foundRight && !foundUp && !foundDown) { - return STATUS_OK; - } - - int offsetX = INT_MAX, offsetY = INT_MAX; - - if (foundLeft && foundRight) { - if (abs(lengthLeft) < abs(lengthRight)) { - offsetX = lengthLeft; - } else { - offsetX = lengthRight; - } - } else if (foundLeft) { - offsetX = lengthLeft; - } else if (foundRight) { - offsetX = lengthRight; - } - - if (foundUp && foundDown) { - if (abs(lengthUp) < abs(lengthDown)) { - offsetY = lengthUp; - } else { - offsetY = lengthDown; - } - } else if (foundUp) { - offsetY = lengthUp; - } else if (foundDown) { - offsetY = lengthDown; - } - - if (abs(offsetX) < abs(offsetY)) { - *argX = *argX + offsetX; - } else { - *argY = *argY + offsetY; - } - - if (!isWalkableAt(*argX, *argY)) { - return correctTargetPoint2(startX, startY, argX, argY, checkFreeObjects, requester); - } else { - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::pfPointsStart() { - _pfPointsNum = 0; -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::pfPointsAdd(int x, int y, int distance) { - if (_pfPointsNum >= (int32)_pfPath.size()) { - _pfPath.add(new AdPathPoint(x, y, distance)); - } else { - _pfPath[_pfPointsNum]->x = x; - _pfPath[_pfPointsNum]->y = y; - _pfPath[_pfPointsNum]->_distance = distance; - _pfPath[_pfPointsNum]->_marked = false; - _pfPath[_pfPointsNum]->_origin = NULL; - } - - _pfPointsNum++; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getViewportOffset(int *offsetX, int *offsetY) { - AdGame *adGame = (AdGame *)_gameRef; - if (_viewport && !_gameRef->_editorMode) { - if (offsetX) { - *offsetX = _viewport->_offsetX; - } - if (offsetY) { - *offsetY = _viewport->_offsetY; - } - } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { - if (offsetX) { - *offsetX = adGame->_sceneViewport->_offsetX; - } - if (offsetY) { - *offsetY = adGame->_sceneViewport->_offsetY; - } - } else { - if (offsetX) { - *offsetX = 0; - } - if (offsetY) { - *offsetY = 0; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getViewportSize(int *width, int *height) { - AdGame *adGame = (AdGame *)_gameRef; - if (_viewport && !_gameRef->_editorMode) { - if (width) { - *width = _viewport->getWidth(); - } - if (height) { - *height = _viewport->getHeight(); - } - } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { - if (width) { - *width = adGame->_sceneViewport->getWidth(); - } - if (height) { - *height = adGame->_sceneViewport->getHeight(); - } - } else { - if (width) { - *width = _gameRef->_renderer->_width; - } - if (height) { - *height = _gameRef->_renderer->_height; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -int AdScene::getOffsetLeft() { - int viewportX; - getViewportOffset(&viewportX); - - return _offsetLeft - viewportX; -} - - -////////////////////////////////////////////////////////////////////////// -int AdScene::getOffsetTop() { - int viewportY; - getViewportOffset(NULL, &viewportY); - - return _offsetTop - viewportY; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::pointInViewport(int x, int y) { - int left, top, width, height; - - getViewportOffset(&left, &top); - getViewportSize(&width, &height); - - return x >= left && x <= left + width && y >= top && y <= top + height; -} - - -////////////////////////////////////////////////////////////////////////// -void AdScene::setOffset(int offsetLeft, int offsetTop) { - _offsetLeft = offsetLeft; - _offsetTop = offsetTop; -} - - -////////////////////////////////////////////////////////////////////////// -BaseObject *AdScene::getNodeByName(const char *name) { - BaseObject *ret = NULL; - - // dependent objects - for (uint32 i = 0; i < _layers.size(); i++) { - AdLayer *layer = _layers[i]; - for (uint32 j = 0; j < layer->_nodes.size(); j++) { - AdSceneNode *node = layer->_nodes[j]; - if ((node->_type == OBJECT_ENTITY && !scumm_stricmp(name, node->_entity->getName())) || - (node->_type == OBJECT_REGION && !scumm_stricmp(name, node->_region->getName()))) { - switch (node->_type) { - case OBJECT_ENTITY: - ret = node->_entity; - break; - case OBJECT_REGION: - ret = node->_region; - break; - default: - ret = NULL; - } - return ret; - } - } - } - - // free entities - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->getName())) { - return _objects[i]; - } - } - - // waypoint groups - for (uint32 i = 0; i < _waypointGroups.size(); i++) { - if (!scumm_stricmp(name, _waypointGroups[i]->getName())) { - return _waypointGroups[i]; - } - } - - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::saveState() { - return persistState(true); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::loadState() { - return persistState(false); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::persistState(bool saving) { - if (!_persistentState) { - return STATUS_OK; - } - - AdGame *adGame = (AdGame *)_gameRef; - AdSceneState *state = adGame->getSceneState(getFilename(), saving); - if (!state) { - return STATUS_OK; - } - - AdNodeState *nodeState; - - // dependent objects - for (uint32 i = 0; i < _layers.size(); i++) { - AdLayer *layer = _layers[i]; - for (uint32 j = 0; j < layer->_nodes.size(); j++) { - AdSceneNode *node = layer->_nodes[j]; - switch (node->_type) { - case OBJECT_ENTITY: - if (!node->_entity->_saveState) { - continue; - } - nodeState = state->getNodeState(node->_entity->getName(), saving); - if (nodeState) { - nodeState->transferEntity(node->_entity, _persistentStateSprites, saving); - //if (Saving) NodeState->_active = node->_entity->_active; - //else node->_entity->_active = NodeState->_active; - } - break; - case OBJECT_REGION: - if (!node->_region->_saveState) { - continue; - } - nodeState = state->getNodeState(node->_region->getName(), saving); - if (nodeState) { - if (saving) { - nodeState->_active = node->_region->_active; - } else { - node->_region->_active = nodeState->_active; - } - } - break; - default: - warning("AdScene::PersistState - unhandled enum"); - break; - } - } - } - - // free entities - for (uint32 i = 0; i < _objects.size(); i++) { - if (!_objects[i]->_saveState) { - continue; - } - if (_objects[i]->_type == OBJECT_ENTITY) { - nodeState = state->getNodeState(_objects[i]->getName(), saving); - if (nodeState) { - nodeState->transferEntity((AdEntity *)_objects[i], _persistentStateSprites, saving); - //if (Saving) NodeState->_active = _objects[i]->_active; - //else _objects[i]->_active = NodeState->_active; - } - } - } - - // waypoint groups - for (uint32 i = 0; i < _waypointGroups.size(); i++) { - nodeState = state->getNodeState(_waypointGroups[i]->getName(), saving); - if (nodeState) { - if (saving) { - nodeState->_active = _waypointGroups[i]->_active; - } else { - _waypointGroups[i]->_active = nodeState->_active; - } - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -float AdScene::getRotationAt(int x, int y) { - AdRotLevel *prev = NULL; - AdRotLevel *next = NULL; - - for (uint32 i = 0; i < _rotLevels.size(); i++) { - /* AdRotLevel *xxx = _rotLevels[i]; - int j = _rotLevels.size();*/ - if (_rotLevels[i]->_posX < x) { - prev = _rotLevels[i]; - } else { - next = _rotLevels[i]; - break; - } - } - - if (prev == NULL || next == NULL) { - return 0; - } - - int delta_x = next->_posX - prev->_posX; - float delta_rot = next->_rotation - prev->_rotation; - x -= prev->_posX; - - float percent = (float)x / ((float)delta_x / 100.0f); - return prev->_rotation + delta_rot / 100 * percent; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::handleItemAssociations(const char *itemName, bool show) { - for (uint32 i = 0; i < _layers.size(); i++) { - AdLayer *layer = _layers[i]; - for (uint32 j = 0; j < layer->_nodes.size(); j++) { - if (layer->_nodes[j]->_type == OBJECT_ENTITY) { - AdEntity *ent = layer->_nodes[j]->_entity; - - if (ent->_item && strcmp(ent->_item, itemName) == 0) { - ent->_active = show; - } - } - } - } - - for (uint32 i = 0; i < _objects.size(); i++) { - if (_objects[i]->_type == OBJECT_ENTITY) { - AdEntity *ent = (AdEntity *)_objects[i]; - if (ent->_item && strcmp(ent->_item, itemName) == 0) { - ent->_active = show; - } - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getRegionsAt(int x, int y, AdRegion **regionList, int numRegions) { - int numUsed = 0; - if (_mainLayer) { - for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { - AdSceneNode *node = _mainLayer->_nodes[i]; - if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) { - if (numUsed < numRegions - 1) { - regionList[numUsed] = node->_region; - numUsed++; - } else { - break; - } - } - } - } - for (int i = numUsed; i < numRegions; i++) { - regionList[i] = NULL; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdScene::restoreDeviceObjects() { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -BaseObject *AdScene::getNextAccessObject(BaseObject *currObject) { - BaseArray objects; - getSceneObjects(objects, true); - - if (objects.size() == 0) { - return NULL; - } else { - if (currObject != NULL) { - for (uint32 i = 0; i < objects.size(); i++) { - if (objects[i] == currObject) { - if (i < objects.size() - 1) { - return objects[i + 1]; - } else { - break; - } - } - } - } - return objects[0]; - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -BaseObject *AdScene::getPrevAccessObject(BaseObject *currObject) { - BaseArray objects; - getSceneObjects(objects, true); - - if (objects.size() == 0) { - return NULL; - } else { - if (currObject != NULL) { - for (int i = objects.size() - 1; i >= 0; i--) { - if (objects[i] == currObject) { - if (i > 0) { - return objects[i - 1]; - } else { - break; - } - } - } - } - return objects[objects.size() - 1]; - } - return NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getSceneObjects(BaseArray &objects, bool interactiveOnly) { - for (uint32 i = 0; i < _layers.size(); i++) { - // close-up layer -> remove everything below it - if (interactiveOnly && _layers[i]->_closeUp) { - objects.clear(); - } - - - for (uint32 j = 0; j < _layers[i]->_nodes.size(); j++) { - AdSceneNode *node = _layers[i]->_nodes[j]; - switch (node->_type) { - case OBJECT_ENTITY: { - AdEntity *ent = node->_entity; - if (ent->_active && (ent->_registrable || !interactiveOnly)) { - objects.add(ent); - } - } - break; - - case OBJECT_REGION: { - BaseArray regionObj; - getRegionObjects(node->_region, regionObj, interactiveOnly); - for (uint32 newIndex = 0; newIndex < regionObj.size(); newIndex++) { - bool found = false; - for (uint32 old = 0; old < objects.size(); old++) { - if (objects[old] == regionObj[newIndex]) { - found = true; - break; - } - } - if (!found) { - objects.add(regionObj[newIndex]); - } - } - //if (regionObj.size() > 0) Objects.Append(RegionObj); - } - break; - default: - debugC(kWintermuteDebugGeneral, "AdScene::GetSceneObjects - Unhandled enum"); - break; - } - } - } - - // objects outside any region - BaseArray regionObj; - getRegionObjects(NULL, regionObj, interactiveOnly); - for (uint32 newIndex = 0; newIndex < regionObj.size(); newIndex++) { - bool found = false; - for (uint32 old = 0; old < objects.size(); old++) { - if (objects[old] == regionObj[newIndex]) { - found = true; - break; - } - } - if (!found) { - objects.add(regionObj[newIndex]); - } - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdScene::getRegionObjects(AdRegion *region, BaseArray &objects, bool interactiveOnly) { - AdGame *adGame = (AdGame *)_gameRef; - AdObject *obj; - - // global objects - for (uint32 i = 0; i < adGame->_objects.size(); i++) { - obj = adGame->_objects[i]; - if (obj->_active && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - if (interactiveOnly && !obj->_registrable) { - continue; - } - - objects.add(obj); - } - } - - // scene objects - for (uint32 i = 0; i < _objects.size(); i++) { - obj = _objects[i]; - if (obj->_active && !obj->_editorOnly && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { - if (interactiveOnly && !obj->_registrable) { - continue; - } - - objects.add(obj); - } - } - - // sort by _posY - Common::sort(objects.begin(), objects.end(), AdScene::compareObjs); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_scene.h" +#include "engines/wintermute/ad/ad_actor.h" +#include "engines/wintermute/ad/ad_entity.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/ad/ad_layer.h" +#include "engines/wintermute/ad/ad_node_state.h" +#include "engines/wintermute/ad/ad_object.h" +#include "engines/wintermute/ad/ad_path.h" +#include "engines/wintermute/ad/ad_path_point.h" +#include "engines/wintermute/ad/ad_rot_level.h" +#include "engines/wintermute/ad/ad_scale_level.h" +#include "engines/wintermute/ad/ad_scene_node.h" +#include "engines/wintermute/ad/ad_scene_state.h" +#include "engines/wintermute/ad/ad_sentence.h" +#include "engines/wintermute/ad/ad_waypoint_group.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_point.h" +#include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/base/base_scriptable.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_viewport.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/ui/ui_window.h" +#include "engines/wintermute/utils/utils.h" +#include "engines/wintermute/wintermute.h" +#include + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdScene, false) + +////////////////////////////////////////////////////////////////////////// +AdScene::AdScene(BaseGame *inGame) : BaseObject(inGame) { + _pfTarget = new BasePoint; + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +AdScene::~AdScene() { + cleanup(); + _gameRef->unregisterObject(_fader); + delete _pfTarget; + _pfTarget = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::setDefaults() { + _initialized = false; + _pfReady = true; + _pfTargetPath = NULL; + _pfRequester = NULL; + _mainLayer = NULL; + + _pfPointsNum = 0; + _persistentState = false; + _persistentStateSprites = true; + + _autoScroll = true; + _offsetLeft = _offsetTop = 0; + _targetOffsetLeft = _targetOffsetTop = 0; + + _lastTimeH = _lastTimeV = 0; + _scrollTimeH = _scrollTimeV = 10; + _scrollPixelsH = _scrollPixelsV = 1; + + _pfMaxTime = 15; + + _paralaxScrolling = true; + + // editor settings + _editorMarginH = _editorMarginV = 100; + + _editorColFrame = 0xE0888888; + _editorColEntity = 0xFF008000; + _editorColRegion = 0xFF0000FF; + _editorColBlocked = 0xFF800080; + _editorColWaypoints = 0xFF0000FF; + _editorColEntitySel = 0xFFFF0000; + _editorColRegionSel = 0xFFFF0000; + _editorColBlockedSel = 0xFFFF0000; + _editorColWaypointsSel = 0xFFFF0000; + _editorColScale = 0xFF00FF00; + _editorColDecor = 0xFF00FFFF; + _editorColDecorSel = 0xFFFF0000; + + _editorShowRegions = true; + _editorShowBlocked = true; + _editorShowDecor = true; + _editorShowEntities = true; + _editorShowScale = true; + + _shieldWindow = NULL; + + _fader = new BaseFader(_gameRef); + _gameRef->registerObject(_fader); + + _viewport = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::cleanup() { + BaseObject::cleanup(); + + _mainLayer = NULL; // reference only + + delete _shieldWindow; + _shieldWindow = NULL; + + _gameRef->unregisterObject(_fader); + _fader = NULL; + + for (uint32 i = 0; i < _layers.size(); i++) { + _gameRef->unregisterObject(_layers[i]); + } + _layers.clear(); + + + for (uint32 i = 0; i < _waypointGroups.size(); i++) { + _gameRef->unregisterObject(_waypointGroups[i]); + } + _waypointGroups.clear(); + + for (uint32 i = 0; i < _scaleLevels.size(); i++) { + _gameRef->unregisterObject(_scaleLevels[i]); + } + _scaleLevels.clear(); + + for (uint32 i = 0; i < _rotLevels.size(); i++) { + _gameRef->unregisterObject(_rotLevels[i]); + } + _rotLevels.clear(); + + + for (uint32 i = 0; i < _pfPath.size(); i++) { + delete _pfPath[i]; + } + _pfPath.clear(); + _pfPointsNum = 0; + + for (uint32 i = 0; i < _objects.size(); i++) { + _gameRef->unregisterObject(_objects[i]); + } + _objects.clear(); + + delete _viewport; + _viewport = NULL; + + setDefaults(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester) { + if (!_pfReady) { + return false; + } else { + _pfReady = false; + *_pfTarget = target; + _pfTargetPath = path; + _pfRequester = requester; + + _pfTargetPath->reset(); + _pfTargetPath->setReady(false); + + // prepare working path + pfPointsStart(); + + // first point + //_pfPath.add(new AdPathPoint(source.x, source.y, 0)); + + // if we're one pixel stuck, get unstuck + int startX = source.x; + int startY = source.y; + int bestDistance = 1000; + if (isBlockedAt(startX, startY, true, requester)) { + int tolerance = 2; + for (int xxx = startX - tolerance; xxx <= startX + tolerance; xxx++) { + for (int yyy = startY - tolerance; yyy <= startY + tolerance; yyy++) { + if (isWalkableAt(xxx, yyy, true, requester)) { + int distance = abs(xxx - source.x) + abs(yyy - source.y); + if (distance < bestDistance) { + startX = xxx; + startY = yyy; + + bestDistance = distance; + } + } + } + } + } + + pfPointsAdd(startX, startY, 0); + + //CorrectTargetPoint(&target.x, &target.y); + + // last point + //_pfPath.add(new AdPathPoint(target.x, target.y, INT_MAX)); + pfPointsAdd(target.x, target.y, INT_MAX); + + // active waypoints + for (uint32 i = 0; i < _waypointGroups.size(); i++) { + if (_waypointGroups[i]->_active) { + pfAddWaypointGroup(_waypointGroups[i], requester); + } + } + + + // free waypoints + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentWptGroup) { + pfAddWaypointGroup(_objects[i]->_currentWptGroup, requester); + } + } + AdGame *adGame = (AdGame *)_gameRef; + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentWptGroup) { + pfAddWaypointGroup(adGame->_objects[i]->_currentWptGroup, requester); + } + } + + return true; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::pfAddWaypointGroup(AdWaypointGroup *wpt, BaseObject *requester) { + if (!wpt->_active) { + return; + } + + for (uint32 i = 0; i < wpt->_points.size(); i++) { + if (isBlockedAt(wpt->_points[i]->x, wpt->_points[i]->y, true, requester)) { + continue; + } + + //_pfPath.add(new AdPathPoint(Wpt->_points[i]->x, Wpt->_points[i]->y, INT_MAX)); + pfPointsAdd(wpt->_points[i]->x, wpt->_points[i]->y, INT_MAX); + } +} + + +////////////////////////////////////////////////////////////////////////// +float AdScene::getZoomAt(int x, int y) { + float ret = 100; + + bool found = false; + if (_mainLayer) { + for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { + AdSceneNode *node = _mainLayer->_nodes[i]; + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_blocked && node->_region->pointInRegion(x, y)) { + if (node->_region->_zoom != 0) { + ret = node->_region->_zoom; + found = true; + break; + } + } + } + } + if (!found) { + ret = getScaleAt(y); + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +uint32 AdScene::getAlphaAt(int x, int y, bool colorCheck) { + if (!_gameRef->_debugDebugMode) { + colorCheck = false; + } + + uint32 ret; + if (colorCheck) { + ret = 0xFFFF0000; + } else { + ret = 0xFFFFFFFF; + } + + if (_mainLayer) { + for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { + AdSceneNode *node = _mainLayer->_nodes[i]; + if (node->_type == OBJECT_REGION && node->_region->_active && (colorCheck || !node->_region->_blocked) && node->_region->pointInRegion(x, y)) { + if (!node->_region->_blocked) { + ret = node->_region->_alpha; + } + break; + } + } + } + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::isBlockedAt(int x, int y, bool checkFreeObjects, BaseObject *requester) { + bool ret = true; + + if (checkFreeObjects) { + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { + if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { + return true; + } + } + } + AdGame *adGame = (AdGame *)_gameRef; + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) { + if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { + return true; + } + } + } + } + + + if (_mainLayer) { + for (uint32 i = 0; i < _mainLayer->_nodes.size(); i++) { + AdSceneNode *node = _mainLayer->_nodes[i]; + /* + if (Node->_type == OBJECT_REGION && Node->_region->_active && Node->_region->_blocked && Node->_region->PointInRegion(X, Y)) + { + ret = true; + break; + } + */ + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { + if (node->_region->_blocked) { + ret = true; + break; + } else { + ret = false; + } + } + } + } + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::isWalkableAt(int x, int y, bool checkFreeObjects, BaseObject *requester) { + bool ret = false; + + if (checkFreeObjects) { + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && _objects[i] != requester && _objects[i]->_currentBlockRegion) { + if (_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { + return false; + } + } + } + AdGame *adGame = (AdGame *)_gameRef; + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + if (adGame->_objects[i]->_active && adGame->_objects[i] != requester && adGame->_objects[i]->_currentBlockRegion) { + if (adGame->_objects[i]->_currentBlockRegion->pointInRegion(x, y)) { + return false; + } + } + } + } + + + if (_mainLayer) { + for (uint32 i = 0; i < _mainLayer->_nodes.size(); i++) { + AdSceneNode *node = _mainLayer->_nodes[i]; + if (node->_type == OBJECT_REGION && node->_region->_active && !node->_region->_decoration && node->_region->pointInRegion(x, y)) { + if (node->_region->_blocked) { + ret = false; + break; + } else { + ret = true; + } + } + } + } + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +int AdScene::getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester) { + double xStep, yStep, x, y; + int xLength, yLength, xCount, yCount; + int x1, y1, x2, y2; + + x1 = p1.x; + y1 = p1.y; + x2 = p2.x; + y2 = p2.y; + + xLength = abs(x2 - x1); + yLength = abs(y2 - y1); + + if (xLength > yLength) { + if (x1 > x2) { + BaseUtils::swap(&x1, &x2); + BaseUtils::swap(&y1, &y2); + } + + yStep = (double)(y2 - y1) / (double)(x2 - x1); + y = y1; + + for (xCount = x1; xCount < x2; xCount++) { + if (isBlockedAt(xCount, (int)y, true, requester)) { + return -1; + } + y += yStep; + } + } else { + if (y1 > y2) { + BaseUtils::swap(&x1, &x2); + BaseUtils::swap(&y1, &y2); + } + + xStep = (double)(x2 - x1) / (double)(y2 - y1); + x = x1; + + for (yCount = y1; yCount < y2; yCount++) { + if (isBlockedAt((int)x, yCount, true, requester)) { + return -1; + } + x += xStep; + } + } + return MAX(xLength, yLength); +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::pathFinderStep() { + int i; + // get lowest unmarked + int lowestDist = INT_MAX; + AdPathPoint *lowestPt = NULL; + + for (i = 0; i < _pfPointsNum; i++) + if (!_pfPath[i]->_marked && _pfPath[i]->_distance < lowestDist) { + lowestDist = _pfPath[i]->_distance; + lowestPt = _pfPath[i]; + } + + if (lowestPt == NULL) { // no path -> terminate PathFinder + _pfReady = true; + _pfTargetPath->setReady(true); + return; + } + + lowestPt->_marked = true; + + // target point marked, generate path and terminate + if (lowestPt->x == _pfTarget->x && lowestPt->y == _pfTarget->y) { + while (lowestPt != NULL) { + _pfTargetPath->_points.insert_at(0, new BasePoint(lowestPt->x, lowestPt->y)); + lowestPt = lowestPt->_origin; + } + + _pfReady = true; + _pfTargetPath->setReady(true); + return; + } + + // otherwise keep on searching + for (i = 0; i < _pfPointsNum; i++) + if (!_pfPath[i]->_marked) { + int j = getPointsDist(*lowestPt, *_pfPath[i], _pfRequester); + if (j != -1 && lowestPt->_distance + j < _pfPath[i]->_distance) { + _pfPath[i]->_distance = lowestPt->_distance + j; + _pfPath[i]->_origin = lowestPt; + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::initLoop() { +#ifdef _DEBUGxxxx + int nu_steps = 0; + uint32 start = _gameRef->_currentTime; + while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) { + PathFinderStep(); + nu_steps++; + } + if (nu_steps > 0) { + _gameRef->LOG(0, "STAT: PathFinder iterations in one loop: %d (%s) _pfMaxTime=%d", nu_steps, _pfReady ? "finished" : "not yet done", _pfMaxTime); + } +#else + uint32 start = _gameRef->_currentTime; + while (!_pfReady && g_system->getMillis() - start <= _pfMaxTime) { + pathFinderStep(); + } +#endif + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdScene::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 SCENE file '%s'", filename); + } + + setFilename(filename); + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(SCENE) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(LAYER) +TOKEN_DEF(WAYPOINTS) +TOKEN_DEF(EVENTS) +TOKEN_DEF(CURSOR) +TOKEN_DEF(CAMERA) +TOKEN_DEF(ENTITY) +TOKEN_DEF(SCALE_LEVEL) +TOKEN_DEF(ROTATION_LEVEL) +TOKEN_DEF(EDITOR_MARGIN_H) +TOKEN_DEF(EDITOR_MARGIN_V) +TOKEN_DEF(EDITOR_COLOR_FRAME) +TOKEN_DEF(EDITOR_COLOR_ENTITY_SEL) +TOKEN_DEF(EDITOR_COLOR_REGION_SEL) +TOKEN_DEF(EDITOR_COLOR_DECORATION_SEL) +TOKEN_DEF(EDITOR_COLOR_BLOCKED_SEL) +TOKEN_DEF(EDITOR_COLOR_WAYPOINTS_SEL) +TOKEN_DEF(EDITOR_COLOR_REGION) +TOKEN_DEF(EDITOR_COLOR_DECORATION) +TOKEN_DEF(EDITOR_COLOR_BLOCKED) +TOKEN_DEF(EDITOR_COLOR_ENTITY) +TOKEN_DEF(EDITOR_COLOR_WAYPOINTS) +TOKEN_DEF(EDITOR_COLOR_SCALE) +TOKEN_DEF(EDITOR_SHOW_REGIONS) +TOKEN_DEF(EDITOR_SHOW_BLOCKED) +TOKEN_DEF(EDITOR_SHOW_DECORATION) +TOKEN_DEF(EDITOR_SHOW_ENTITIES) +TOKEN_DEF(EDITOR_SHOW_SCALE) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(VIEWPORT) +TOKEN_DEF(PERSISTENT_STATE_SPRITES) +TOKEN_DEF(PERSISTENT_STATE) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdScene::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(SCENE) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(LAYER) + TOKEN_TABLE(WAYPOINTS) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(CAMERA) + TOKEN_TABLE(ENTITY) + TOKEN_TABLE(SCALE_LEVEL) + TOKEN_TABLE(ROTATION_LEVEL) + TOKEN_TABLE(EDITOR_MARGIN_H) + TOKEN_TABLE(EDITOR_MARGIN_V) + TOKEN_TABLE(EDITOR_COLOR_FRAME) + TOKEN_TABLE(EDITOR_COLOR_ENTITY_SEL) + TOKEN_TABLE(EDITOR_COLOR_REGION_SEL) + TOKEN_TABLE(EDITOR_COLOR_DECORATION_SEL) + TOKEN_TABLE(EDITOR_COLOR_BLOCKED_SEL) + TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS_SEL) + TOKEN_TABLE(EDITOR_COLOR_REGION) + TOKEN_TABLE(EDITOR_COLOR_DECORATION) + TOKEN_TABLE(EDITOR_COLOR_BLOCKED) + TOKEN_TABLE(EDITOR_COLOR_ENTITY) + TOKEN_TABLE(EDITOR_COLOR_WAYPOINTS) + TOKEN_TABLE(EDITOR_COLOR_SCALE) + TOKEN_TABLE(EDITOR_SHOW_REGIONS) + TOKEN_TABLE(EDITOR_SHOW_DECORATION) + TOKEN_TABLE(EDITOR_SHOW_BLOCKED) + TOKEN_TABLE(EDITOR_SHOW_ENTITIES) + TOKEN_TABLE(EDITOR_SHOW_SCALE) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(VIEWPORT) + TOKEN_TABLE(PERSISTENT_STATE_SPRITES) + TOKEN_TABLE(PERSISTENT_STATE) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + cleanup(); + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SCENE) { + _gameRef->LOG(0, "'SCENE' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + int ar, ag, ab, aa; + char camera[MAX_PATH_LENGTH] = ""; + /* float waypointHeight = -1.0f; */ + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_LAYER: { + AdLayer *layer = new AdLayer(_gameRef); + if (!layer || DID_FAIL(layer->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete layer; + layer = NULL; + } else { + _gameRef->registerObject(layer); + _layers.add(layer); + if (layer->_main) { + _mainLayer = layer; + _width = layer->_width; + _height = layer->_height; + } + } + } + break; + + case TOKEN_WAYPOINTS: { + AdWaypointGroup *wpt = new AdWaypointGroup(_gameRef); + if (!wpt || DID_FAIL(wpt->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete wpt; + wpt = NULL; + } else { + _gameRef->registerObject(wpt); + _waypointGroups.add(wpt); + } + } + break; + + case TOKEN_SCALE_LEVEL: { + AdScaleLevel *sl = new AdScaleLevel(_gameRef); + if (!sl || DID_FAIL(sl->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete sl; + sl = NULL; + } else { + _gameRef->registerObject(sl); + _scaleLevels.add(sl); + } + } + break; + + case TOKEN_ROTATION_LEVEL: { + AdRotLevel *rl = new AdRotLevel(_gameRef); + if (!rl || DID_FAIL(rl->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete rl; + rl = NULL; + } else { + _gameRef->registerObject(rl); + _rotLevels.add(rl); + } + } + break; + + case TOKEN_ENTITY: { + AdEntity *entity = new AdEntity(_gameRef); + if (!entity || DID_FAIL(entity->loadBuffer(params, false))) { + cmd = PARSERR_GENERIC; + delete entity; + entity = NULL; + } else { + addObject(entity); + } + } + 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_CAMERA: + strcpy(camera, (char *)params); + break; + + case TOKEN_EDITOR_MARGIN_H: + parser.scanStr((char *)params, "%d", &_editorMarginH); + break; + + case TOKEN_EDITOR_MARGIN_V: + parser.scanStr((char *)params, "%d", &_editorMarginV); + break; + + case TOKEN_EDITOR_COLOR_FRAME: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColFrame = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_ENTITY: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColEntity = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_ENTITY_SEL: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColEntitySel = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_REGION_SEL: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColRegionSel = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_DECORATION_SEL: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColDecorSel = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_BLOCKED_SEL: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColBlockedSel = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_WAYPOINTS_SEL: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColWaypointsSel = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_REGION: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColRegion = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_DECORATION: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColDecor = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_BLOCKED: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColBlocked = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_WAYPOINTS: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColWaypoints = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_COLOR_SCALE: + parser.scanStr((char *)params, "%d,%d,%d,%d", &ar, &ag, &ab, &aa); + _editorColScale = BYTETORGBA(ar, ag, ab, aa); + break; + + case TOKEN_EDITOR_SHOW_REGIONS: + parser.scanStr((char *)params, "%b", &_editorShowRegions); + break; + + case TOKEN_EDITOR_SHOW_BLOCKED: + parser.scanStr((char *)params, "%b", &_editorShowBlocked); + break; + + case TOKEN_EDITOR_SHOW_DECORATION: + parser.scanStr((char *)params, "%b", &_editorShowDecor); + break; + + case TOKEN_EDITOR_SHOW_ENTITIES: + parser.scanStr((char *)params, "%b", &_editorShowEntities); + break; + + case TOKEN_EDITOR_SHOW_SCALE: + parser.scanStr((char *)params, "%b", &_editorShowScale); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_VIEWPORT: { + Rect32 rc; + parser.scanStr((char *)params, "%d,%d,%d,%d", &rc.left, &rc.top, &rc.right, &rc.bottom); + if (!_viewport) { + _viewport = new BaseViewport(_gameRef); + } + if (_viewport) { + _viewport->setRect(rc.left, rc.top, rc.right, rc.bottom, true); + } + } + + case TOKEN_PERSISTENT_STATE: + parser.scanStr((char *)params, "%b", &_persistentState); + break; + + case TOKEN_PERSISTENT_STATE_SPRITES: + parser.scanStr((char *)params, "%b", &_persistentStateSprites); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in SCENE definition"); + return STATUS_FAILED; + } + + if (_mainLayer == NULL) { + _gameRef->LOG(0, "Warning: scene '%s' has no main layer.", getFilename()); + } + + + sortScaleLevels(); + sortRotLevels(); + + _initialized = true; + + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::traverseNodes(bool doUpdate) { + if (!_initialized) { + return STATUS_OK; + } + + AdGame *adGame = (AdGame *)_gameRef; + + + ////////////////////////////////////////////////////////////////////////// + // prepare viewport + bool popViewport = false; + if (_viewport && !_gameRef->_editorMode) { + _gameRef->pushViewport(_viewport); + popViewport = true; + } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { + _gameRef->pushViewport(adGame->_sceneViewport); + popViewport = true; + } + + + ////////////////////////////////////////////////////////////////////////// + // *** adjust scroll offset + if (doUpdate) { + /* + if (_autoScroll && _gameRef->_mainObject != NULL) + { + ScrollToObject(_gameRef->_mainObject); + } + */ + + if (_autoScroll) { + // adjust horizontal scroll + if (_gameRef->_timer - _lastTimeH >= _scrollTimeH) { + _lastTimeH = _gameRef->_timer; + if (_offsetLeft < _targetOffsetLeft) { + _offsetLeft += _scrollPixelsH; + _offsetLeft = MIN(_offsetLeft, _targetOffsetLeft); + } else if (_offsetLeft > _targetOffsetLeft) { + _offsetLeft -= _scrollPixelsH; + _offsetLeft = MAX(_offsetLeft, _targetOffsetLeft); + } + } + + // adjust vertical scroll + if (_gameRef->_timer - _lastTimeV >= _scrollTimeV) { + _lastTimeV = _gameRef->_timer; + if (_offsetTop < _targetOffsetTop) { + _offsetTop += _scrollPixelsV; + _offsetTop = MIN(_offsetTop, _targetOffsetTop); + } else if (_offsetTop > _targetOffsetTop) { + _offsetTop -= _scrollPixelsV; + _offsetTop = MAX(_offsetTop, _targetOffsetTop); + } + } + + if (_offsetTop == _targetOffsetTop && _offsetLeft == _targetOffsetLeft) { + _ready = true; + } + } else { + _ready = true; // not scrolling, i.e. always ready + } + } + + + + + ////////////////////////////////////////////////////////////////////////// + int viewportWidth, viewportHeight; + getViewportSize(&viewportWidth, &viewportHeight); + + int viewportX, viewportY; + getViewportOffset(&viewportX, &viewportY); + + int scrollableX = _width - viewportWidth; + int scrollableY = _height - viewportHeight; + + double widthRatio = scrollableX <= 0 ? 0 : ((double)(_offsetLeft) / (double)scrollableX); + double heightRatio = scrollableY <= 0 ? 0 : ((double)(_offsetTop) / (double)scrollableY); + + int origX, origY; + _gameRef->getOffset(&origX, &origY); + + + + ////////////////////////////////////////////////////////////////////////// + // *** display/update everything + _gameRef->_renderer->setup2D(); + + // for each layer + /* int mainOffsetX = 0; */ + /* int mainOffsetY = 0; */ + + for (uint32 j = 0; j < _layers.size(); j++) { + if (!_layers[j]->_active) { + continue; + } + + // make layer exclusive + if (!doUpdate) { + if (_layers[j]->_closeUp && !_gameRef->_editorMode) { + if (!_shieldWindow) { + _shieldWindow = new UIWindow(_gameRef); + } + if (_shieldWindow) { + _shieldWindow->_posX = _shieldWindow->_posY = 0; + _shieldWindow->_width = _gameRef->_renderer->_width; + _shieldWindow->_height = _gameRef->_renderer->_height; + _shieldWindow->display(); + } + } + } + + if (_paralaxScrolling) { + int offsetX = (int)(widthRatio * (_layers[j]->_width - viewportWidth) - viewportX); + int offsetY = (int)(heightRatio * (_layers[j]->_height - viewportHeight) - viewportY); + _gameRef->setOffset(offsetX, offsetY); + + _gameRef->_offsetPercentX = (float)offsetX / ((float)_layers[j]->_width - viewportWidth) * 100.0f; + _gameRef->_offsetPercentY = (float)offsetY / ((float)_layers[j]->_height - viewportHeight) * 100.0f; + + //_gameRef->QuickMessageForm("%d %f", OffsetX+ViewportX, _gameRef->_offsetPercentX); + } else { + _gameRef->setOffset(_offsetLeft - viewportX, _offsetTop - viewportY); + + _gameRef->_offsetPercentX = (float)(_offsetLeft - viewportX) / ((float)_layers[j]->_width - viewportWidth) * 100.0f; + _gameRef->_offsetPercentY = (float)(_offsetTop - viewportY) / ((float)_layers[j]->_height - viewportHeight) * 100.0f; + } + + + // for each node + for (uint32 k = 0; k < _layers[j]->_nodes.size(); k++) { + AdSceneNode *node = _layers[j]->_nodes[k]; + switch (node->_type) { + case OBJECT_ENTITY: + if (node->_entity->_active && (_gameRef->_editorMode || !node->_entity->_editorOnly)) { + _gameRef->_renderer->setup2D(); + + if (doUpdate) { + node->_entity->update(); + } else { + node->_entity->display(); + } + } + break; + + case OBJECT_REGION: { + if (node->_region->_blocked) { + break; + } + if (node->_region->_decoration) { + break; + } + + if (!doUpdate) { + displayRegionContent(node->_region); + } + } + break; + default: + error("AdScene::TraverseNodes - Unhandled enum"); + break; + } // switch + } // each node + + // display/update all objects which are off-regions + if (_layers[j]->_main) { + if (doUpdate) { + updateFreeObjects(); + } else { + displayRegionContent(NULL); + } + } + } // each layer + + + // restore state + _gameRef->setOffset(origX, origY); + _gameRef->_renderer->setup2D(); + + // display/update fader + if (_fader) { + if (doUpdate) { + _fader->update(); + } else { + _fader->display(); + } + } + + if (popViewport) { + _gameRef->popViewport(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::display() { + return traverseNodes(false); +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::updateFreeObjects() { + AdGame *adGame = (AdGame *)_gameRef; + // 3D-code removed + // bool is3DSet; + + // *** update all active objects + // is3DSet = false; + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + if (!adGame->_objects[i]->_active) { + continue; + } + // 3D-code removed + adGame->_objects[i]->update(); + adGame->_objects[i]->_drawn = false; + } + + + for (uint32 i = 0; i < _objects.size(); i++) { + if (!_objects[i]->_active) { + continue; + } + + _objects[i]->update(); + _objects[i]->_drawn = false; + } + + + if (_autoScroll && _gameRef->_mainObject != NULL) { + scrollToObject(_gameRef->_mainObject); + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::displayRegionContent(AdRegion *region, bool display3DOnly) { + AdGame *adGame = (AdGame *)_gameRef; + BaseArray objects; + AdObject *obj; + + // global objects + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + obj = adGame->_objects[i]; + if (obj->_active && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + objects.add(obj); + } + } + + // scene objects + for (uint32 i = 0; i < _objects.size(); i++) { + obj = _objects[i]; + if (obj->_active && !obj->_editorOnly && !obj->_drawn && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + objects.add(obj); + } + } + + // sort by _posY + Common::sort(objects.begin(), objects.end(), AdScene::compareObjs); + + // display them + for (uint32 i = 0; i < objects.size(); i++) { + obj = objects[i]; + + if (display3DOnly && !obj->_is3D) { + continue; + } + + _gameRef->_renderer->setup2D(); + + if (_gameRef->_editorMode || !obj->_editorOnly) { + obj->display(); + } + obj->_drawn = true; + } + + + // display design only objects + if (!display3DOnly) { + if (_gameRef->_editorMode && region == NULL) { + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && _objects[i]->_editorOnly) { + _objects[i]->display(); + _objects[i]->_drawn = true; + } + } + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +int AdScene::compareObjs(const void *obj1, const void *obj2) { + const AdObject *object1 = *(const AdObject *const *)obj1; + const AdObject *object2 = *(const AdObject *const *)obj2; + + if (object1->_posY < object2->_posY) { + return -1; + } else if (object1->_posY > object2->_posY) { + return 1; + } else { + return 0; + } +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::displayRegionContentOld(AdRegion *region) { + AdGame *adGame = (AdGame *)_gameRef; + AdObject *obj; + + // display all objects in region sorted by _posY + do { + obj = NULL; + int minY = INT_MAX; + + // global objects + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + if (adGame->_objects[i]->_active && !adGame->_objects[i]->_drawn && adGame->_objects[i]->_posY < minY && (adGame->_objects[i]->_stickRegion == region || region == NULL || (adGame->_objects[i]->_stickRegion == NULL && region->pointInRegion(adGame->_objects[i]->_posX, adGame->_objects[i]->_posY)))) { + obj = adGame->_objects[i]; + minY = adGame->_objects[i]->_posY; + } + } + + // scene objects + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && !_objects[i]->_editorOnly && !_objects[i]->_drawn && _objects[i]->_posY < minY && (_objects[i]->_stickRegion == region || region == NULL || (_objects[i]->_stickRegion == NULL && region->pointInRegion(_objects[i]->_posX, _objects[i]->_posY)))) { + obj = _objects[i]; + minY = _objects[i]->_posY; + } + } + + + if (obj != NULL) { + _gameRef->_renderer->setup2D(); + + if (_gameRef->_editorMode || !obj->_editorOnly) { + obj->display(); + } + obj->_drawn = true; + } + } while (obj != NULL); + + + // design only objects + if (_gameRef->_editorMode && region == NULL) { + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_active && _objects[i]->_editorOnly) { + _objects[i]->display(); + _objects[i]->_drawn = true; + } + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::update() { + return traverseNodes(true); +} + +////////////////////////////////////////////////////////////////////////// +void AdScene::scrollTo(int offsetX, int offsetY) { + int viewportWidth, viewportHeight; + getViewportSize(&viewportWidth, &viewportHeight); + + int origOffsetLeft = _targetOffsetLeft; + int origOffsetTop = _targetOffsetTop; + + _targetOffsetLeft = MAX(0, offsetX - viewportWidth / 2); + _targetOffsetLeft = MIN(_targetOffsetLeft, _width - viewportWidth); + + _targetOffsetTop = MAX(0, offsetY - viewportHeight / 2); + _targetOffsetTop = MIN(_targetOffsetTop, _height - viewportHeight); + + + if (_gameRef->_mainObject && _gameRef->_mainObject->_is3D) { + if (abs(origOffsetLeft - _targetOffsetLeft) < 5) { + _targetOffsetLeft = origOffsetLeft; + } + if (abs(origOffsetTop - _targetOffsetTop) < 5) { + _targetOffsetTop = origOffsetTop; + } + //_targetOffsetTop = 0; + } + + _ready = false; +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::scrollToObject(BaseObject *object) { + if (object) { + scrollTo(object->_posX, object->_posY - object->getHeight() / 2); + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::skipToObject(BaseObject *object) { + if (object) { + skipTo(object->_posX, object->_posY - object->getHeight() / 2); + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::skipTo(int offsetX, int offsetY) { + int viewportWidth, viewportHeight; + getViewportSize(&viewportWidth, &viewportHeight); + + _offsetLeft = MAX(0, offsetX - viewportWidth / 2); + _offsetLeft = MIN(_offsetLeft, _width - viewportWidth); + + _offsetTop = MAX(0, offsetY - viewportHeight / 2); + _offsetTop = MIN(_offsetTop, _height - viewportHeight); + + _targetOffsetLeft = _offsetLeft; + _targetOffsetTop = _offsetTop; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdScene::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // LoadActor + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "LoadActor") == 0) { + stack->correctParams(1); + AdActor *act = new AdActor(_gameRef); + if (act && DID_SUCCEED(act->loadFile(stack->pop()->getString()))) { + addObject(act); + stack->pushNative(act, true); + } else { + delete act; + act = NULL; + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadEntity") == 0) { + stack->correctParams(1); + AdEntity *ent = new AdEntity(_gameRef); + if (ent && DID_SUCCEED(ent->loadFile(stack->pop()->getString()))) { + addObject(ent); + stack->pushNative(ent, true); + } else { + delete ent; + ent = NULL; + stack->pushNULL(); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateEntity") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdEntity *ent = new AdEntity(_gameRef); + addObject(ent); + if (!val->isNULL()) { + ent->setName(val->getString()); + } + stack->pushNative(ent, true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // UnloadObject / UnloadActor / UnloadEntity / UnloadActor3D / DeleteEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "UnloadObject") == 0 || strcmp(name, "UnloadActor") == 0 || strcmp(name, "UnloadEntity") == 0 || strcmp(name, "UnloadActor3D") == 0 || strcmp(name, "DeleteEntity") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + AdObject *obj = (AdObject *)val->getNative(); + removeObject(obj); + if (val->getType() == VAL_VARIABLE_REF) { + val->setNULL(); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SkipTo + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SkipTo") == 0) { + stack->correctParams(2); + ScValue *val1 = stack->pop(); + ScValue *val2 = stack->pop(); + if (val1->isNative()) { + skipToObject((BaseObject *)val1->getNative()); + } else { + skipTo(val1->getInt(), val2->getInt()); + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollTo / ScrollToAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollTo") == 0 || strcmp(name, "ScrollToAsync") == 0) { + stack->correctParams(2); + ScValue *val1 = stack->pop(); + ScValue *val2 = stack->pop(); + if (val1->isNative()) { + scrollToObject((BaseObject *)val1->getNative()); + } else { + scrollTo(val1->getInt(), val2->getInt()); + } + if (strcmp(name, "ScrollTo") == 0) { + script->waitForExclusive(this); + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetLayer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetLayer") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + if (val->isInt()) { + int layer = val->getInt(); + if (layer < 0 || layer >= (int32)_layers.size()) { + stack->pushNULL(); + } else { + stack->pushNative(_layers[layer], true); + } + } else { + const char *layerName = val->getString(); + bool layerFound = false; + for (uint32 i = 0; i < _layers.size(); i++) { + if (scumm_stricmp(layerName, _layers[i]->getName()) == 0) { + stack->pushNative(_layers[i], true); + layerFound = true; + break; + } + } + if (!layerFound) { + stack->pushNULL(); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetWaypointGroup + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetWaypointGroup") == 0) { + stack->correctParams(1); + int group = stack->pop()->getInt(); + if (group < 0 || group >= (int32)_waypointGroups.size()) { + stack->pushNULL(); + } else { + stack->pushNative(_waypointGroups[group], true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetNode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetNode") == 0) { + stack->correctParams(1); + const char *nodeName = stack->pop()->getString(); + + BaseObject *node = getNodeByName(nodeName); + if (node) { + stack->pushNative((BaseScriptable *)node, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFreeNode + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFreeNode") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdObject *ret = NULL; + if (val->isInt()) { + int index = val->getInt(); + if (index >= 0 && index < (int32)_objects.size()) { + ret = _objects[index]; + } + } else { + const char *nodeName = val->getString(); + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i] && _objects[i]->getName() && scumm_stricmp(_objects[i]->getName(), nodeName) == 0) { + ret = _objects[i]; + break; + } + } + } + if (ret) { + stack->pushNative(ret, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetRegionAt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetRegionAt") == 0) { + stack->correctParams(3); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + ScValue *val = stack->pop(); + + bool includeDecors = false; + if (!val->isNULL()) { + includeDecors = val->getBool(); + } + + if (_mainLayer) { + for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { + AdSceneNode *node = _mainLayer->_nodes[i]; + if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) { + if (node->_region->_decoration && !includeDecors) { + continue; + } + + stack->pushNative(node->_region, true); + return STATUS_OK; + } + } + } + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsBlockedAt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsBlockedAt") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + + stack->pushBool(isBlockedAt(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsWalkableAt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsWalkableAt") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + + stack->pushBool(isWalkableAt(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetScaleAt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetScaleAt") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + + stack->pushFloat(getZoomAt(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetRotationAt + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetRotationAt") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + + stack->pushFloat(getRotationAt(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // IsScrolling + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsScrolling") == 0) { + stack->correctParams(0); + bool ret = false; + if (_autoScroll) { + if (_targetOffsetLeft != _offsetLeft || _targetOffsetTop != _offsetTop) { + ret = true; + } + } + + stack->pushBool(ret); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeOut / FadeOutAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeOut") == 0 || strcmp(name, "FadeOutAsync") == 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); + + _fader->fadeOut(BYTETORGBA(red, green, blue, alpha), duration); + if (strcmp(name, "FadeOutAsync") != 0) { + script->waitFor(_fader); + } + + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeIn / FadeInAsync + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeIn") == 0 || strcmp(name, "FadeInAsync") == 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); + + _fader->fadeIn(BYTETORGBA(red, green, blue, alpha), duration); + if (strcmp(name, "FadeInAsync") != 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; + } + + ////////////////////////////////////////////////////////////////////////// + // IsPointInViewport + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "IsPointInViewport") == 0) { + stack->correctParams(2); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + stack->pushBool(pointInViewport(x, y)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetViewport + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetViewport") == 0) { + stack->correctParams(4); + int x = stack->pop()->getInt(); + int y = stack->pop()->getInt(); + int width = stack->pop()->getInt(); + int height = stack->pop()->getInt(); + + if (width <= 0) { + width = _gameRef->_renderer->_width; + } + if (height <= 0) { + height = _gameRef->_renderer->_height; + } + + if (!_viewport) { + _viewport = new BaseViewport(_gameRef); + } + if (_viewport) { + _viewport->setRect(x, y, x + width, y + height); + } + + stack->pushBool(true); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddLayer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddLayer") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdLayer *layer = new AdLayer(_gameRef); + if (!val->isNULL()) { + layer->setName(val->getString()); + } + if (_mainLayer) { + layer->_width = _mainLayer->_width; + layer->_height = _mainLayer->_height; + } + _layers.add(layer); + _gameRef->registerObject(layer); + + stack->pushNative(layer, true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InsertLayer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InsertLayer") == 0) { + stack->correctParams(2); + int index = stack->pop()->getInt(); + ScValue *val = stack->pop(); + + AdLayer *layer = new AdLayer(_gameRef); + if (!val->isNULL()) { + layer->setName(val->getString()); + } + if (_mainLayer) { + layer->_width = _mainLayer->_width; + layer->_height = _mainLayer->_height; + } + if (index < 0) { + index = 0; + } + if (index <= (int32)_layers.size() - 1) { + _layers.insert_at(index, layer); + } else { + _layers.add(layer); + } + + _gameRef->registerObject(layer); + + stack->pushNative(layer, true); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteLayer + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteLayer") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + AdLayer *toDelete = NULL; + if (val->isNative()) { + BaseScriptable *temp = val->getNative(); + for (uint32 i = 0; i < _layers.size(); i++) { + if (_layers[i] == temp) { + toDelete = _layers[i]; + break; + } + } + } else { + int index = val->getInt(); + if (index >= 0 && index < (int32)_layers.size()) { + toDelete = _layers[index]; + } + } + if (toDelete == NULL) { + stack->pushBool(false); + return STATUS_OK; + } + + if (toDelete->_main) { + script->runtimeError("Scene.DeleteLayer - cannot delete main scene layer"); + stack->pushBool(false); + return STATUS_OK; + } + + for (uint32 i = 0; i < _layers.size(); i++) { + if (_layers[i] == toDelete) { + _layers.remove_at(i); + _gameRef->unregisterObject(toDelete); + break; + } + } + stack->pushBool(true); + return STATUS_OK; + } else { + return BaseObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdScene::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("scene"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumLayers (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumLayers") == 0) { + _scValue->setInt(_layers.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumWaypointGroups (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumWaypointGroups") == 0) { + _scValue->setInt(_waypointGroups.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MainLayer (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MainLayer") == 0) { + if (_mainLayer) { + _scValue->setNative(_mainLayer, true); + } else { + _scValue->setNULL(); + } + + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumFreeNodes (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumFreeNodes") == 0) { + _scValue->setInt(_objects.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseX (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MouseX") == 0) { + int viewportX; + getViewportOffset(&viewportX); + + _scValue->setInt(_gameRef->_mousePos.x + _offsetLeft - viewportX); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MouseY (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MouseY") == 0) { + int viewportY; + getViewportOffset(NULL, &viewportY); + + _scValue->setInt(_gameRef->_mousePos.y + _offsetTop - viewportY); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoScroll + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AutoScroll") == 0) { + _scValue->setBool(_autoScroll); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PersistentState + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PersistentState") == 0) { + _scValue->setBool(_persistentState); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PersistentStateSprites + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PersistentStateSprites") == 0) { + _scValue->setBool(_persistentStateSprites); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollPixelsX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollPixelsX") == 0) { + _scValue->setInt(_scrollPixelsH); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollPixelsY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollPixelsY") == 0) { + _scValue->setInt(_scrollPixelsV); + return _scValue; + } + + + ////////////////////////////////////////////////////////////////////////// + // ScrollSpeedX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollSpeedX") == 0) { + _scValue->setInt(_scrollTimeH); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollSpeedY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollSpeedY") == 0) { + _scValue->setInt(_scrollTimeV); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // OffsetX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "OffsetX") == 0) { + _scValue->setInt(_offsetLeft); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // OffsetY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "OffsetY") == 0) { + _scValue->setInt(_offsetTop); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Width (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Width") == 0) { + if (_mainLayer) { + _scValue->setInt(_mainLayer->_width); + } else { + _scValue->setInt(0); + } + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Height (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Height") == 0) { + if (_mainLayer) { + _scValue->setInt(_mainLayer->_height); + } else { + _scValue->setInt(0); + } + return _scValue; + } else { + return BaseObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AutoScroll + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AutoScroll") == 0) { + _autoScroll = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PersistentState + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PersistentState") == 0) { + _persistentState = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PersistentStateSprites + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PersistentStateSprites") == 0) { + _persistentStateSprites = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollPixelsX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollPixelsX") == 0) { + _scrollPixelsH = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollPixelsY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollPixelsY") == 0) { + _scrollPixelsV = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollSpeedX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollSpeedX") == 0) { + _scrollTimeH = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ScrollSpeedY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ScrollSpeedY") == 0) { + _scrollTimeV = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // OffsetX + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "OffsetX") == 0) { + _offsetLeft = value->getInt(); + + int viewportWidth, viewportHeight; + getViewportSize(&viewportWidth, &viewportHeight); + + _offsetLeft = MAX(0, _offsetLeft - viewportWidth / 2); + _offsetLeft = MIN(_offsetLeft, _width - viewportWidth); + _targetOffsetLeft = _offsetLeft; + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // OffsetY + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "OffsetY") == 0) { + _offsetTop = value->getInt(); + + int viewportWidth, viewportHeight; + getViewportSize(&viewportWidth, &viewportHeight); + + _offsetTop = MAX(0, _offsetTop - viewportHeight / 2); + _offsetTop = MIN(_offsetTop, _height - viewportHeight); + _targetOffsetTop = _offsetTop; + + return STATUS_OK; + } else { + return BaseObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdScene::scToString() { + return "[scene object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::addObject(AdObject *object) { + _objects.add(object); + return _gameRef->registerObject(object); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::removeObject(AdObject *object) { + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i] == object) { + _objects.remove_at(i); + return _gameRef->unregisterObject(object); + } + } + return STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "SCENE {\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + if (_persistentState) { + buffer->putTextIndent(indent + 2, "PERSISTENT_STATE=%s\n", _persistentState ? "TRUE" : "FALSE"); + } + + if (!_persistentStateSprites) { + buffer->putTextIndent(indent + 2, "PERSISTENT_STATE_SPRITES=%s\n", _persistentStateSprites ? "TRUE" : "FALSE"); + } + + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // properties + if (_scProp) { + _scProp->saveAsText(buffer, indent + 2); + } + + // viewport + if (_viewport) { + Rect32 *rc = _viewport->getRect(); + buffer->putTextIndent(indent + 2, "VIEWPORT { %d, %d, %d, %d }\n", rc->left, rc->top, rc->right, rc->bottom); + } + + + + // editor settings + buffer->putTextIndent(indent + 2, "; ----- editor settings\n"); + buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_H=%d\n", _editorMarginH); + buffer->putTextIndent(indent + 2, "EDITOR_MARGIN_V=%d\n", _editorMarginV); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_FRAME { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColFrame), RGBCOLGetG(_editorColFrame), RGBCOLGetB(_editorColFrame), RGBCOLGetA(_editorColFrame)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntitySel), RGBCOLGetG(_editorColEntitySel), RGBCOLGetB(_editorColEntitySel), RGBCOLGetA(_editorColEntitySel)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegionSel), RGBCOLGetG(_editorColRegionSel), RGBCOLGetB(_editorColRegionSel), RGBCOLGetA(_editorColRegionSel)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlockedSel), RGBCOLGetG(_editorColBlockedSel), RGBCOLGetB(_editorColBlockedSel), RGBCOLGetA(_editorColBlockedSel)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecorSel), RGBCOLGetG(_editorColDecorSel), RGBCOLGetB(_editorColDecorSel), RGBCOLGetA(_editorColDecorSel)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS_SEL { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypointsSel), RGBCOLGetG(_editorColWaypointsSel), RGBCOLGetB(_editorColWaypointsSel), RGBCOLGetA(_editorColWaypointsSel)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_ENTITY { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColEntity), RGBCOLGetG(_editorColEntity), RGBCOLGetB(_editorColEntity), RGBCOLGetA(_editorColEntity)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_REGION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColRegion), RGBCOLGetG(_editorColRegion), RGBCOLGetB(_editorColRegion), RGBCOLGetA(_editorColRegion)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_DECORATION { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColDecor), RGBCOLGetG(_editorColDecor), RGBCOLGetB(_editorColDecor), RGBCOLGetA(_editorColDecor)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_BLOCKED { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColBlocked), RGBCOLGetG(_editorColBlocked), RGBCOLGetB(_editorColBlocked), RGBCOLGetA(_editorColBlocked)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_WAYPOINTS { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColWaypoints), RGBCOLGetG(_editorColWaypoints), RGBCOLGetB(_editorColWaypoints), RGBCOLGetA(_editorColWaypoints)); + buffer->putTextIndent(indent + 2, "EDITOR_COLOR_SCALE { %d,%d,%d,%d }\n", RGBCOLGetR(_editorColScale), RGBCOLGetG(_editorColScale), RGBCOLGetB(_editorColScale), RGBCOLGetA(_editorColScale)); + + buffer->putTextIndent(indent + 2, "EDITOR_SHOW_REGIONS=%s\n", _editorShowRegions ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SHOW_BLOCKED=%s\n", _editorShowBlocked ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SHOW_DECORATION=%s\n", _editorShowDecor ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SHOW_ENTITIES=%s\n", _editorShowEntities ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SHOW_SCALE=%s\n", _editorShowScale ? "TRUE" : "FALSE"); + + buffer->putTextIndent(indent + 2, "\n"); + + BaseClass::saveAsText(buffer, indent + 2); + + // waypoints + buffer->putTextIndent(indent + 2, "; ----- waypoints\n"); + for (uint32 i = 0; i < _waypointGroups.size(); i++) { + _waypointGroups[i]->saveAsText(buffer, indent + 2); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // layers + buffer->putTextIndent(indent + 2, "; ----- layers\n"); + for (uint32 i = 0; i < _layers.size(); i++) { + _layers[i]->saveAsText(buffer, indent + 2); + } + + // scale levels + buffer->putTextIndent(indent + 2, "; ----- scale levels\n"); + for (uint32 i = 0; i < _scaleLevels.size(); i++) { + _scaleLevels[i]->saveAsText(buffer, indent + 2); + } + + // rotation levels + buffer->putTextIndent(indent + 2, "; ----- rotation levels\n"); + for (uint32 i = 0; i < _rotLevels.size(); i++) { + _rotLevels[i]->saveAsText(buffer, indent + 2); + } + + + buffer->putTextIndent(indent + 2, "\n"); + + // free entities + buffer->putTextIndent(indent + 2, "; ----- free entities\n"); + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY) { + _objects[i]->saveAsText(buffer, indent + 2); + + } + } + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::sortScaleLevels() { + if (_scaleLevels.size() == 0) { + return STATUS_OK; + } + bool changed; + do { + changed = false; + for (uint32 i = 0; i < _scaleLevels.size() - 1; i++) { + if (_scaleLevels[i]->_posY > _scaleLevels[i + 1]->_posY) { + AdScaleLevel *sl = _scaleLevels[i]; + _scaleLevels[i] = _scaleLevels[i + 1]; + _scaleLevels[i + 1] = sl; + + changed = true; + } + } + + } while (changed); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::sortRotLevels() { + if (_rotLevels.size() == 0) { + return STATUS_OK; + } + bool changed; + do { + changed = false; + for (uint32 i = 0; i < _rotLevels.size() - 1; i++) { + if (_rotLevels[i]->_posX > _rotLevels[i + 1]->_posX) { + AdRotLevel *rl = _rotLevels[i]; + _rotLevels[i] = _rotLevels[i + 1]; + _rotLevels[i + 1] = rl; + + changed = true; + } + } + + } while (changed); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float AdScene::getScaleAt(int Y) { + AdScaleLevel *prev = NULL; + AdScaleLevel *next = NULL; + + for (uint32 i = 0; i < _scaleLevels.size(); i++) { + /* AdScaleLevel *xxx = _scaleLevels[i];*/ + /* int j = _scaleLevels.size(); */ + if (_scaleLevels[i]->_posY < Y) { + prev = _scaleLevels[i]; + } else { + next = _scaleLevels[i]; + break; + } + } + + if (prev == NULL || next == NULL) { + return 100; + } + + int delta_y = next->_posY - prev->_posY; + float delta_scale = next->_scale - prev->_scale; + Y -= prev->_posY; + + float percent = (float)Y / ((float)delta_y / 100.0f); + return prev->_scale + delta_scale / 100 * percent; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_autoScroll)); + persistMgr->transfer(TMEMBER(_editorColBlocked)); + persistMgr->transfer(TMEMBER(_editorColBlockedSel)); + persistMgr->transfer(TMEMBER(_editorColDecor)); + persistMgr->transfer(TMEMBER(_editorColDecorSel)); + persistMgr->transfer(TMEMBER(_editorColEntity)); + persistMgr->transfer(TMEMBER(_editorColEntitySel)); + persistMgr->transfer(TMEMBER(_editorColFrame)); + persistMgr->transfer(TMEMBER(_editorColRegion)); + persistMgr->transfer(TMEMBER(_editorColRegionSel)); + persistMgr->transfer(TMEMBER(_editorColScale)); + persistMgr->transfer(TMEMBER(_editorColWaypoints)); + persistMgr->transfer(TMEMBER(_editorColWaypointsSel)); + persistMgr->transfer(TMEMBER(_editorMarginH)); + persistMgr->transfer(TMEMBER(_editorMarginV)); + persistMgr->transfer(TMEMBER(_editorShowBlocked)); + persistMgr->transfer(TMEMBER(_editorShowDecor)); + persistMgr->transfer(TMEMBER(_editorShowEntities)); + persistMgr->transfer(TMEMBER(_editorShowRegions)); + persistMgr->transfer(TMEMBER(_editorShowScale)); + persistMgr->transfer(TMEMBER(_fader)); + persistMgr->transfer(TMEMBER(_height)); + persistMgr->transfer(TMEMBER(_initialized)); + persistMgr->transfer(TMEMBER(_lastTimeH)); + persistMgr->transfer(TMEMBER(_lastTimeV)); + _layers.persist(persistMgr); + persistMgr->transfer(TMEMBER(_mainLayer)); + _objects.persist(persistMgr); + persistMgr->transfer(TMEMBER(_offsetLeft)); + persistMgr->transfer(TMEMBER(_offsetTop)); + persistMgr->transfer(TMEMBER(_paralaxScrolling)); + persistMgr->transfer(TMEMBER(_persistentState)); + persistMgr->transfer(TMEMBER(_persistentStateSprites)); + persistMgr->transfer(TMEMBER(_pfMaxTime)); + _pfPath.persist(persistMgr); + persistMgr->transfer(TMEMBER(_pfPointsNum)); + persistMgr->transfer(TMEMBER(_pfReady)); + persistMgr->transfer(TMEMBER(_pfRequester)); + persistMgr->transfer(TMEMBER(_pfTarget)); + persistMgr->transfer(TMEMBER(_pfTargetPath)); + _rotLevels.persist(persistMgr); + _scaleLevels.persist(persistMgr); + persistMgr->transfer(TMEMBER(_scrollPixelsH)); + persistMgr->transfer(TMEMBER(_scrollPixelsV)); + persistMgr->transfer(TMEMBER(_scrollTimeH)); + persistMgr->transfer(TMEMBER(_scrollTimeV)); + persistMgr->transfer(TMEMBER(_shieldWindow)); + persistMgr->transfer(TMEMBER(_targetOffsetLeft)); + persistMgr->transfer(TMEMBER(_targetOffsetTop)); + _waypointGroups.persist(persistMgr); + persistMgr->transfer(TMEMBER(_viewport)); + persistMgr->transfer(TMEMBER(_width)); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::afterLoad() { + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester) { + double xStep, yStep, x, y; + int xLength, yLength, xCount, yCount; + int x1, y1, x2, y2; + + x1 = *targetX; + y1 = *targetY; + x2 = startX; + y2 = startY; + + + xLength = abs(x2 - x1); + yLength = abs(y2 - y1); + + if (xLength > yLength) { + + yStep = fabs((double)(y2 - y1) / (double)(x2 - x1)); + y = y1; + + for (xCount = x1; xCount < x2; xCount++) { + if (isWalkableAt(xCount, (int)y, checkFreeObjects, requester)) { + *targetX = xCount; + *targetY = (int)y; + return STATUS_OK; + } + y += yStep; + } + } else { + + xStep = fabs((double)(x2 - x1) / (double)(y2 - y1)); + x = x1; + + for (yCount = y1; yCount < y2; yCount++) { + if (isWalkableAt((int)x, yCount, checkFreeObjects, requester)) { + *targetX = (int)x; + *targetY = yCount; + return STATUS_OK; + } + x += xStep; + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::correctTargetPoint(int startX, int startY, int *argX, int *argY, bool checkFreeObjects, BaseObject *requester) { + int x = *argX; + int y = *argY; + + if (isWalkableAt(x, y, checkFreeObjects, requester) || !_mainLayer) { + return STATUS_OK; + } + + // right + int lengthRight = 0; + bool foundRight = false; + for (x = *argX, y = *argY; x < _mainLayer->_width; x++, lengthRight++) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x - 5, y, checkFreeObjects, requester)) { + foundRight = true; + break; + } + } + + // left + int lengthLeft = 0; + bool foundLeft = false; + for (x = *argX, y = *argY; x >= 0; x--, lengthLeft--) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x + 5, y, checkFreeObjects, requester)) { + foundLeft = true; + break; + } + } + + // up + int lengthUp = 0; + bool foundUp = false; + for (x = *argX, y = *argY; y >= 0; y--, lengthUp--) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y + 5, checkFreeObjects, requester)) { + foundUp = true; + break; + } + } + + // down + int lengthDown = 0; + bool foundDown = false; + for (x = *argX, y = *argY; y < _mainLayer->_height; y++, lengthDown++) { + if (isWalkableAt(x, y, checkFreeObjects, requester) && isWalkableAt(x, y - 5, checkFreeObjects, requester)) { + foundDown = true; + break; + } + } + + if (!foundLeft && !foundRight && !foundUp && !foundDown) { + return STATUS_OK; + } + + int offsetX = INT_MAX, offsetY = INT_MAX; + + if (foundLeft && foundRight) { + if (abs(lengthLeft) < abs(lengthRight)) { + offsetX = lengthLeft; + } else { + offsetX = lengthRight; + } + } else if (foundLeft) { + offsetX = lengthLeft; + } else if (foundRight) { + offsetX = lengthRight; + } + + if (foundUp && foundDown) { + if (abs(lengthUp) < abs(lengthDown)) { + offsetY = lengthUp; + } else { + offsetY = lengthDown; + } + } else if (foundUp) { + offsetY = lengthUp; + } else if (foundDown) { + offsetY = lengthDown; + } + + if (abs(offsetX) < abs(offsetY)) { + *argX = *argX + offsetX; + } else { + *argY = *argY + offsetY; + } + + if (!isWalkableAt(*argX, *argY)) { + return correctTargetPoint2(startX, startY, argX, argY, checkFreeObjects, requester); + } else { + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::pfPointsStart() { + _pfPointsNum = 0; +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::pfPointsAdd(int x, int y, int distance) { + if (_pfPointsNum >= (int32)_pfPath.size()) { + _pfPath.add(new AdPathPoint(x, y, distance)); + } else { + _pfPath[_pfPointsNum]->x = x; + _pfPath[_pfPointsNum]->y = y; + _pfPath[_pfPointsNum]->_distance = distance; + _pfPath[_pfPointsNum]->_marked = false; + _pfPath[_pfPointsNum]->_origin = NULL; + } + + _pfPointsNum++; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getViewportOffset(int *offsetX, int *offsetY) { + AdGame *adGame = (AdGame *)_gameRef; + if (_viewport && !_gameRef->_editorMode) { + if (offsetX) { + *offsetX = _viewport->_offsetX; + } + if (offsetY) { + *offsetY = _viewport->_offsetY; + } + } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { + if (offsetX) { + *offsetX = adGame->_sceneViewport->_offsetX; + } + if (offsetY) { + *offsetY = adGame->_sceneViewport->_offsetY; + } + } else { + if (offsetX) { + *offsetX = 0; + } + if (offsetY) { + *offsetY = 0; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getViewportSize(int *width, int *height) { + AdGame *adGame = (AdGame *)_gameRef; + if (_viewport && !_gameRef->_editorMode) { + if (width) { + *width = _viewport->getWidth(); + } + if (height) { + *height = _viewport->getHeight(); + } + } else if (adGame->_sceneViewport && !_gameRef->_editorMode) { + if (width) { + *width = adGame->_sceneViewport->getWidth(); + } + if (height) { + *height = adGame->_sceneViewport->getHeight(); + } + } else { + if (width) { + *width = _gameRef->_renderer->_width; + } + if (height) { + *height = _gameRef->_renderer->_height; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +int AdScene::getOffsetLeft() { + int viewportX; + getViewportOffset(&viewportX); + + return _offsetLeft - viewportX; +} + + +////////////////////////////////////////////////////////////////////////// +int AdScene::getOffsetTop() { + int viewportY; + getViewportOffset(NULL, &viewportY); + + return _offsetTop - viewportY; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::pointInViewport(int x, int y) { + int left, top, width, height; + + getViewportOffset(&left, &top); + getViewportSize(&width, &height); + + return x >= left && x <= left + width && y >= top && y <= top + height; +} + + +////////////////////////////////////////////////////////////////////////// +void AdScene::setOffset(int offsetLeft, int offsetTop) { + _offsetLeft = offsetLeft; + _offsetTop = offsetTop; +} + + +////////////////////////////////////////////////////////////////////////// +BaseObject *AdScene::getNodeByName(const char *name) { + BaseObject *ret = NULL; + + // dependent objects + for (uint32 i = 0; i < _layers.size(); i++) { + AdLayer *layer = _layers[i]; + for (uint32 j = 0; j < layer->_nodes.size(); j++) { + AdSceneNode *node = layer->_nodes[j]; + if ((node->_type == OBJECT_ENTITY && !scumm_stricmp(name, node->_entity->getName())) || + (node->_type == OBJECT_REGION && !scumm_stricmp(name, node->_region->getName()))) { + switch (node->_type) { + case OBJECT_ENTITY: + ret = node->_entity; + break; + case OBJECT_REGION: + ret = node->_region; + break; + default: + ret = NULL; + } + return ret; + } + } + } + + // free entities + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY && !scumm_stricmp(name, _objects[i]->getName())) { + return _objects[i]; + } + } + + // waypoint groups + for (uint32 i = 0; i < _waypointGroups.size(); i++) { + if (!scumm_stricmp(name, _waypointGroups[i]->getName())) { + return _waypointGroups[i]; + } + } + + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::saveState() { + return persistState(true); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::loadState() { + return persistState(false); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::persistState(bool saving) { + if (!_persistentState) { + return STATUS_OK; + } + + AdGame *adGame = (AdGame *)_gameRef; + AdSceneState *state = adGame->getSceneState(getFilename(), saving); + if (!state) { + return STATUS_OK; + } + + AdNodeState *nodeState; + + // dependent objects + for (uint32 i = 0; i < _layers.size(); i++) { + AdLayer *layer = _layers[i]; + for (uint32 j = 0; j < layer->_nodes.size(); j++) { + AdSceneNode *node = layer->_nodes[j]; + switch (node->_type) { + case OBJECT_ENTITY: + if (!node->_entity->_saveState) { + continue; + } + nodeState = state->getNodeState(node->_entity->getName(), saving); + if (nodeState) { + nodeState->transferEntity(node->_entity, _persistentStateSprites, saving); + //if (Saving) NodeState->_active = node->_entity->_active; + //else node->_entity->_active = NodeState->_active; + } + break; + case OBJECT_REGION: + if (!node->_region->_saveState) { + continue; + } + nodeState = state->getNodeState(node->_region->getName(), saving); + if (nodeState) { + if (saving) { + nodeState->_active = node->_region->_active; + } else { + node->_region->_active = nodeState->_active; + } + } + break; + default: + warning("AdScene::PersistState - unhandled enum"); + break; + } + } + } + + // free entities + for (uint32 i = 0; i < _objects.size(); i++) { + if (!_objects[i]->_saveState) { + continue; + } + if (_objects[i]->_type == OBJECT_ENTITY) { + nodeState = state->getNodeState(_objects[i]->getName(), saving); + if (nodeState) { + nodeState->transferEntity((AdEntity *)_objects[i], _persistentStateSprites, saving); + //if (Saving) NodeState->_active = _objects[i]->_active; + //else _objects[i]->_active = NodeState->_active; + } + } + } + + // waypoint groups + for (uint32 i = 0; i < _waypointGroups.size(); i++) { + nodeState = state->getNodeState(_waypointGroups[i]->getName(), saving); + if (nodeState) { + if (saving) { + nodeState->_active = _waypointGroups[i]->_active; + } else { + _waypointGroups[i]->_active = nodeState->_active; + } + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +float AdScene::getRotationAt(int x, int y) { + AdRotLevel *prev = NULL; + AdRotLevel *next = NULL; + + for (uint32 i = 0; i < _rotLevels.size(); i++) { + /* AdRotLevel *xxx = _rotLevels[i]; + int j = _rotLevels.size();*/ + if (_rotLevels[i]->_posX < x) { + prev = _rotLevels[i]; + } else { + next = _rotLevels[i]; + break; + } + } + + if (prev == NULL || next == NULL) { + return 0; + } + + int delta_x = next->_posX - prev->_posX; + float delta_rot = next->_rotation - prev->_rotation; + x -= prev->_posX; + + float percent = (float)x / ((float)delta_x / 100.0f); + return prev->_rotation + delta_rot / 100 * percent; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::handleItemAssociations(const char *itemName, bool show) { + for (uint32 i = 0; i < _layers.size(); i++) { + AdLayer *layer = _layers[i]; + for (uint32 j = 0; j < layer->_nodes.size(); j++) { + if (layer->_nodes[j]->_type == OBJECT_ENTITY) { + AdEntity *ent = layer->_nodes[j]->_entity; + + if (ent->_item && strcmp(ent->_item, itemName) == 0) { + ent->_active = show; + } + } + } + } + + for (uint32 i = 0; i < _objects.size(); i++) { + if (_objects[i]->_type == OBJECT_ENTITY) { + AdEntity *ent = (AdEntity *)_objects[i]; + if (ent->_item && strcmp(ent->_item, itemName) == 0) { + ent->_active = show; + } + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getRegionsAt(int x, int y, AdRegion **regionList, int numRegions) { + int numUsed = 0; + if (_mainLayer) { + for (int i = _mainLayer->_nodes.size() - 1; i >= 0; i--) { + AdSceneNode *node = _mainLayer->_nodes[i]; + if (node->_type == OBJECT_REGION && node->_region->_active && node->_region->pointInRegion(x, y)) { + if (numUsed < numRegions - 1) { + regionList[numUsed] = node->_region; + numUsed++; + } else { + break; + } + } + } + } + for (int i = numUsed; i < numRegions; i++) { + regionList[i] = NULL; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdScene::restoreDeviceObjects() { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +BaseObject *AdScene::getNextAccessObject(BaseObject *currObject) { + BaseArray objects; + getSceneObjects(objects, true); + + if (objects.size() == 0) { + return NULL; + } else { + if (currObject != NULL) { + for (uint32 i = 0; i < objects.size(); i++) { + if (objects[i] == currObject) { + if (i < objects.size() - 1) { + return objects[i + 1]; + } else { + break; + } + } + } + } + return objects[0]; + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +BaseObject *AdScene::getPrevAccessObject(BaseObject *currObject) { + BaseArray objects; + getSceneObjects(objects, true); + + if (objects.size() == 0) { + return NULL; + } else { + if (currObject != NULL) { + for (int i = objects.size() - 1; i >= 0; i--) { + if (objects[i] == currObject) { + if (i > 0) { + return objects[i - 1]; + } else { + break; + } + } + } + } + return objects[objects.size() - 1]; + } + return NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getSceneObjects(BaseArray &objects, bool interactiveOnly) { + for (uint32 i = 0; i < _layers.size(); i++) { + // close-up layer -> remove everything below it + if (interactiveOnly && _layers[i]->_closeUp) { + objects.clear(); + } + + + for (uint32 j = 0; j < _layers[i]->_nodes.size(); j++) { + AdSceneNode *node = _layers[i]->_nodes[j]; + switch (node->_type) { + case OBJECT_ENTITY: { + AdEntity *ent = node->_entity; + if (ent->_active && (ent->_registrable || !interactiveOnly)) { + objects.add(ent); + } + } + break; + + case OBJECT_REGION: { + BaseArray regionObj; + getRegionObjects(node->_region, regionObj, interactiveOnly); + for (uint32 newIndex = 0; newIndex < regionObj.size(); newIndex++) { + bool found = false; + for (uint32 old = 0; old < objects.size(); old++) { + if (objects[old] == regionObj[newIndex]) { + found = true; + break; + } + } + if (!found) { + objects.add(regionObj[newIndex]); + } + } + //if (regionObj.size() > 0) Objects.Append(RegionObj); + } + break; + default: + debugC(kWintermuteDebugGeneral, "AdScene::GetSceneObjects - Unhandled enum"); + break; + } + } + } + + // objects outside any region + BaseArray regionObj; + getRegionObjects(NULL, regionObj, interactiveOnly); + for (uint32 newIndex = 0; newIndex < regionObj.size(); newIndex++) { + bool found = false; + for (uint32 old = 0; old < objects.size(); old++) { + if (objects[old] == regionObj[newIndex]) { + found = true; + break; + } + } + if (!found) { + objects.add(regionObj[newIndex]); + } + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdScene::getRegionObjects(AdRegion *region, BaseArray &objects, bool interactiveOnly) { + AdGame *adGame = (AdGame *)_gameRef; + AdObject *obj; + + // global objects + for (uint32 i = 0; i < adGame->_objects.size(); i++) { + obj = adGame->_objects[i]; + if (obj->_active && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + if (interactiveOnly && !obj->_registrable) { + continue; + } + + objects.add(obj); + } + } + + // scene objects + for (uint32 i = 0; i < _objects.size(); i++) { + obj = _objects[i]; + if (obj->_active && !obj->_editorOnly && (obj->_stickRegion == region || region == NULL || (obj->_stickRegion == NULL && region->pointInRegion(obj->_posX, obj->_posY)))) { + if (interactiveOnly && !obj->_registrable) { + continue; + } + + objects.add(obj); + } + } + + // sort by _posY + Common::sort(objects.begin(), objects.end(), AdScene::compareObjs); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene.h b/engines/wintermute/ad/ad_scene.h index 20b3f5026dab..c9c0e413bf0d 100644 --- a/engines/wintermute/ad/ad_scene.h +++ b/engines/wintermute/ad/ad_scene.h @@ -1,181 +1,181 @@ -/* 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_ADSCENE_H -#define WINTERMUTE_ADSCENE_H - -#include "engines/wintermute/base/base_fader.h" - -namespace Wintermute { - -class UIWindow; -class AdObject; -class AdRegion; -class BaseViewport; -class AdLayer; -class BasePoint; -class AdWaypointGroup; -class AdPath; -class AdScaleLevel; -class AdRotLevel; -class AdPathPoint; -class AdScene : public BaseObject { -public: - - BaseObject *getNextAccessObject(BaseObject *currObject); - BaseObject *getPrevAccessObject(BaseObject *currObject); - bool getSceneObjects(BaseArray &objects, bool interactiveOnly); - bool getRegionObjects(AdRegion *region, BaseArray &objects, bool interactiveOnly); - - bool afterLoad(); - - bool getRegionsAt(int x, int y, AdRegion **regionList, int numRegions); - bool handleItemAssociations(const char *itemName, bool show); - UIWindow *_shieldWindow; - float getRotationAt(int x, int y); - bool loadState(); - bool saveState(); - bool _persistentState; - bool _persistentStateSprites; - BaseObject *getNodeByName(const char *name); - void setOffset(int offsetLeft, int offsetTop); - bool pointInViewport(int x, int y); - int getOffsetTop(); - int getOffsetLeft(); - bool getViewportSize(int *width = NULL, int *height = NULL); - bool getViewportOffset(int *offsetX = NULL, int *offsetY = NULL); - BaseViewport *_viewport; - BaseFader *_fader; - int _pfPointsNum; - void pfPointsAdd(int x, int y, int distance); - void pfPointsStart(); - bool _initialized; - bool correctTargetPoint(int startX, int startY, int *x, int *y, bool checkFreeObjects = false, BaseObject *requester = NULL); - bool correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester); - DECLARE_PERSISTENT(AdScene, BaseObject) - bool displayRegionContent(AdRegion *region = NULL, bool display3DOnly = false); - bool displayRegionContentOld(AdRegion *region = NULL); - static int compareObjs(const void *obj1, const void *obj2); - - bool updateFreeObjects(); - bool traverseNodes(bool update = false); - float getScaleAt(int y); - bool sortScaleLevels(); - bool sortRotLevels(); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - uint32 getAlphaAt(int x, int y, bool colorCheck = false); - bool _paralaxScrolling; - void skipTo(int offsetX, int offsetY); - void setDefaults(); - void cleanup(); - void skipToObject(BaseObject *object); - void scrollToObject(BaseObject *object); - void scrollTo(int offsetX, int offsetY); - virtual bool update(); - bool _autoScroll; - int _targetOffsetTop; - int _targetOffsetLeft; - - int _scrollPixelsV; - uint32 _scrollTimeV; - uint32 _lastTimeV; - - int _scrollPixelsH; - uint32 _scrollTimeH; - uint32 _lastTimeH; - - virtual bool display(); - uint32 _pfMaxTime; - bool initLoop(); - void pathFinderStep(); - bool isBlockedAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); - bool isWalkableAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); - AdLayer *_mainLayer; - float getZoomAt(int x, int y); - bool getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester = NULL); - AdScene(BaseGame *inGame); - virtual ~AdScene(); - BaseArray _layers; - BaseArray _objects; - BaseArray _waypointGroups; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - int _width; - int _height; - bool addObject(AdObject *Object); - bool removeObject(AdObject *Object); - int _editorMarginH; - int _editorMarginV; - uint32 _editorColFrame; - uint32 _editorColEntity; - uint32 _editorColRegion; - uint32 _editorColBlocked; - uint32 _editorColWaypoints; - uint32 _editorColEntitySel; - uint32 _editorColRegionSel; - uint32 _editorColBlockedSel; - uint32 _editorColWaypointsSel; - uint32 _editorColScale; - uint32 _editorColDecor; - uint32 _editorColDecorSel; - - bool _editorShowRegions; - bool _editorShowBlocked; - bool _editorShowDecor; - bool _editorShowEntities; - bool _editorShowScale; - BaseArray _scaleLevels; - BaseArray _rotLevels; - - virtual bool restoreDeviceObjects(); - int getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester = NULL); - - // 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: - bool persistState(bool saving = true); - void pfAddWaypointGroup(AdWaypointGroup *Wpt, BaseObject *requester = NULL); - bool _pfReady; - BasePoint *_pfTarget; - AdPath *_pfTargetPath; - BaseObject *_pfRequester; - BaseArray _pfPath; - - int _offsetTop; - int _offsetLeft; - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADSCENE_H +#define WINTERMUTE_ADSCENE_H + +#include "engines/wintermute/base/base_fader.h" + +namespace Wintermute { + +class UIWindow; +class AdObject; +class AdRegion; +class BaseViewport; +class AdLayer; +class BasePoint; +class AdWaypointGroup; +class AdPath; +class AdScaleLevel; +class AdRotLevel; +class AdPathPoint; +class AdScene : public BaseObject { +public: + + BaseObject *getNextAccessObject(BaseObject *currObject); + BaseObject *getPrevAccessObject(BaseObject *currObject); + bool getSceneObjects(BaseArray &objects, bool interactiveOnly); + bool getRegionObjects(AdRegion *region, BaseArray &objects, bool interactiveOnly); + + bool afterLoad(); + + bool getRegionsAt(int x, int y, AdRegion **regionList, int numRegions); + bool handleItemAssociations(const char *itemName, bool show); + UIWindow *_shieldWindow; + float getRotationAt(int x, int y); + bool loadState(); + bool saveState(); + bool _persistentState; + bool _persistentStateSprites; + BaseObject *getNodeByName(const char *name); + void setOffset(int offsetLeft, int offsetTop); + bool pointInViewport(int x, int y); + int getOffsetTop(); + int getOffsetLeft(); + bool getViewportSize(int *width = NULL, int *height = NULL); + bool getViewportOffset(int *offsetX = NULL, int *offsetY = NULL); + BaseViewport *_viewport; + BaseFader *_fader; + int _pfPointsNum; + void pfPointsAdd(int x, int y, int distance); + void pfPointsStart(); + bool _initialized; + bool correctTargetPoint(int startX, int startY, int *x, int *y, bool checkFreeObjects = false, BaseObject *requester = NULL); + bool correctTargetPoint2(int startX, int startY, int *targetX, int *targetY, bool checkFreeObjects, BaseObject *requester); + DECLARE_PERSISTENT(AdScene, BaseObject) + bool displayRegionContent(AdRegion *region = NULL, bool display3DOnly = false); + bool displayRegionContentOld(AdRegion *region = NULL); + static int compareObjs(const void *obj1, const void *obj2); + + bool updateFreeObjects(); + bool traverseNodes(bool update = false); + float getScaleAt(int y); + bool sortScaleLevels(); + bool sortRotLevels(); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + uint32 getAlphaAt(int x, int y, bool colorCheck = false); + bool _paralaxScrolling; + void skipTo(int offsetX, int offsetY); + void setDefaults(); + void cleanup(); + void skipToObject(BaseObject *object); + void scrollToObject(BaseObject *object); + void scrollTo(int offsetX, int offsetY); + virtual bool update(); + bool _autoScroll; + int _targetOffsetTop; + int _targetOffsetLeft; + + int _scrollPixelsV; + uint32 _scrollTimeV; + uint32 _lastTimeV; + + int _scrollPixelsH; + uint32 _scrollTimeH; + uint32 _lastTimeH; + + virtual bool display(); + uint32 _pfMaxTime; + bool initLoop(); + void pathFinderStep(); + bool isBlockedAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); + bool isWalkableAt(int x, int y, bool checkFreeObjects = false, BaseObject *requester = NULL); + AdLayer *_mainLayer; + float getZoomAt(int x, int y); + bool getPath(BasePoint source, BasePoint target, AdPath *path, BaseObject *requester = NULL); + AdScene(BaseGame *inGame); + virtual ~AdScene(); + BaseArray _layers; + BaseArray _objects; + BaseArray _waypointGroups; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + int _width; + int _height; + bool addObject(AdObject *Object); + bool removeObject(AdObject *Object); + int _editorMarginH; + int _editorMarginV; + uint32 _editorColFrame; + uint32 _editorColEntity; + uint32 _editorColRegion; + uint32 _editorColBlocked; + uint32 _editorColWaypoints; + uint32 _editorColEntitySel; + uint32 _editorColRegionSel; + uint32 _editorColBlockedSel; + uint32 _editorColWaypointsSel; + uint32 _editorColScale; + uint32 _editorColDecor; + uint32 _editorColDecorSel; + + bool _editorShowRegions; + bool _editorShowBlocked; + bool _editorShowDecor; + bool _editorShowEntities; + bool _editorShowScale; + BaseArray _scaleLevels; + BaseArray _rotLevels; + + virtual bool restoreDeviceObjects(); + int getPointsDist(BasePoint p1, BasePoint p2, BaseObject *requester = NULL); + + // 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: + bool persistState(bool saving = true); + void pfAddWaypointGroup(AdWaypointGroup *Wpt, BaseObject *requester = NULL); + bool _pfReady; + BasePoint *_pfTarget; + AdPath *_pfTargetPath; + BaseObject *_pfRequester; + BaseArray _pfPath; + + int _offsetTop; + int _offsetLeft; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_scene_node.cpp b/engines/wintermute/ad/ad_scene_node.cpp index 4f6acdbc950b..d0202236fd07 100644 --- a/engines/wintermute/ad/ad_scene_node.cpp +++ b/engines/wintermute/ad/ad_scene_node.cpp @@ -1,82 +1,82 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * 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_scene_node.h" -#include "engines/wintermute/base/base_game.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdSceneNode, false) - -////////////////////////////////////////////////////////////////////////// -AdSceneNode::AdSceneNode(BaseGame *inGame) : BaseObject(inGame) { - _type = OBJECT_NONE; - _region = NULL; - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdSceneNode::~AdSceneNode() { - _gameRef->unregisterObject(_region); - _region = NULL; - - _gameRef->unregisterObject(_entity); - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSceneNode::setEntity(AdEntity *entity) { - _type = OBJECT_ENTITY; - _entity = entity; - return _gameRef->registerObject(entity); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSceneNode::setRegion(AdRegion *region) { - _type = OBJECT_REGION; - _region = region; - return _gameRef->registerObject(region); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSceneNode::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_entity)); - persistMgr->transfer(TMEMBER(_region)); - persistMgr->transfer(TMEMBER_INT(_type)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_scene_node.h" +#include "engines/wintermute/base/base_game.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdSceneNode, false) + +////////////////////////////////////////////////////////////////////////// +AdSceneNode::AdSceneNode(BaseGame *inGame) : BaseObject(inGame) { + _type = OBJECT_NONE; + _region = NULL; + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdSceneNode::~AdSceneNode() { + _gameRef->unregisterObject(_region); + _region = NULL; + + _gameRef->unregisterObject(_entity); + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSceneNode::setEntity(AdEntity *entity) { + _type = OBJECT_ENTITY; + _entity = entity; + return _gameRef->registerObject(entity); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSceneNode::setRegion(AdRegion *region) { + _type = OBJECT_REGION; + _region = region; + return _gameRef->registerObject(region); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSceneNode::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_entity)); + persistMgr->transfer(TMEMBER(_region)); + persistMgr->transfer(TMEMBER_INT(_type)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene_node.h b/engines/wintermute/ad/ad_scene_node.h index 8cc50b86c448..5bb1606d0edc 100644 --- a/engines/wintermute/ad/ad_scene_node.h +++ b/engines/wintermute/ad/ad_scene_node.h @@ -1,54 +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_ADSCENENODE_H -#define WINTERMUTE_ADSCENENODE_H - - -#include "engines/wintermute/ad/ad_types.h" // Added by ClassView -#include "engines/wintermute/ad/ad_region.h" // Added by ClassView -#include "engines/wintermute/ad/ad_entity.h" - -namespace Wintermute { - -class AdSceneNode : public BaseObject { -public: - DECLARE_PERSISTENT(AdSceneNode, BaseObject) - bool setRegion(AdRegion *region); - bool setEntity(AdEntity *entity); - AdEntity *_entity; - AdRegion *_region; - TObjectType _type; - AdSceneNode(BaseGame *inGame); - virtual ~AdSceneNode(); - -}; - -} - -#endif +/* 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_ADSCENENODE_H +#define WINTERMUTE_ADSCENENODE_H + + +#include "engines/wintermute/ad/ad_types.h" // Added by ClassView +#include "engines/wintermute/ad/ad_region.h" // Added by ClassView +#include "engines/wintermute/ad/ad_entity.h" + +namespace Wintermute { + +class AdSceneNode : public BaseObject { +public: + DECLARE_PERSISTENT(AdSceneNode, BaseObject) + bool setRegion(AdRegion *region); + bool setEntity(AdEntity *entity); + AdEntity *_entity; + AdRegion *_region; + TObjectType _type; + AdSceneNode(BaseGame *inGame); + virtual ~AdSceneNode(); + +}; + +} + +#endif diff --git a/engines/wintermute/ad/ad_scene_state.cpp b/engines/wintermute/ad/ad_scene_state.cpp index 04fd52c382e8..c09e6a259cf0 100644 --- a/engines/wintermute/ad/ad_scene_state.cpp +++ b/engines/wintermute/ad/ad_scene_state.cpp @@ -1,95 +1,95 @@ -/* 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/ad/ad_scene_state.h" -#include "engines/wintermute/ad/ad_node_state.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdSceneState, false) - -////////////////////////////////////////////////////////////////////////// -AdSceneState::AdSceneState(BaseGame *inGame) : BaseClass(inGame) { - _filename = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdSceneState::~AdSceneState() { - delete[] _filename; - _filename = NULL; - - for (uint32 i = 0; i < _nodeStates.size(); i++) { - delete _nodeStates[i]; - } - _nodeStates.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSceneState::persist(BasePersistenceManager *persistMgr) { - persistMgr->transfer(TMEMBER(_filename)); - _nodeStates.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdSceneState::setFilename(const char *filename) { - delete[] _filename; - _filename = new char [strlen(filename) + 1]; - if (_filename) { - strcpy(_filename, filename); - } -} - - -////////////////////////////////////////////////////////////////////////// -AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) { - for (uint32 i = 0; i < _nodeStates.size(); i++) { - if (scumm_stricmp(_nodeStates[i]->getName(), name) == 0) { - return _nodeStates[i]; - } - } - - if (saving) { - AdNodeState *ret = new AdNodeState(_gameRef); - ret->setName(name); - _nodeStates.add(ret); - - return ret; - } else { - return NULL; - } -} - -} // end of namespace Wintermute +/* 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/ad/ad_scene_state.h" +#include "engines/wintermute/ad/ad_node_state.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdSceneState, false) + +////////////////////////////////////////////////////////////////////////// +AdSceneState::AdSceneState(BaseGame *inGame) : BaseClass(inGame) { + _filename = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdSceneState::~AdSceneState() { + delete[] _filename; + _filename = NULL; + + for (uint32 i = 0; i < _nodeStates.size(); i++) { + delete _nodeStates[i]; + } + _nodeStates.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSceneState::persist(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_filename)); + _nodeStates.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdSceneState::setFilename(const char *filename) { + delete[] _filename; + _filename = new char [strlen(filename) + 1]; + if (_filename) { + strcpy(_filename, filename); + } +} + + +////////////////////////////////////////////////////////////////////////// +AdNodeState *AdSceneState::getNodeState(const char *name, bool saving) { + for (uint32 i = 0; i < _nodeStates.size(); i++) { + if (scumm_stricmp(_nodeStates[i]->getName(), name) == 0) { + return _nodeStates[i]; + } + } + + if (saving) { + AdNodeState *ret = new AdNodeState(_gameRef); + ret->setName(name); + _nodeStates.add(ret); + + return ret; + } else { + return NULL; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_scene_state.h b/engines/wintermute/ad/ad_scene_state.h index 8298d23d7627..2b25393c5a2d 100644 --- a/engines/wintermute/ad/ad_scene_state.h +++ b/engines/wintermute/ad/ad_scene_state.h @@ -1,51 +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_ADSCENESTATE_H -#define WINTERMUTE_ADSCENESTATE_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/base.h" -#include "engines/wintermute/coll_templ.h" - -namespace Wintermute { -class AdNodeState; -class AdSceneState : public BaseClass { -public: - AdNodeState *getNodeState(const char *name, bool saving); - void setFilename(const char *filename); - DECLARE_PERSISTENT(AdSceneState, BaseClass) - AdSceneState(BaseGame *inGame); - virtual ~AdSceneState(); - char *_filename; - BaseArray _nodeStates; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADSCENESTATE_H +#define WINTERMUTE_ADSCENESTATE_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/coll_templ.h" + +namespace Wintermute { +class AdNodeState; +class AdSceneState : public BaseClass { +public: + AdNodeState *getNodeState(const char *name, bool saving); + void setFilename(const char *filename); + DECLARE_PERSISTENT(AdSceneState, BaseClass) + AdSceneState(BaseGame *inGame); + virtual ~AdSceneState(); + char *_filename; + BaseArray _nodeStates; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_sentence.cpp b/engines/wintermute/ad/ad_sentence.cpp index 51765e3fe9b3..1f09d3ae0fb7 100644 --- a/engines/wintermute/ad/ad_sentence.cpp +++ b/engines/wintermute/ad/ad_sentence.cpp @@ -1,360 +1,360 @@ -/* 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_sentence.h" -#include "engines/wintermute/ad/ad_talk_def.h" -#include "engines/wintermute/ad/ad_talk_node.h" -#include "engines/wintermute/ad/ad_game.h" -#include "engines/wintermute/utils/path_util.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/sound/base_sound.h" -#include "engines/wintermute/ad/ad_scene.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdSentence, false) - -////////////////////////////////////////////////////////////////////////// -AdSentence::AdSentence(BaseGame *inGame) : BaseClass(inGame) { - _text = NULL; - _stances = NULL; - _tempStance = NULL; - - _duration = 0; - _startTime = 0; - _currentStance = 0; - - _font = NULL; - - _pos.x = _pos.y = 0; - _width = _gameRef->_renderer->_width; - - _align = (TTextAlign)TAL_CENTER; - - _sound = NULL; - _soundStarted = false; - - _talkDef = NULL; - _currentSprite = NULL; - _currentSkelAnim = NULL; - _fixedPos = false; - _freezable = true; -} - - -////////////////////////////////////////////////////////////////////////// -AdSentence::~AdSentence() { - delete _sound; - delete[] _text; - delete[] _stances; - delete[] _tempStance; - delete _talkDef; - _sound = NULL; - _text = NULL; - _stances = NULL; - _tempStance = NULL; - _talkDef = NULL; - - _currentSprite = NULL; // ref only - _currentSkelAnim = NULL; - _font = NULL; // ref only -} - - -////////////////////////////////////////////////////////////////////////// -void AdSentence::setText(const char *text) { - if (_text) { - delete[] _text; - } - _text = new char[strlen(text) + 1]; - if (_text) { - strcpy(_text, text); - } -} - - -////////////////////////////////////////////////////////////////////////// -void AdSentence::setStances(const char *stances) { - if (_stances) { - delete[] _stances; - } - if (stances) { - _stances = new char[strlen(stances) + 1]; - if (_stances) { - strcpy(_stances, stances); - } - } else { - _stances = NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -char *AdSentence::getCurrentStance() { - return getStance(_currentStance); -} - - -////////////////////////////////////////////////////////////////////////// -char *AdSentence::getNextStance() { - _currentStance++; - return getStance(_currentStance); -} - - -////////////////////////////////////////////////////////////////////////// -char *AdSentence::getStance(int stance) { - if (_stances == NULL) { - return NULL; - } - - if (_tempStance) { - delete[] _tempStance; - } - _tempStance = NULL; - - char *start; - char *curr; - int pos; - - if (stance == 0) { - start = _stances; - } else { - pos = 0; - start = NULL; - curr = _stances; - while (pos < stance) { - if (*curr == '\0') { - break; - } - if (*curr == ',') { - pos++; - } - curr++; - } - if (pos == stance) { - start = curr; - } - } - - if (start == NULL) { - return NULL; - } - - while (*start == ' ' && *start != ',' && *start != '\0') { - start++; - } - - curr = start; - while (*curr != '\0' && *curr != ',') { - curr++; - } - - while (curr > start && *(curr - 1) == ' ') { - curr--; - } - - _tempStance = new char [curr - start + 1]; - if (_tempStance) { - Common::strlcpy(_tempStance, start, curr - start + 1); - } - - return _tempStance; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::display() { - if (!_font || !_text) { - return STATUS_FAILED; - } - - if (_sound && !_soundStarted) { - _sound->play(); - _soundStarted = true; - } - - if (_gameRef->_subtitles) { - int x = _pos.x; - int y = _pos.y; - - if (!_fixedPos) { - x = x - ((AdGame *)_gameRef)->_scene->getOffsetLeft(); - y = y - ((AdGame *)_gameRef)->_scene->getOffsetTop(); - } - - - x = MAX(x, 0); - x = MIN(x, _gameRef->_renderer->_width - _width); - y = MAX(y, 0); - - _font->drawText((byte *)_text, x, y, _width, _align); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void AdSentence::setSound(BaseSound *sound) { - if (!sound) { - return; - } - delete _sound; - _sound = sound; - _soundStarted = false; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::finish() { - if (_sound) { - _sound->stop(); - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::persist(BasePersistenceManager *persistMgr) { - - persistMgr->transfer(TMEMBER(_gameRef)); - - persistMgr->transfer(TMEMBER_INT(_align)); - persistMgr->transfer(TMEMBER(_currentStance)); - persistMgr->transfer(TMEMBER(_currentSprite)); - persistMgr->transfer(TMEMBER(_currentSkelAnim)); - persistMgr->transfer(TMEMBER(_duration)); - persistMgr->transfer(TMEMBER(_font)); - persistMgr->transfer(TMEMBER(_pos)); - persistMgr->transfer(TMEMBER(_sound)); - persistMgr->transfer(TMEMBER(_soundStarted)); - persistMgr->transfer(TMEMBER(_stances)); - persistMgr->transfer(TMEMBER(_startTime)); - persistMgr->transfer(TMEMBER(_talkDef)); - persistMgr->transfer(TMEMBER(_tempStance)); - persistMgr->transfer(TMEMBER(_text)); - persistMgr->transfer(TMEMBER(_width)); - persistMgr->transfer(TMEMBER(_fixedPos)); - persistMgr->transfer(TMEMBER(_freezable)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::setupTalkFile(const char *soundFilename) { - delete _talkDef; - _talkDef = NULL; - _currentSprite = NULL; - - if (!soundFilename) { - return STATUS_OK; - } - - - AnsiString path = PathUtil::getDirectoryName(soundFilename); - AnsiString name = PathUtil::getFileNameWithoutExtension(soundFilename); - - AnsiString talkDefFileName = PathUtil::combine(path, name + ".talk"); - - if (!BaseFileManager::getEngineInstance()->hasFile(talkDefFileName)) { - return STATUS_OK; // no talk def file found - } - - _talkDef = new AdTalkDef(_gameRef); - if (!_talkDef || DID_FAIL(_talkDef->loadFile(talkDefFileName.c_str()))) { - delete _talkDef; - _talkDef = NULL; - return STATUS_FAILED; - } - //_gameRef->LOG(0, "Using .talk file: %s", TalkDefFile); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::update(TDirection dir) { - if (!_talkDef) { - return STATUS_OK; - } - - uint32 currentTime; - // if sound is available, synchronize with sound, otherwise use timer - - /* - if (_sound) CurrentTime = _sound->GetPositionTime(); - else CurrentTime = _gameRef->_timer - _startTime; - */ - currentTime = _gameRef->_timer - _startTime; - - bool talkNodeFound = false; - for (uint32 i = 0; i < _talkDef->_nodes.size(); i++) { - if (_talkDef->_nodes[i]->isInTimeInterval(currentTime, dir)) { - talkNodeFound = true; - - BaseSprite *newSprite = _talkDef->_nodes[i]->getSprite(dir); - if (newSprite != _currentSprite) { - newSprite->reset(); - } - _currentSprite = newSprite; - - if (!_talkDef->_nodes[i]->_playToEnd) { - break; - } - } - } - - - // no talk node, try to use default sprite instead (if any) - if (!talkNodeFound) { - BaseSprite *newSprite = _talkDef->getDefaultSprite(dir); - if (newSprite) { - if (newSprite != _currentSprite) { - newSprite->reset(); - } - _currentSprite = newSprite; - } else { - _currentSprite = NULL; - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdSentence::canSkip() { - // prevent accidental sentence skipping (TODO make configurable) - return (_gameRef->_timer - _startTime) > 300; -} - -} // end of namespace Wintermute +/* 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_sentence.h" +#include "engines/wintermute/ad/ad_talk_def.h" +#include "engines/wintermute/ad/ad_talk_node.h" +#include "engines/wintermute/ad/ad_game.h" +#include "engines/wintermute/utils/path_util.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/sound/base_sound.h" +#include "engines/wintermute/ad/ad_scene.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdSentence, false) + +////////////////////////////////////////////////////////////////////////// +AdSentence::AdSentence(BaseGame *inGame) : BaseClass(inGame) { + _text = NULL; + _stances = NULL; + _tempStance = NULL; + + _duration = 0; + _startTime = 0; + _currentStance = 0; + + _font = NULL; + + _pos.x = _pos.y = 0; + _width = _gameRef->_renderer->_width; + + _align = (TTextAlign)TAL_CENTER; + + _sound = NULL; + _soundStarted = false; + + _talkDef = NULL; + _currentSprite = NULL; + _currentSkelAnim = NULL; + _fixedPos = false; + _freezable = true; +} + + +////////////////////////////////////////////////////////////////////////// +AdSentence::~AdSentence() { + delete _sound; + delete[] _text; + delete[] _stances; + delete[] _tempStance; + delete _talkDef; + _sound = NULL; + _text = NULL; + _stances = NULL; + _tempStance = NULL; + _talkDef = NULL; + + _currentSprite = NULL; // ref only + _currentSkelAnim = NULL; + _font = NULL; // ref only +} + + +////////////////////////////////////////////////////////////////////////// +void AdSentence::setText(const char *text) { + if (_text) { + delete[] _text; + } + _text = new char[strlen(text) + 1]; + if (_text) { + strcpy(_text, text); + } +} + + +////////////////////////////////////////////////////////////////////////// +void AdSentence::setStances(const char *stances) { + if (_stances) { + delete[] _stances; + } + if (stances) { + _stances = new char[strlen(stances) + 1]; + if (_stances) { + strcpy(_stances, stances); + } + } else { + _stances = NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +char *AdSentence::getCurrentStance() { + return getStance(_currentStance); +} + + +////////////////////////////////////////////////////////////////////////// +char *AdSentence::getNextStance() { + _currentStance++; + return getStance(_currentStance); +} + + +////////////////////////////////////////////////////////////////////////// +char *AdSentence::getStance(int stance) { + if (_stances == NULL) { + return NULL; + } + + if (_tempStance) { + delete[] _tempStance; + } + _tempStance = NULL; + + char *start; + char *curr; + int pos; + + if (stance == 0) { + start = _stances; + } else { + pos = 0; + start = NULL; + curr = _stances; + while (pos < stance) { + if (*curr == '\0') { + break; + } + if (*curr == ',') { + pos++; + } + curr++; + } + if (pos == stance) { + start = curr; + } + } + + if (start == NULL) { + return NULL; + } + + while (*start == ' ' && *start != ',' && *start != '\0') { + start++; + } + + curr = start; + while (*curr != '\0' && *curr != ',') { + curr++; + } + + while (curr > start && *(curr - 1) == ' ') { + curr--; + } + + _tempStance = new char [curr - start + 1]; + if (_tempStance) { + Common::strlcpy(_tempStance, start, curr - start + 1); + } + + return _tempStance; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::display() { + if (!_font || !_text) { + return STATUS_FAILED; + } + + if (_sound && !_soundStarted) { + _sound->play(); + _soundStarted = true; + } + + if (_gameRef->_subtitles) { + int x = _pos.x; + int y = _pos.y; + + if (!_fixedPos) { + x = x - ((AdGame *)_gameRef)->_scene->getOffsetLeft(); + y = y - ((AdGame *)_gameRef)->_scene->getOffsetTop(); + } + + + x = MAX(x, 0); + x = MIN(x, _gameRef->_renderer->_width - _width); + y = MAX(y, 0); + + _font->drawText((byte *)_text, x, y, _width, _align); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void AdSentence::setSound(BaseSound *sound) { + if (!sound) { + return; + } + delete _sound; + _sound = sound; + _soundStarted = false; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::finish() { + if (_sound) { + _sound->stop(); + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::persist(BasePersistenceManager *persistMgr) { + + persistMgr->transfer(TMEMBER(_gameRef)); + + persistMgr->transfer(TMEMBER_INT(_align)); + persistMgr->transfer(TMEMBER(_currentStance)); + persistMgr->transfer(TMEMBER(_currentSprite)); + persistMgr->transfer(TMEMBER(_currentSkelAnim)); + persistMgr->transfer(TMEMBER(_duration)); + persistMgr->transfer(TMEMBER(_font)); + persistMgr->transfer(TMEMBER(_pos)); + persistMgr->transfer(TMEMBER(_sound)); + persistMgr->transfer(TMEMBER(_soundStarted)); + persistMgr->transfer(TMEMBER(_stances)); + persistMgr->transfer(TMEMBER(_startTime)); + persistMgr->transfer(TMEMBER(_talkDef)); + persistMgr->transfer(TMEMBER(_tempStance)); + persistMgr->transfer(TMEMBER(_text)); + persistMgr->transfer(TMEMBER(_width)); + persistMgr->transfer(TMEMBER(_fixedPos)); + persistMgr->transfer(TMEMBER(_freezable)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::setupTalkFile(const char *soundFilename) { + delete _talkDef; + _talkDef = NULL; + _currentSprite = NULL; + + if (!soundFilename) { + return STATUS_OK; + } + + + AnsiString path = PathUtil::getDirectoryName(soundFilename); + AnsiString name = PathUtil::getFileNameWithoutExtension(soundFilename); + + AnsiString talkDefFileName = PathUtil::combine(path, name + ".talk"); + + if (!BaseFileManager::getEngineInstance()->hasFile(talkDefFileName)) { + return STATUS_OK; // no talk def file found + } + + _talkDef = new AdTalkDef(_gameRef); + if (!_talkDef || DID_FAIL(_talkDef->loadFile(talkDefFileName.c_str()))) { + delete _talkDef; + _talkDef = NULL; + return STATUS_FAILED; + } + //_gameRef->LOG(0, "Using .talk file: %s", TalkDefFile); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::update(TDirection dir) { + if (!_talkDef) { + return STATUS_OK; + } + + uint32 currentTime; + // if sound is available, synchronize with sound, otherwise use timer + + /* + if (_sound) CurrentTime = _sound->GetPositionTime(); + else CurrentTime = _gameRef->_timer - _startTime; + */ + currentTime = _gameRef->_timer - _startTime; + + bool talkNodeFound = false; + for (uint32 i = 0; i < _talkDef->_nodes.size(); i++) { + if (_talkDef->_nodes[i]->isInTimeInterval(currentTime, dir)) { + talkNodeFound = true; + + BaseSprite *newSprite = _talkDef->_nodes[i]->getSprite(dir); + if (newSprite != _currentSprite) { + newSprite->reset(); + } + _currentSprite = newSprite; + + if (!_talkDef->_nodes[i]->_playToEnd) { + break; + } + } + } + + + // no talk node, try to use default sprite instead (if any) + if (!talkNodeFound) { + BaseSprite *newSprite = _talkDef->getDefaultSprite(dir); + if (newSprite) { + if (newSprite != _currentSprite) { + newSprite->reset(); + } + _currentSprite = newSprite; + } else { + _currentSprite = NULL; + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdSentence::canSkip() { + // prevent accidental sentence skipping (TODO make configurable) + return (_gameRef->_timer - _startTime) > 300; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_sentence.h b/engines/wintermute/ad/ad_sentence.h index 85be09094cd5..e7c94030b9f2 100644 --- a/engines/wintermute/ad/ad_sentence.h +++ b/engines/wintermute/ad/ad_sentence.h @@ -1,85 +1,85 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_ADSENTENCE_H -#define WINTERMUTE_ADSENTENCE_H - - -#include "engines/wintermute/base/base.h" -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/math/rect32.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView -#include "common/rect.h" - -namespace Wintermute { -class AdTalkDef; -class BaseFont; -class BaseSprite; -class BaseSound; -class AdSentence : public BaseClass { -public: - bool _freezable; - bool _fixedPos; - BaseSprite *_currentSprite; - char *_currentSkelAnim; - bool update(TDirection dir = DI_DOWN); - bool setupTalkFile(const char *soundFilename); - DECLARE_PERSISTENT(AdSentence, BaseClass) - bool finish(); - void setSound(BaseSound *Sound); - bool _soundStarted; - BaseSound *_sound; - TTextAlign _align; - bool display(); - int _width; - Point32 _pos; - BaseFont *_font; - char *getNextStance(); - char *getCurrentStance(); - void setStances(const char *stances); - void setText(const char *text); - int _currentStance; - uint32 _startTime; - char *_stances; - char *_text; - uint32 _duration; - AdSentence(BaseGame *inGame); - virtual ~AdSentence(); - AdTalkDef *_talkDef; - - bool canSkip(); - -private: - char *_tempStance; - char *getStance(int stance); - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADSENTENCE_H +#define WINTERMUTE_ADSENTENCE_H + + +#include "engines/wintermute/base/base.h" +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/math/rect32.h" +#include "engines/wintermute/dctypes.h" // Added by ClassView +#include "common/rect.h" + +namespace Wintermute { +class AdTalkDef; +class BaseFont; +class BaseSprite; +class BaseSound; +class AdSentence : public BaseClass { +public: + bool _freezable; + bool _fixedPos; + BaseSprite *_currentSprite; + char *_currentSkelAnim; + bool update(TDirection dir = DI_DOWN); + bool setupTalkFile(const char *soundFilename); + DECLARE_PERSISTENT(AdSentence, BaseClass) + bool finish(); + void setSound(BaseSound *Sound); + bool _soundStarted; + BaseSound *_sound; + TTextAlign _align; + bool display(); + int _width; + Point32 _pos; + BaseFont *_font; + char *getNextStance(); + char *getCurrentStance(); + void setStances(const char *stances); + void setText(const char *text); + int _currentStance; + uint32 _startTime; + char *_stances; + char *_text; + uint32 _duration; + AdSentence(BaseGame *inGame); + virtual ~AdSentence(); + AdTalkDef *_talkDef; + + bool canSkip(); + +private: + char *_tempStance; + char *getStance(int stance); + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_sprite_set.cpp b/engines/wintermute/ad/ad_sprite_set.cpp index 5b605d6e3226..c8cdec03c310 100644 --- a/engines/wintermute/ad/ad_sprite_set.cpp +++ b/engines/wintermute/ad/ad_sprite_set.cpp @@ -1,356 +1,356 @@ -/* 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_sprite_set.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/base_file_manager.h" -#include "engines/wintermute/base/base_sprite.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdSpriteSet, false) - -////////////////////////////////////////////////////////////////////////// -AdSpriteSet::AdSpriteSet(BaseGame *inGame, BaseObject *owner) : BaseObject(inGame) { - _owner = owner; - - for (int i = 0; i < NUM_DIRECTIONS; i++) { - _sprites[i] = NULL; - } -} - - -////////////////////////////////////////////////////////////////////////// -AdSpriteSet::~AdSpriteSet() { - for (int i = 0; i < NUM_DIRECTIONS; i++) { - delete _sprites[i]; - _sprites[i] = NULL; - } - - _owner = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdSpriteSet::LoadFile failed for file '%s'", filename); - return STATUS_FAILED; - } - - bool ret; - - if (DID_FAIL(ret = loadBuffer(buffer, true))) { - _gameRef->LOG(0, "Error parsing SPRITESET file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(SPRITESET) -TOKEN_DEF(NAME) -TOKEN_DEF(UP_LEFT) -TOKEN_DEF(DOWN_LEFT) -TOKEN_DEF(LEFT) -TOKEN_DEF(UP_RIGHT) -TOKEN_DEF(DOWN_RIGHT) -TOKEN_DEF(RIGHT) -TOKEN_DEF(UP) -TOKEN_DEF(DOWN) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(SPRITESET) - TOKEN_TABLE(NAME) - TOKEN_TABLE(UP_LEFT) - TOKEN_TABLE(DOWN_LEFT) - TOKEN_TABLE(LEFT) - TOKEN_TABLE(UP_RIGHT) - TOKEN_TABLE(DOWN_RIGHT) - TOKEN_TABLE(RIGHT) - TOKEN_TABLE(UP) - TOKEN_TABLE(DOWN) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SPRITESET) { - _gameRef->LOG(0, "'SPRITESET' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - BaseSprite *spr = NULL; - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_NAME: - setName((char *)params); - break; - - case TOKEN_LEFT: - delete _sprites[DI_LEFT]; - _sprites[DI_LEFT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_LEFT] = spr; - } - break; - - case TOKEN_RIGHT: - delete _sprites[DI_RIGHT]; - _sprites[DI_RIGHT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_RIGHT] = spr; - } - break; - - case TOKEN_UP: - delete _sprites[DI_UP]; - _sprites[DI_UP] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_UP] = spr; - } - break; - - case TOKEN_DOWN: - delete _sprites[DI_DOWN]; - _sprites[DI_DOWN] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_DOWN] = spr; - } - break; - - case TOKEN_UP_LEFT: - delete _sprites[DI_UPLEFT]; - _sprites[DI_UPLEFT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_UPLEFT] = spr; - } - break; - - case TOKEN_UP_RIGHT: - delete _sprites[DI_UPRIGHT]; - _sprites[DI_UPRIGHT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_UPRIGHT] = spr; - } - break; - - case TOKEN_DOWN_LEFT: - delete _sprites[DI_DOWNLEFT]; - _sprites[DI_DOWNLEFT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_DOWNLEFT] = spr; - } - break; - - case TOKEN_DOWN_RIGHT: - delete _sprites[DI_DOWNRIGHT]; - _sprites[DI_DOWNRIGHT] = NULL; - spr = new BaseSprite(_gameRef, _owner); - if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { - cmd = PARSERR_GENERIC; - } else { - _sprites[DI_DOWNRIGHT] = spr; - } - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in SPRITESET definition"); - return STATUS_FAILED; - } - - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading SPRITESET definition"); - if (spr) { - delete spr; - } - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdSpriteSet::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_owner)); - for (int i = 0; i < NUM_DIRECTIONS; i++) { - persistMgr->transfer("", &_sprites[i]); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdSpriteSet::getSprite(TDirection direction) { - int dir = (int)direction; - if (dir < 0) { - dir = 0; - } - if (dir >= NUM_DIRECTIONS) { - dir = NUM_DIRECTIONS - 1; - } - - BaseSprite *ret = NULL; - - // find nearest set sprite - int numSteps = 0; - for (int i = dir; i >= 0; i--) { - if (_sprites[i] != NULL) { - ret = _sprites[i]; - numSteps = dir - i; - break; - } - } - - for (int i = dir; i < NUM_DIRECTIONS; i++) { - if (_sprites[i] != NULL) { - if (ret == NULL || numSteps > i - dir) { - return _sprites[i]; - } else { - return ret; - } - } - } - - return ret; -} - - - -////////////////////////////////////////////////////////////////////////// -bool AdSpriteSet::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "SPRITESET {\n"); - if (getName()) { - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - } - for (int i = 0; i < NUM_DIRECTIONS; i++) { - if (_sprites[i]) { - switch (i) { - case DI_UP: - buffer->putTextIndent(indent + 2, "UP=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_UPRIGHT: - buffer->putTextIndent(indent + 2, "UP_RIGHT=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_RIGHT: - buffer->putTextIndent(indent + 2, "RIGHT=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_DOWNRIGHT: - buffer->putTextIndent(indent + 2, "DOWN_RIGHT=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_DOWN: - buffer->putTextIndent(indent + 2, "DOWN=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_DOWNLEFT: - buffer->putTextIndent(indent + 2, "DOWN_LEFT=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_LEFT: - buffer->putTextIndent(indent + 2, "LEFT=\"%s\"\n", _sprites[i]->getFilename()); - break; - case DI_UPLEFT: - buffer->putTextIndent(indent + 2, "UP_LEFT=\"%s\"\n", _sprites[i]->getFilename()); - break; - } - } - } - - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool AdSpriteSet::containsSprite(BaseSprite *sprite) { - if (!sprite) { - return false; - } - - for (int i = 0; i < NUM_DIRECTIONS; i++) { - if (_sprites[i] == sprite) { - return true; - } - } - return false; -} - -} // end of namespace Wintermute +/* 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_sprite_set.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/base_file_manager.h" +#include "engines/wintermute/base/base_sprite.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdSpriteSet, false) + +////////////////////////////////////////////////////////////////////////// +AdSpriteSet::AdSpriteSet(BaseGame *inGame, BaseObject *owner) : BaseObject(inGame) { + _owner = owner; + + for (int i = 0; i < NUM_DIRECTIONS; i++) { + _sprites[i] = NULL; + } +} + + +////////////////////////////////////////////////////////////////////////// +AdSpriteSet::~AdSpriteSet() { + for (int i = 0; i < NUM_DIRECTIONS; i++) { + delete _sprites[i]; + _sprites[i] = NULL; + } + + _owner = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSpriteSet::loadFile(const char *filename, int lifeTime, TSpriteCacheType cacheType) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdSpriteSet::LoadFile failed for file '%s'", filename); + return STATUS_FAILED; + } + + bool ret; + + if (DID_FAIL(ret = loadBuffer(buffer, true))) { + _gameRef->LOG(0, "Error parsing SPRITESET file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(SPRITESET) +TOKEN_DEF(NAME) +TOKEN_DEF(UP_LEFT) +TOKEN_DEF(DOWN_LEFT) +TOKEN_DEF(LEFT) +TOKEN_DEF(UP_RIGHT) +TOKEN_DEF(DOWN_RIGHT) +TOKEN_DEF(RIGHT) +TOKEN_DEF(UP) +TOKEN_DEF(DOWN) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdSpriteSet::loadBuffer(byte *buffer, bool complete, int lifeTime, TSpriteCacheType cacheType) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(SPRITESET) + TOKEN_TABLE(NAME) + TOKEN_TABLE(UP_LEFT) + TOKEN_TABLE(DOWN_LEFT) + TOKEN_TABLE(LEFT) + TOKEN_TABLE(UP_RIGHT) + TOKEN_TABLE(DOWN_RIGHT) + TOKEN_TABLE(RIGHT) + TOKEN_TABLE(UP) + TOKEN_TABLE(DOWN) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_SPRITESET) { + _gameRef->LOG(0, "'SPRITESET' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + BaseSprite *spr = NULL; + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_NAME: + setName((char *)params); + break; + + case TOKEN_LEFT: + delete _sprites[DI_LEFT]; + _sprites[DI_LEFT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_LEFT] = spr; + } + break; + + case TOKEN_RIGHT: + delete _sprites[DI_RIGHT]; + _sprites[DI_RIGHT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_RIGHT] = spr; + } + break; + + case TOKEN_UP: + delete _sprites[DI_UP]; + _sprites[DI_UP] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_UP] = spr; + } + break; + + case TOKEN_DOWN: + delete _sprites[DI_DOWN]; + _sprites[DI_DOWN] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_DOWN] = spr; + } + break; + + case TOKEN_UP_LEFT: + delete _sprites[DI_UPLEFT]; + _sprites[DI_UPLEFT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_UPLEFT] = spr; + } + break; + + case TOKEN_UP_RIGHT: + delete _sprites[DI_UPRIGHT]; + _sprites[DI_UPRIGHT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_UPRIGHT] = spr; + } + break; + + case TOKEN_DOWN_LEFT: + delete _sprites[DI_DOWNLEFT]; + _sprites[DI_DOWNLEFT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_DOWNLEFT] = spr; + } + break; + + case TOKEN_DOWN_RIGHT: + delete _sprites[DI_DOWNRIGHT]; + _sprites[DI_DOWNRIGHT] = NULL; + spr = new BaseSprite(_gameRef, _owner); + if (!spr || DID_FAIL(spr->loadFile((char *)params, lifeTime, cacheType))) { + cmd = PARSERR_GENERIC; + } else { + _sprites[DI_DOWNRIGHT] = spr; + } + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in SPRITESET definition"); + return STATUS_FAILED; + } + + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading SPRITESET definition"); + if (spr) { + delete spr; + } + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdSpriteSet::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_owner)); + for (int i = 0; i < NUM_DIRECTIONS; i++) { + persistMgr->transfer("", &_sprites[i]); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdSpriteSet::getSprite(TDirection direction) { + int dir = (int)direction; + if (dir < 0) { + dir = 0; + } + if (dir >= NUM_DIRECTIONS) { + dir = NUM_DIRECTIONS - 1; + } + + BaseSprite *ret = NULL; + + // find nearest set sprite + int numSteps = 0; + for (int i = dir; i >= 0; i--) { + if (_sprites[i] != NULL) { + ret = _sprites[i]; + numSteps = dir - i; + break; + } + } + + for (int i = dir; i < NUM_DIRECTIONS; i++) { + if (_sprites[i] != NULL) { + if (ret == NULL || numSteps > i - dir) { + return _sprites[i]; + } else { + return ret; + } + } + } + + return ret; +} + + + +////////////////////////////////////////////////////////////////////////// +bool AdSpriteSet::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "SPRITESET {\n"); + if (getName()) { + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + } + for (int i = 0; i < NUM_DIRECTIONS; i++) { + if (_sprites[i]) { + switch (i) { + case DI_UP: + buffer->putTextIndent(indent + 2, "UP=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_UPRIGHT: + buffer->putTextIndent(indent + 2, "UP_RIGHT=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_RIGHT: + buffer->putTextIndent(indent + 2, "RIGHT=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_DOWNRIGHT: + buffer->putTextIndent(indent + 2, "DOWN_RIGHT=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_DOWN: + buffer->putTextIndent(indent + 2, "DOWN=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_DOWNLEFT: + buffer->putTextIndent(indent + 2, "DOWN_LEFT=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_LEFT: + buffer->putTextIndent(indent + 2, "LEFT=\"%s\"\n", _sprites[i]->getFilename()); + break; + case DI_UPLEFT: + buffer->putTextIndent(indent + 2, "UP_LEFT=\"%s\"\n", _sprites[i]->getFilename()); + break; + } + } + } + + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool AdSpriteSet::containsSprite(BaseSprite *sprite) { + if (!sprite) { + return false; + } + + for (int i = 0; i < NUM_DIRECTIONS; i++) { + if (_sprites[i] == sprite) { + return true; + } + } + return false; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_sprite_set.h b/engines/wintermute/ad/ad_sprite_set.h index 385511485033..ba5da0ff2e8c 100644 --- a/engines/wintermute/ad/ad_sprite_set.h +++ b/engines/wintermute/ad/ad_sprite_set.h @@ -1,53 +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_ADSPRITESET_H -#define WINTERMUTE_ADSPRITESET_H - - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { -class BaseSprite; -class AdSpriteSet : public BaseObject { -public: - bool containsSprite(BaseSprite *sprite); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); - BaseSprite *getSprite(TDirection direction); - DECLARE_PERSISTENT(AdSpriteSet, BaseObject) - BaseObject *_owner; - AdSpriteSet(BaseGame *inGame, BaseObject *owner = NULL); - virtual ~AdSpriteSet(); - bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - bool loadBuffer(byte *buffer, bool complete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); - BaseSprite *_sprites[NUM_DIRECTIONS]; -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADSPRITESET_H +#define WINTERMUTE_ADSPRITESET_H + + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { +class BaseSprite; +class AdSpriteSet : public BaseObject { +public: + bool containsSprite(BaseSprite *sprite); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); + BaseSprite *getSprite(TDirection direction); + DECLARE_PERSISTENT(AdSpriteSet, BaseObject) + BaseObject *_owner; + AdSpriteSet(BaseGame *inGame, BaseObject *owner = NULL); + virtual ~AdSpriteSet(); + bool loadFile(const char *filename, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); + bool loadBuffer(byte *buffer, bool complete = true, int lifeTime = -1, TSpriteCacheType cacheType = CACHE_ALL); + BaseSprite *_sprites[NUM_DIRECTIONS]; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_talk_def.cpp b/engines/wintermute/ad/ad_talk_def.cpp index cd96345fc88d..8cb489509bc8 100644 --- a/engines/wintermute/ad/ad_talk_def.cpp +++ b/engines/wintermute/ad/ad_talk_def.cpp @@ -1,285 +1,285 @@ -/* 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_talk_def.h" -#include "engines/wintermute/ad/ad_talk_node.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/ad/ad_sprite_set.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/utils/utils.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdTalkDef, false) - -////////////////////////////////////////////////////////////////////////// -AdTalkDef::AdTalkDef(BaseGame *inGame) : BaseObject(inGame) { - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; - - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdTalkDef::~AdTalkDef() { - for (uint32 i = 0; i < _nodes.size(); i++) { - delete _nodes[i]; - } - _nodes.clear(); - - delete[] _defaultSpriteFilename; - delete _defaultSprite; - _defaultSpriteFilename = NULL; - _defaultSprite = NULL; - - delete[] _defaultSpriteSetFilename; - delete _defaultSpriteSet; - _defaultSpriteSetFilename = NULL; - _defaultSpriteSet = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkDef::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdTalkDef::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 TALK file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(TALK) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(ACTION) -TOKEN_DEF(DEFAULT_SPRITESET_FILE) -TOKEN_DEF(DEFAULT_SPRITESET) -TOKEN_DEF(DEFAULT_SPRITE) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdTalkDef::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(TALK) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(ACTION) - TOKEN_TABLE(DEFAULT_SPRITESET_FILE) - TOKEN_TABLE(DEFAULT_SPRITESET) - TOKEN_TABLE(DEFAULT_SPRITE) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TALK) { - _gameRef->LOG(0, "'TALK' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_ACTION: { - AdTalkNode *node = new AdTalkNode(_gameRef); - if (node && DID_SUCCEED(node->loadBuffer(params, false))) { - _nodes.add(node); - } else { - delete node; - node = NULL; - cmd = PARSERR_GENERIC; - } - } - break; - - case TOKEN_DEFAULT_SPRITE: - BaseUtils::setString(&_defaultSpriteFilename, (char *)params); - break; - - case TOKEN_DEFAULT_SPRITESET_FILE: - BaseUtils::setString(&_defaultSpriteSetFilename, (char *)params); - break; - - case TOKEN_DEFAULT_SPRITESET: { - delete _defaultSpriteSet; - _defaultSpriteSet = new AdSpriteSet(_gameRef); - if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadBuffer(params, false))) { - delete _defaultSpriteSet; - _defaultSpriteSet = NULL; - cmd = PARSERR_GENERIC; - } - } - break; - - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in TALK definition"); - return STATUS_FAILED; - } - - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading TALK definition"); - return STATUS_FAILED; - } - - delete _defaultSprite; - delete _defaultSpriteSet; - _defaultSprite = NULL; - _defaultSpriteSet = NULL; - - if (_defaultSpriteFilename) { - _defaultSprite = new BaseSprite(_gameRef); - if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) { - return STATUS_FAILED; - } - } - - if (_defaultSpriteSetFilename) { - _defaultSpriteSet = new AdSpriteSet(_gameRef); - if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { - return STATUS_FAILED; - } - } - - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkDef::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_defaultSprite)); - persistMgr->transfer(TMEMBER(_defaultSpriteFilename)); - persistMgr->transfer(TMEMBER(_defaultSpriteSet)); - persistMgr->transfer(TMEMBER(_defaultSpriteSetFilename)); - - _nodes.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkDef::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "TALK {\n"); - if (_defaultSpriteFilename) { - buffer->putTextIndent(indent + 2, "DEFAULT_SPRITE=\"%s\"\n", _defaultSpriteFilename); - } - - if (_defaultSpriteSetFilename) { - buffer->putTextIndent(indent + 2, "DEFAULT_SPRITESET_FILE=\"%s\"\n", _defaultSpriteSetFilename); - } else if (_defaultSpriteSet) { - _defaultSpriteSet->saveAsText(buffer, indent + 2); - } - - for (uint32 i = 0; i < _nodes.size(); i++) { - _nodes[i]->saveAsText(buffer, indent + 2); - buffer->putTextIndent(indent, "\n"); - } - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkDef::loadDefaultSprite() { - if (_defaultSpriteFilename && !_defaultSprite) { - _defaultSprite = new BaseSprite(_gameRef); - if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) { - delete _defaultSprite; - _defaultSprite = NULL; - return STATUS_FAILED; - } else { - return STATUS_OK; - } - } else if (_defaultSpriteSetFilename && !_defaultSpriteSet) { - _defaultSpriteSet = new AdSpriteSet(_gameRef); - if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { - delete _defaultSpriteSet; - _defaultSpriteSet = NULL; - return STATUS_FAILED; - } else { - return STATUS_OK; - } - } else { - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdTalkDef::getDefaultSprite(TDirection dir) { - loadDefaultSprite(); - if (_defaultSprite) { - return _defaultSprite; - } else if (_defaultSpriteSet) { - return _defaultSpriteSet->getSprite(dir); - } else { - return NULL; - } -} - -} // end of namespace Wintermute +/* 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_talk_def.h" +#include "engines/wintermute/ad/ad_talk_node.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/ad/ad_sprite_set.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/utils/utils.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdTalkDef, false) + +////////////////////////////////////////////////////////////////////////// +AdTalkDef::AdTalkDef(BaseGame *inGame) : BaseObject(inGame) { + _defaultSpriteFilename = NULL; + _defaultSprite = NULL; + + _defaultSpriteSetFilename = NULL; + _defaultSpriteSet = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdTalkDef::~AdTalkDef() { + for (uint32 i = 0; i < _nodes.size(); i++) { + delete _nodes[i]; + } + _nodes.clear(); + + delete[] _defaultSpriteFilename; + delete _defaultSprite; + _defaultSpriteFilename = NULL; + _defaultSprite = NULL; + + delete[] _defaultSpriteSetFilename; + delete _defaultSpriteSet; + _defaultSpriteSetFilename = NULL; + _defaultSpriteSet = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkDef::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdTalkDef::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 TALK file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(TALK) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(ACTION) +TOKEN_DEF(DEFAULT_SPRITESET_FILE) +TOKEN_DEF(DEFAULT_SPRITESET) +TOKEN_DEF(DEFAULT_SPRITE) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdTalkDef::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(TALK) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(ACTION) + TOKEN_TABLE(DEFAULT_SPRITESET_FILE) + TOKEN_TABLE(DEFAULT_SPRITESET) + TOKEN_TABLE(DEFAULT_SPRITE) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TALK) { + _gameRef->LOG(0, "'TALK' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_ACTION: { + AdTalkNode *node = new AdTalkNode(_gameRef); + if (node && DID_SUCCEED(node->loadBuffer(params, false))) { + _nodes.add(node); + } else { + delete node; + node = NULL; + cmd = PARSERR_GENERIC; + } + } + break; + + case TOKEN_DEFAULT_SPRITE: + BaseUtils::setString(&_defaultSpriteFilename, (char *)params); + break; + + case TOKEN_DEFAULT_SPRITESET_FILE: + BaseUtils::setString(&_defaultSpriteSetFilename, (char *)params); + break; + + case TOKEN_DEFAULT_SPRITESET: { + delete _defaultSpriteSet; + _defaultSpriteSet = new AdSpriteSet(_gameRef); + if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadBuffer(params, false))) { + delete _defaultSpriteSet; + _defaultSpriteSet = NULL; + cmd = PARSERR_GENERIC; + } + } + break; + + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in TALK definition"); + return STATUS_FAILED; + } + + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading TALK definition"); + return STATUS_FAILED; + } + + delete _defaultSprite; + delete _defaultSpriteSet; + _defaultSprite = NULL; + _defaultSpriteSet = NULL; + + if (_defaultSpriteFilename) { + _defaultSprite = new BaseSprite(_gameRef); + if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) { + return STATUS_FAILED; + } + } + + if (_defaultSpriteSetFilename) { + _defaultSpriteSet = new AdSpriteSet(_gameRef); + if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { + return STATUS_FAILED; + } + } + + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkDef::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_defaultSprite)); + persistMgr->transfer(TMEMBER(_defaultSpriteFilename)); + persistMgr->transfer(TMEMBER(_defaultSpriteSet)); + persistMgr->transfer(TMEMBER(_defaultSpriteSetFilename)); + + _nodes.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkDef::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "TALK {\n"); + if (_defaultSpriteFilename) { + buffer->putTextIndent(indent + 2, "DEFAULT_SPRITE=\"%s\"\n", _defaultSpriteFilename); + } + + if (_defaultSpriteSetFilename) { + buffer->putTextIndent(indent + 2, "DEFAULT_SPRITESET_FILE=\"%s\"\n", _defaultSpriteSetFilename); + } else if (_defaultSpriteSet) { + _defaultSpriteSet->saveAsText(buffer, indent + 2); + } + + for (uint32 i = 0; i < _nodes.size(); i++) { + _nodes[i]->saveAsText(buffer, indent + 2); + buffer->putTextIndent(indent, "\n"); + } + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkDef::loadDefaultSprite() { + if (_defaultSpriteFilename && !_defaultSprite) { + _defaultSprite = new BaseSprite(_gameRef); + if (!_defaultSprite || DID_FAIL(_defaultSprite->loadFile(_defaultSpriteFilename))) { + delete _defaultSprite; + _defaultSprite = NULL; + return STATUS_FAILED; + } else { + return STATUS_OK; + } + } else if (_defaultSpriteSetFilename && !_defaultSpriteSet) { + _defaultSpriteSet = new AdSpriteSet(_gameRef); + if (!_defaultSpriteSet || DID_FAIL(_defaultSpriteSet->loadFile(_defaultSpriteSetFilename))) { + delete _defaultSpriteSet; + _defaultSpriteSet = NULL; + return STATUS_FAILED; + } else { + return STATUS_OK; + } + } else { + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdTalkDef::getDefaultSprite(TDirection dir) { + loadDefaultSprite(); + if (_defaultSprite) { + return _defaultSprite; + } else if (_defaultSpriteSet) { + return _defaultSpriteSet->getSprite(dir); + } else { + return NULL; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_def.h b/engines/wintermute/ad/ad_talk_def.h index f748aa4e7a31..d147212775fd 100644 --- a/engines/wintermute/ad/ad_talk_def.h +++ b/engines/wintermute/ad/ad_talk_def.h @@ -1,58 +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_ADTALKDEF_H -#define WINTERMUTE_ADTALKDEF_H - -#include "engines/wintermute/coll_templ.h" -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { -class AdTalkNode; -class AdSpriteSet; -class AdTalkDef : public BaseObject { -public: - char *_defaultSpriteSetFilename; - AdSpriteSet *_defaultSpriteSet; - BaseSprite *getDefaultSprite(TDirection Dir); - bool loadDefaultSprite(); - DECLARE_PERSISTENT(AdTalkDef, BaseObject) - - AdTalkDef(BaseGame *inGame); - virtual ~AdTalkDef(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - BaseArray _nodes; - char *_defaultSpriteFilename; - BaseSprite *_defaultSprite; - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADTALKDEF_H +#define WINTERMUTE_ADTALKDEF_H + +#include "engines/wintermute/coll_templ.h" +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { +class AdTalkNode; +class AdSpriteSet; +class AdTalkDef : public BaseObject { +public: + char *_defaultSpriteSetFilename; + AdSpriteSet *_defaultSpriteSet; + BaseSprite *getDefaultSprite(TDirection Dir); + bool loadDefaultSprite(); + DECLARE_PERSISTENT(AdTalkDef, BaseObject) + + AdTalkDef(BaseGame *inGame); + virtual ~AdTalkDef(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + BaseArray _nodes; + char *_defaultSpriteFilename; + BaseSprite *_defaultSprite; + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_talk_holder.cpp b/engines/wintermute/ad/ad_talk_holder.cpp index 89d7bd8a46ac..1e4ec2645964 100644 --- a/engines/wintermute/ad/ad_talk_holder.cpp +++ b/engines/wintermute/ad/ad_talk_holder.cpp @@ -1,402 +1,402 @@ -/* 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_talk_holder.h" -#include "engines/wintermute/base/base_dynamic_buffer.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/base_game.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/base_engine.h" -#include "common/str.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdTalkHolder, false) - -////////////////////////////////////////////////////////////////////////// -AdTalkHolder::AdTalkHolder(BaseGame *inGame) : AdObject(inGame) { - _sprite = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -AdTalkHolder::~AdTalkHolder() { - delete _sprite; - _sprite = NULL; - - for (uint32 i = 0; i < _talkSprites.size(); i++) { - delete _talkSprites[i]; - } - _talkSprites.clear(); - - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - delete _talkSpritesEx[i]; - } - _talkSpritesEx.clear(); -} - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { - BaseSprite *ret = NULL; - - - // forced stance? - if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { - _forcedTalkAnimUsed = true; - delete _animSprite; - _animSprite = new BaseSprite(_gameRef, this); - if (_animSprite) { - bool res = _animSprite->loadFile(_forcedTalkAnimName); - if (DID_FAIL(res)) { - _gameRef->LOG(res, "AdTalkHolder::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); - delete _animSprite; - _animSprite = NULL; - } else { - return _animSprite; - } - } - } - - - if (stance != NULL) { - // search special talk stances - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { - ret = _talkSpritesEx[i]; - break; - } - } - if (ret == NULL) { - // serach generic talk stances - for (uint32 i = 0; i < _talkSprites.size(); i++) { - if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { - ret = _talkSprites[i]; - break; - } - } - } - } - - // not a valid stance? get a random one - if (ret == NULL) { - if (_talkSprites.size() < 1) { - ret = _sprite; - } else { - // TODO: remember last - int rnd = BaseEngine::instance().randInt(0, _talkSprites.size() - 1); - ret = _talkSprites[rnd]; - } - } - - return ret; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool AdTalkHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetSprite - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetSprite") == 0) { - stack->correctParams(1); - - ScValue *val = stack->pop(); - - bool setCurrent = false; - if (_currentSprite && _currentSprite == _sprite) { - setCurrent = true; - } - - delete _sprite; - _sprite = NULL; - - if (val->isNULL()) { - _sprite = NULL; - if (setCurrent) { - _currentSprite = NULL; - } - stack->pushBool(true); - } else { - const char *filename = val->getString(); - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - script->runtimeError("SetSprite method failed for file '%s'", filename); - stack->pushBool(false); - } else { - _sprite = spr; - if (setCurrent) { - _currentSprite = _sprite; - } - stack->pushBool(true); - } - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetSprite") == 0) { - stack->correctParams(0); - - if (!_sprite || !_sprite->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_sprite->getFilename()); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetSpriteObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetSpriteObject") == 0) { - stack->correctParams(0); - - if (!_sprite) { - stack->pushNULL(); - } else { - stack->pushNative(_sprite, true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // AddTalkSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "AddTalkSprite") == 0) { - stack->correctParams(2); - - const char *filename = stack->pop()->getString(); - bool ex = stack->pop()->getBool(); - - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - stack->pushBool(false); - script->runtimeError("AddTalkSprite method failed for file '%s'", filename); - } else { - if (ex) { - _talkSpritesEx.add(spr); - } else { - _talkSprites.add(spr); - } - stack->pushBool(true); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // RemoveTalkSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "RemoveTalkSprite") == 0) { - stack->correctParams(2); - - const char *filename = stack->pop()->getString(); - bool ex = stack->pop()->getBool(); - - bool setCurrent = false; - bool setTemp2 = false; - - if (ex) { - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - if (scumm_stricmp(_talkSpritesEx[i]->getFilename(), filename) == 0) { - if (_currentSprite == _talkSpritesEx[i]) { - setCurrent = true; - } - if (_tempSprite2 == _talkSpritesEx[i]) { - setTemp2 = true; - } - delete _talkSpritesEx[i]; - _talkSpritesEx.remove_at(i); - break; - } - } - } else { - for (uint32 i = 0; i < _talkSprites.size(); i++) { - if (scumm_stricmp(_talkSprites[i]->getFilename(), filename) == 0) { - if (_currentSprite == _talkSprites[i]) { - setCurrent = true; - } - if (_tempSprite2 == _talkSprites[i]) { - setTemp2 = true; - } - delete _talkSprites[i]; - _talkSprites.remove_at(i); - break; - } - } - - } - - stack->pushBool(true); - if (setCurrent) { - _currentSprite = _sprite; - } - if (setTemp2) { - _tempSprite2 = _sprite; - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetTalkSprite - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetTalkSprite") == 0) { - stack->correctParams(2); - - const char *filename = stack->pop()->getString(); - bool ex = stack->pop()->getBool(); - bool setCurrent = false; - bool setTemp2 = false; - - BaseSprite *spr = new BaseSprite(_gameRef, this); - if (!spr || DID_FAIL(spr->loadFile(filename))) { - stack->pushBool(false); - script->runtimeError("SetTalkSprite method failed for file '%s'", filename); - } else { - - // delete current - if (ex) { - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - if (_talkSpritesEx[i] == _currentSprite) { - setCurrent = true; - } - if (_talkSpritesEx[i] == _tempSprite2) { - setTemp2 = true; - } - delete _talkSpritesEx[i]; - } - _talkSpritesEx.clear(); - } else { - for (uint32 i = 0; i < _talkSprites.size(); i++) { - if (_talkSprites[i] == _currentSprite) { - setCurrent = true; - } - if (_talkSprites[i] == _tempSprite2) { - setTemp2 = true; - } - delete _talkSprites[i]; - } - _talkSprites.clear(); - } - - // set new - if (ex) { - _talkSpritesEx.add(spr); - } else { - _talkSprites.add(spr); - } - stack->pushBool(true); - - if (setCurrent) { - _currentSprite = spr; - } - if (setTemp2) { - _tempSprite2 = spr; - } - } - return STATUS_OK; - } else { - return AdObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdTalkHolder::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type (RO) - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("talk-holder"); - return _scValue; - } else { - return AdObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkHolder::scSetProperty(const char *name, ScValue *value) { - /* - ////////////////////////////////////////////////////////////////////////// - // Item - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Item")==0){ - SetItem(value->getString()); - return STATUS_OK; - } - - else*/ return AdObject::scSetProperty(name, value); -} - - -////////////////////////////////////////////////////////////////////////// -const char *AdTalkHolder::scToString() { - return "[talk-holder object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkHolder::saveAsText(BaseDynamicBuffer *buffer, int indent) { - for (uint32 i = 0; i < _talkSprites.size(); i++) { - if (_talkSprites[i]->getFilename()) { - buffer->putTextIndent(indent + 2, "TALK=\"%s\"\n", _talkSprites[i]->getFilename()); - } - } - - for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { - if (_talkSpritesEx[i]->getFilename()) { - buffer->putTextIndent(indent + 2, "TALK_SPECIAL=\"%s\"\n", _talkSpritesEx[i]->getFilename()); - } - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkHolder::persist(BasePersistenceManager *persistMgr) { - AdObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_sprite)); - _talkSprites.persist(persistMgr); - _talkSpritesEx.persist(persistMgr); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_talk_holder.h" +#include "engines/wintermute/base/base_dynamic_buffer.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/base_game.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/base/base_engine.h" +#include "common/str.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdTalkHolder, false) + +////////////////////////////////////////////////////////////////////////// +AdTalkHolder::AdTalkHolder(BaseGame *inGame) : AdObject(inGame) { + _sprite = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +AdTalkHolder::~AdTalkHolder() { + delete _sprite; + _sprite = NULL; + + for (uint32 i = 0; i < _talkSprites.size(); i++) { + delete _talkSprites[i]; + } + _talkSprites.clear(); + + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + delete _talkSpritesEx[i]; + } + _talkSpritesEx.clear(); +} + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdTalkHolder::getTalkStance(const char *stance) { + BaseSprite *ret = NULL; + + + // forced stance? + if (_forcedTalkAnimName && !_forcedTalkAnimUsed) { + _forcedTalkAnimUsed = true; + delete _animSprite; + _animSprite = new BaseSprite(_gameRef, this); + if (_animSprite) { + bool res = _animSprite->loadFile(_forcedTalkAnimName); + if (DID_FAIL(res)) { + _gameRef->LOG(res, "AdTalkHolder::GetTalkStance: error loading talk sprite (object:\"%s\" sprite:\"%s\")", getName(), _forcedTalkAnimName); + delete _animSprite; + _animSprite = NULL; + } else { + return _animSprite; + } + } + } + + + if (stance != NULL) { + // search special talk stances + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->getName(), stance) == 0) { + ret = _talkSpritesEx[i]; + break; + } + } + if (ret == NULL) { + // serach generic talk stances + for (uint32 i = 0; i < _talkSprites.size(); i++) { + if (scumm_stricmp(_talkSprites[i]->getName(), stance) == 0) { + ret = _talkSprites[i]; + break; + } + } + } + } + + // not a valid stance? get a random one + if (ret == NULL) { + if (_talkSprites.size() < 1) { + ret = _sprite; + } else { + // TODO: remember last + int rnd = BaseEngine::instance().randInt(0, _talkSprites.size() - 1); + ret = _talkSprites[rnd]; + } + } + + return ret; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool AdTalkHolder::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetSprite + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetSprite") == 0) { + stack->correctParams(1); + + ScValue *val = stack->pop(); + + bool setCurrent = false; + if (_currentSprite && _currentSprite == _sprite) { + setCurrent = true; + } + + delete _sprite; + _sprite = NULL; + + if (val->isNULL()) { + _sprite = NULL; + if (setCurrent) { + _currentSprite = NULL; + } + stack->pushBool(true); + } else { + const char *filename = val->getString(); + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + script->runtimeError("SetSprite method failed for file '%s'", filename); + stack->pushBool(false); + } else { + _sprite = spr; + if (setCurrent) { + _currentSprite = _sprite; + } + stack->pushBool(true); + } + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetSprite") == 0) { + stack->correctParams(0); + + if (!_sprite || !_sprite->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_sprite->getFilename()); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetSpriteObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetSpriteObject") == 0) { + stack->correctParams(0); + + if (!_sprite) { + stack->pushNULL(); + } else { + stack->pushNative(_sprite, true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // AddTalkSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "AddTalkSprite") == 0) { + stack->correctParams(2); + + const char *filename = stack->pop()->getString(); + bool ex = stack->pop()->getBool(); + + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + stack->pushBool(false); + script->runtimeError("AddTalkSprite method failed for file '%s'", filename); + } else { + if (ex) { + _talkSpritesEx.add(spr); + } else { + _talkSprites.add(spr); + } + stack->pushBool(true); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // RemoveTalkSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "RemoveTalkSprite") == 0) { + stack->correctParams(2); + + const char *filename = stack->pop()->getString(); + bool ex = stack->pop()->getBool(); + + bool setCurrent = false; + bool setTemp2 = false; + + if (ex) { + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + if (scumm_stricmp(_talkSpritesEx[i]->getFilename(), filename) == 0) { + if (_currentSprite == _talkSpritesEx[i]) { + setCurrent = true; + } + if (_tempSprite2 == _talkSpritesEx[i]) { + setTemp2 = true; + } + delete _talkSpritesEx[i]; + _talkSpritesEx.remove_at(i); + break; + } + } + } else { + for (uint32 i = 0; i < _talkSprites.size(); i++) { + if (scumm_stricmp(_talkSprites[i]->getFilename(), filename) == 0) { + if (_currentSprite == _talkSprites[i]) { + setCurrent = true; + } + if (_tempSprite2 == _talkSprites[i]) { + setTemp2 = true; + } + delete _talkSprites[i]; + _talkSprites.remove_at(i); + break; + } + } + + } + + stack->pushBool(true); + if (setCurrent) { + _currentSprite = _sprite; + } + if (setTemp2) { + _tempSprite2 = _sprite; + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetTalkSprite + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetTalkSprite") == 0) { + stack->correctParams(2); + + const char *filename = stack->pop()->getString(); + bool ex = stack->pop()->getBool(); + bool setCurrent = false; + bool setTemp2 = false; + + BaseSprite *spr = new BaseSprite(_gameRef, this); + if (!spr || DID_FAIL(spr->loadFile(filename))) { + stack->pushBool(false); + script->runtimeError("SetTalkSprite method failed for file '%s'", filename); + } else { + + // delete current + if (ex) { + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + if (_talkSpritesEx[i] == _currentSprite) { + setCurrent = true; + } + if (_talkSpritesEx[i] == _tempSprite2) { + setTemp2 = true; + } + delete _talkSpritesEx[i]; + } + _talkSpritesEx.clear(); + } else { + for (uint32 i = 0; i < _talkSprites.size(); i++) { + if (_talkSprites[i] == _currentSprite) { + setCurrent = true; + } + if (_talkSprites[i] == _tempSprite2) { + setTemp2 = true; + } + delete _talkSprites[i]; + } + _talkSprites.clear(); + } + + // set new + if (ex) { + _talkSpritesEx.add(spr); + } else { + _talkSprites.add(spr); + } + stack->pushBool(true); + + if (setCurrent) { + _currentSprite = spr; + } + if (setTemp2) { + _tempSprite2 = spr; + } + } + return STATUS_OK; + } else { + return AdObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdTalkHolder::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type (RO) + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("talk-holder"); + return _scValue; + } else { + return AdObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkHolder::scSetProperty(const char *name, ScValue *value) { + /* + ////////////////////////////////////////////////////////////////////////// + // Item + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Item")==0){ + SetItem(value->getString()); + return STATUS_OK; + } + + else*/ return AdObject::scSetProperty(name, value); +} + + +////////////////////////////////////////////////////////////////////////// +const char *AdTalkHolder::scToString() { + return "[talk-holder object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkHolder::saveAsText(BaseDynamicBuffer *buffer, int indent) { + for (uint32 i = 0; i < _talkSprites.size(); i++) { + if (_talkSprites[i]->getFilename()) { + buffer->putTextIndent(indent + 2, "TALK=\"%s\"\n", _talkSprites[i]->getFilename()); + } + } + + for (uint32 i = 0; i < _talkSpritesEx.size(); i++) { + if (_talkSpritesEx[i]->getFilename()) { + buffer->putTextIndent(indent + 2, "TALK_SPECIAL=\"%s\"\n", _talkSpritesEx[i]->getFilename()); + } + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkHolder::persist(BasePersistenceManager *persistMgr) { + AdObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_sprite)); + _talkSprites.persist(persistMgr); + _talkSpritesEx.persist(persistMgr); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_holder.h b/engines/wintermute/ad/ad_talk_holder.h index 906c469b3248..ce10364b3d9e 100644 --- a/engines/wintermute/ad/ad_talk_holder.h +++ b/engines/wintermute/ad/ad_talk_holder.h @@ -1,57 +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_ADTALKHOLDER_H -#define WINTERMUTE_ADTALKHOLDER_H - -#include "engines/wintermute/ad/ad_object.h" - -namespace Wintermute { - -class AdTalkHolder : public AdObject { -public: - DECLARE_PERSISTENT(AdTalkHolder, AdObject) - virtual BaseSprite *getTalkStance(const char *stance); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - BaseSprite *_sprite; - BaseArray _talkSprites; - BaseArray _talkSpritesEx; - AdTalkHolder(BaseGame *inGame); - virtual ~AdTalkHolder(); - - // 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 +/* 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_ADTALKHOLDER_H +#define WINTERMUTE_ADTALKHOLDER_H + +#include "engines/wintermute/ad/ad_object.h" + +namespace Wintermute { + +class AdTalkHolder : public AdObject { +public: + DECLARE_PERSISTENT(AdTalkHolder, AdObject) + virtual BaseSprite *getTalkStance(const char *stance); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + BaseSprite *_sprite; + BaseArray _talkSprites; + BaseArray _talkSpritesEx; + AdTalkHolder(BaseGame *inGame); + virtual ~AdTalkHolder(); + + // 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/ad/ad_talk_node.cpp b/engines/wintermute/ad/ad_talk_node.cpp index 6d793f483cac..b43a2b288e6a 100644 --- a/engines/wintermute/ad/ad_talk_node.cpp +++ b/engines/wintermute/ad/ad_talk_node.cpp @@ -1,295 +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/ad/ad_talk_node.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/base_sprite.h" -#include "engines/wintermute/ad/ad_sprite_set.h" -#include "engines/wintermute/utils/utils.h" -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdTalkNode, false) - -////////////////////////////////////////////////////////////////////////// -AdTalkNode::AdTalkNode(BaseGame *inGame) : BaseClass(inGame) { - _sprite = NULL; - _spriteFilename = NULL; - _spriteSet = NULL; - _spriteSetFilename = NULL; - _comment = NULL; - - _startTime = _endTime = 0; - _playToEnd = false; - _preCache = false; -} - - -////////////////////////////////////////////////////////////////////////// -AdTalkNode::~AdTalkNode() { - delete[] _spriteFilename; - delete _sprite; - delete[] _spriteSetFilename; - delete _spriteSet; - delete _comment; - _spriteFilename = NULL; - _sprite = NULL; - _spriteSetFilename = NULL; - _spriteSet = NULL; - _comment = NULL; -} - - - -TOKEN_DEF_START -TOKEN_DEF(ACTION) -TOKEN_DEF(SPRITESET_FILE) -TOKEN_DEF(SPRITESET) -TOKEN_DEF(SPRITE) -TOKEN_DEF(START_TIME) -TOKEN_DEF(END_TIME) -TOKEN_DEF(COMMENT) -TOKEN_DEF(PRECACHE) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdTalkNode::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ACTION) - TOKEN_TABLE(SPRITESET_FILE) - TOKEN_TABLE(SPRITESET) - TOKEN_TABLE(SPRITE) - TOKEN_TABLE(START_TIME) - TOKEN_TABLE(END_TIME) - TOKEN_TABLE(COMMENT) - TOKEN_TABLE(PRECACHE) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTION) { - _gameRef->LOG(0, "'ACTION' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - _endTime = 0; - _playToEnd = false; - _preCache = false; - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_SPRITE: - BaseUtils::setString(&_spriteFilename, (char *)params); - break; - - case TOKEN_SPRITESET_FILE: - BaseUtils::setString(&_spriteSetFilename, (char *)params); - break; - - case TOKEN_SPRITESET: { - delete _spriteSet; - _spriteSet = new AdSpriteSet(_gameRef); - if (!_spriteSet || DID_FAIL(_spriteSet->loadBuffer(params, false))) { - delete _spriteSet; - _spriteSet = NULL; - cmd = PARSERR_GENERIC; - } - } - break; - - case TOKEN_START_TIME: - parser.scanStr((char *)params, "%d", &_startTime); - break; - - case TOKEN_END_TIME: - parser.scanStr((char *)params, "%d", &_endTime); - break; - - case TOKEN_PRECACHE: - parser.scanStr((char *)params, "%b", &_preCache); - break; - - case TOKEN_COMMENT: - if (_gameRef->_editorMode) { - BaseUtils::setString(&_comment, (char *)params); - } - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ACTION definition"); - return STATUS_FAILED; - } - - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading ACTION definition"); - return STATUS_FAILED; - } - - if (_endTime == 0) { - _playToEnd = true; - } else { - _playToEnd = false; - } - - if (_preCache && _spriteFilename) { - delete _sprite; - _sprite = new BaseSprite(_gameRef); - if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) { - return STATUS_FAILED; - } - } - - if (_preCache && _spriteSetFilename) { - delete _spriteSet; - _spriteSet = new AdSpriteSet(_gameRef); - if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { - return STATUS_FAILED; - } - } - - return STATUS_OK; -} - - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkNode::persist(BasePersistenceManager *persistMgr) { - persistMgr->transfer(TMEMBER(_comment)); - persistMgr->transfer(TMEMBER(_startTime)); - persistMgr->transfer(TMEMBER(_endTime)); - persistMgr->transfer(TMEMBER(_playToEnd)); - persistMgr->transfer(TMEMBER(_sprite)); - persistMgr->transfer(TMEMBER(_spriteFilename)); - persistMgr->transfer(TMEMBER(_spriteSet)); - persistMgr->transfer(TMEMBER(_spriteSetFilename)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkNode::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ACTION {\n"); - if (_comment) { - buffer->putTextIndent(indent + 2, "COMMENT=\"%s\"\n", _comment); - } - buffer->putTextIndent(indent + 2, "START_TIME=%d\n", _startTime); - if (!_playToEnd) { - buffer->putTextIndent(indent + 2, "END_TIME=%d\n", _endTime); - } - if (_spriteFilename) { - buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _spriteFilename); - } - if (_spriteSetFilename) { - buffer->putTextIndent(indent + 2, "SPRITESET_FILE=\"%s\"\n", _spriteSetFilename); - } else if (_spriteSet) { - _spriteSet->saveAsText(buffer, indent + 2); - } - if (_preCache) { - buffer->putTextIndent(indent + 2, "PRECACHE=\"%s\"\n", _preCache ? "TRUE" : "FALSE"); - } - - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkNode::loadSprite() { - if (_spriteFilename && !_sprite) { - _sprite = new BaseSprite(_gameRef); - if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) { - delete _sprite; - _sprite = NULL; - return STATUS_FAILED; - } else { - return STATUS_OK; - } - } else if (_spriteSetFilename && !_spriteSet) { - _spriteSet = new AdSpriteSet(_gameRef); - if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { - delete _spriteSet; - _spriteSet = NULL; - return STATUS_FAILED; - } else { - return STATUS_OK; - } - } else { - return STATUS_OK; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdTalkNode::isInTimeInterval(uint32 time, TDirection dir) { - if (time >= _startTime) { - if (_playToEnd) { - if ((_spriteFilename && _sprite == NULL) || (_sprite && _sprite->_finished == false)) { - return true; - } else if ((_spriteSetFilename && _spriteSet == NULL) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->_finished == false)) { - return true; - } else { - return false; - } - } else { - return _endTime >= time; - } - } else { - return false; - } -} - - -////////////////////////////////////////////////////////////////////////// -BaseSprite *AdTalkNode::getSprite(TDirection dir) { - loadSprite(); - if (_sprite) { - return _sprite; - } else if (_spriteSet) { - return _spriteSet->getSprite(dir); - } else { - return NULL; - } -} - -} // end of namespace Wintermute +/* 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_talk_node.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/base_sprite.h" +#include "engines/wintermute/ad/ad_sprite_set.h" +#include "engines/wintermute/utils/utils.h" +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdTalkNode, false) + +////////////////////////////////////////////////////////////////////////// +AdTalkNode::AdTalkNode(BaseGame *inGame) : BaseClass(inGame) { + _sprite = NULL; + _spriteFilename = NULL; + _spriteSet = NULL; + _spriteSetFilename = NULL; + _comment = NULL; + + _startTime = _endTime = 0; + _playToEnd = false; + _preCache = false; +} + + +////////////////////////////////////////////////////////////////////////// +AdTalkNode::~AdTalkNode() { + delete[] _spriteFilename; + delete _sprite; + delete[] _spriteSetFilename; + delete _spriteSet; + delete _comment; + _spriteFilename = NULL; + _sprite = NULL; + _spriteSetFilename = NULL; + _spriteSet = NULL; + _comment = NULL; +} + + + +TOKEN_DEF_START +TOKEN_DEF(ACTION) +TOKEN_DEF(SPRITESET_FILE) +TOKEN_DEF(SPRITESET) +TOKEN_DEF(SPRITE) +TOKEN_DEF(START_TIME) +TOKEN_DEF(END_TIME) +TOKEN_DEF(COMMENT) +TOKEN_DEF(PRECACHE) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdTalkNode::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ACTION) + TOKEN_TABLE(SPRITESET_FILE) + TOKEN_TABLE(SPRITESET) + TOKEN_TABLE(SPRITE) + TOKEN_TABLE(START_TIME) + TOKEN_TABLE(END_TIME) + TOKEN_TABLE(COMMENT) + TOKEN_TABLE(PRECACHE) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ACTION) { + _gameRef->LOG(0, "'ACTION' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + _endTime = 0; + _playToEnd = false; + _preCache = false; + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_SPRITE: + BaseUtils::setString(&_spriteFilename, (char *)params); + break; + + case TOKEN_SPRITESET_FILE: + BaseUtils::setString(&_spriteSetFilename, (char *)params); + break; + + case TOKEN_SPRITESET: { + delete _spriteSet; + _spriteSet = new AdSpriteSet(_gameRef); + if (!_spriteSet || DID_FAIL(_spriteSet->loadBuffer(params, false))) { + delete _spriteSet; + _spriteSet = NULL; + cmd = PARSERR_GENERIC; + } + } + break; + + case TOKEN_START_TIME: + parser.scanStr((char *)params, "%d", &_startTime); + break; + + case TOKEN_END_TIME: + parser.scanStr((char *)params, "%d", &_endTime); + break; + + case TOKEN_PRECACHE: + parser.scanStr((char *)params, "%b", &_preCache); + break; + + case TOKEN_COMMENT: + if (_gameRef->_editorMode) { + BaseUtils::setString(&_comment, (char *)params); + } + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ACTION definition"); + return STATUS_FAILED; + } + + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading ACTION definition"); + return STATUS_FAILED; + } + + if (_endTime == 0) { + _playToEnd = true; + } else { + _playToEnd = false; + } + + if (_preCache && _spriteFilename) { + delete _sprite; + _sprite = new BaseSprite(_gameRef); + if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) { + return STATUS_FAILED; + } + } + + if (_preCache && _spriteSetFilename) { + delete _spriteSet; + _spriteSet = new AdSpriteSet(_gameRef); + if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { + return STATUS_FAILED; + } + } + + return STATUS_OK; +} + + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkNode::persist(BasePersistenceManager *persistMgr) { + persistMgr->transfer(TMEMBER(_comment)); + persistMgr->transfer(TMEMBER(_startTime)); + persistMgr->transfer(TMEMBER(_endTime)); + persistMgr->transfer(TMEMBER(_playToEnd)); + persistMgr->transfer(TMEMBER(_sprite)); + persistMgr->transfer(TMEMBER(_spriteFilename)); + persistMgr->transfer(TMEMBER(_spriteSet)); + persistMgr->transfer(TMEMBER(_spriteSetFilename)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkNode::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ACTION {\n"); + if (_comment) { + buffer->putTextIndent(indent + 2, "COMMENT=\"%s\"\n", _comment); + } + buffer->putTextIndent(indent + 2, "START_TIME=%d\n", _startTime); + if (!_playToEnd) { + buffer->putTextIndent(indent + 2, "END_TIME=%d\n", _endTime); + } + if (_spriteFilename) { + buffer->putTextIndent(indent + 2, "SPRITE=\"%s\"\n", _spriteFilename); + } + if (_spriteSetFilename) { + buffer->putTextIndent(indent + 2, "SPRITESET_FILE=\"%s\"\n", _spriteSetFilename); + } else if (_spriteSet) { + _spriteSet->saveAsText(buffer, indent + 2); + } + if (_preCache) { + buffer->putTextIndent(indent + 2, "PRECACHE=\"%s\"\n", _preCache ? "TRUE" : "FALSE"); + } + + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkNode::loadSprite() { + if (_spriteFilename && !_sprite) { + _sprite = new BaseSprite(_gameRef); + if (!_sprite || DID_FAIL(_sprite->loadFile(_spriteFilename))) { + delete _sprite; + _sprite = NULL; + return STATUS_FAILED; + } else { + return STATUS_OK; + } + } else if (_spriteSetFilename && !_spriteSet) { + _spriteSet = new AdSpriteSet(_gameRef); + if (!_spriteSet || DID_FAIL(_spriteSet->loadFile(_spriteSetFilename))) { + delete _spriteSet; + _spriteSet = NULL; + return STATUS_FAILED; + } else { + return STATUS_OK; + } + } else { + return STATUS_OK; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdTalkNode::isInTimeInterval(uint32 time, TDirection dir) { + if (time >= _startTime) { + if (_playToEnd) { + if ((_spriteFilename && _sprite == NULL) || (_sprite && _sprite->_finished == false)) { + return true; + } else if ((_spriteSetFilename && _spriteSet == NULL) || (_spriteSet && _spriteSet->getSprite(dir) && _spriteSet->getSprite(dir)->_finished == false)) { + return true; + } else { + return false; + } + } else { + return _endTime >= time; + } + } else { + return false; + } +} + + +////////////////////////////////////////////////////////////////////////// +BaseSprite *AdTalkNode::getSprite(TDirection dir) { + loadSprite(); + if (_sprite) { + return _sprite; + } else if (_spriteSet) { + return _spriteSet->getSprite(dir); + } else { + return NULL; + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_talk_node.h b/engines/wintermute/ad/ad_talk_node.h index 863f6d0a3bdf..7dfd861f85e5 100644 --- a/engines/wintermute/ad/ad_talk_node.h +++ b/engines/wintermute/ad/ad_talk_node.h @@ -1,63 +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_ADTALKNODE_H -#define WINTERMUTE_ADTALKNODE_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/base/base.h" - -namespace Wintermute { -class AdSpriteSet; -class BaseSprite; -class AdTalkNode : public BaseClass { -public: - char *_spriteSetFilename; - AdSpriteSet *_spriteSet; - BaseSprite *getSprite(TDirection dir); - bool isInTimeInterval(uint32 time, TDirection dir); - bool loadSprite(); - DECLARE_PERSISTENT(AdTalkNode, BaseClass) - - AdTalkNode(BaseGame *inGame); - virtual ~AdTalkNode(); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); - char *_spriteFilename; - BaseSprite *_sprite; - uint32 _startTime; - uint32 _endTime; - bool _playToEnd; - bool _preCache; - char *_comment; - -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADTALKNODE_H +#define WINTERMUTE_ADTALKNODE_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/base/base.h" + +namespace Wintermute { +class AdSpriteSet; +class BaseSprite; +class AdTalkNode : public BaseClass { +public: + char *_spriteSetFilename; + AdSpriteSet *_spriteSet; + BaseSprite *getSprite(TDirection dir); + bool isInTimeInterval(uint32 time, TDirection dir); + bool loadSprite(); + DECLARE_PERSISTENT(AdTalkNode, BaseClass) + + AdTalkNode(BaseGame *inGame); + virtual ~AdTalkNode(); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent = 0); + char *_spriteFilename; + BaseSprite *_sprite; + uint32 _startTime; + uint32 _endTime; + bool _playToEnd; + bool _preCache; + char *_comment; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_types.h b/engines/wintermute/ad/ad_types.h index 8db20bfc02f3..ae5882f4ee03 100644 --- a/engines/wintermute/ad/ad_types.h +++ b/engines/wintermute/ad/ad_types.h @@ -1,107 +1,107 @@ -/* 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_ADTYPES_H -#define WINTERMUTE_ADTYPES_H - -namespace Wintermute { - -typedef enum { - GAME_NORMAL, - GAME_WAITING_RESPONSE -} TGameStateEx; - -typedef enum { - OBJECT_ENTITY, - OBJECT_REGION, - OBJECT_ACTOR, - OBJECT_NONE -} TObjectType; - -typedef enum { - ENTITY_NORMAL, - ENTITY_SOUND -} TEntityType; - -typedef enum { - STATE_NONE, - STATE_IDLE, - STATE_PLAYING_ANIM, - STATE_READY, - STATE_FOLLOWING_PATH, - STATE_SEARCHING_PATH, - STATE_WAITING_PATH, - STATE_TURNING_LEFT, - STATE_TURNING_RIGHT, - STATE_TURNING, - STATE_TALKING, - STATE_DIRECT_CONTROL, - STATE_PLAYING_ANIM_SET -} TObjectState; - -typedef enum { - DIRECT_WALK_NONE, - DIRECT_WALK_FW, - DIRECT_WALK_BK -} TDirectWalkMode; - -typedef enum { - DIRECT_TURN_NONE, - DIRECT_TURN_CW, - DIRECT_TURN_CCW -} TDirectTurnMode; - -typedef enum { - RESPONSE_TEXT, - RESPONSE_ICON -} TResponseStyle; - -typedef enum { - RESPONSE_ALWAYS, - RESPONSE_ONCE, - RESPONSE_ONCE_GAME -} TResponseType; - - -typedef enum { - TALK_SKIP_LEFT = 0, - TALK_SKIP_RIGHT = 1, - TALK_SKIP_BOTH = 2, - TALK_SKIP_NONE = 3 -} TTalkSkipButton; - -typedef enum { - GEOM_WAYPOINT, - GEOM_WALKPLANE, - GEOM_BLOCKED, - GEOM_GENERIC -} TGeomNodeType; - -} // end of namespace Wintermute - -#endif +/* 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_ADTYPES_H +#define WINTERMUTE_ADTYPES_H + +namespace Wintermute { + +typedef enum { + GAME_NORMAL, + GAME_WAITING_RESPONSE +} TGameStateEx; + +typedef enum { + OBJECT_ENTITY, + OBJECT_REGION, + OBJECT_ACTOR, + OBJECT_NONE +} TObjectType; + +typedef enum { + ENTITY_NORMAL, + ENTITY_SOUND +} TEntityType; + +typedef enum { + STATE_NONE, + STATE_IDLE, + STATE_PLAYING_ANIM, + STATE_READY, + STATE_FOLLOWING_PATH, + STATE_SEARCHING_PATH, + STATE_WAITING_PATH, + STATE_TURNING_LEFT, + STATE_TURNING_RIGHT, + STATE_TURNING, + STATE_TALKING, + STATE_DIRECT_CONTROL, + STATE_PLAYING_ANIM_SET +} TObjectState; + +typedef enum { + DIRECT_WALK_NONE, + DIRECT_WALK_FW, + DIRECT_WALK_BK +} TDirectWalkMode; + +typedef enum { + DIRECT_TURN_NONE, + DIRECT_TURN_CW, + DIRECT_TURN_CCW +} TDirectTurnMode; + +typedef enum { + RESPONSE_TEXT, + RESPONSE_ICON +} TResponseStyle; + +typedef enum { + RESPONSE_ALWAYS, + RESPONSE_ONCE, + RESPONSE_ONCE_GAME +} TResponseType; + + +typedef enum { + TALK_SKIP_LEFT = 0, + TALK_SKIP_RIGHT = 1, + TALK_SKIP_BOTH = 2, + TALK_SKIP_NONE = 3 +} TTalkSkipButton; + +typedef enum { + GEOM_WAYPOINT, + GEOM_WALKPLANE, + GEOM_BLOCKED, + GEOM_GENERIC +} TGeomNodeType; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ad/ad_waypoint_group.cpp b/engines/wintermute/ad/ad_waypoint_group.cpp index 8da62c911507..984ed75aebcf 100644 --- a/engines/wintermute/ad/ad_waypoint_group.cpp +++ b/engines/wintermute/ad/ad_waypoint_group.cpp @@ -1,270 +1,270 @@ -/* 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_waypoint_group.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_region.h" -#include "engines/wintermute/base/base_file_manager.h" -#include - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(AdWaypointGroup, false) - -////////////////////////////////////////////////////////////////////////// -AdWaypointGroup::AdWaypointGroup(BaseGame *inGame) : BaseObject(inGame) { - _active = true; - _editorSelectedPoint = -1; - _lastMimicScale = -1; - _lastMimicX = _lastMimicY = INT_MIN; -} - - -////////////////////////////////////////////////////////////////////////// -AdWaypointGroup::~AdWaypointGroup() { - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void AdWaypointGroup::cleanup() { - for (uint32 i = 0; i < _points.size(); i++) { - delete _points[i]; - } - _points.clear(); - _editorSelectedPoint = -1; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "AdWaypointGroup::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 WAYPOINTS file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(WAYPOINTS) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(NAME) -TOKEN_DEF(POINT) -TOKEN_DEF(EDITOR_SELECTED_POINT) -TOKEN_DEF(EDITOR_SELECTED) -TOKEN_DEF(PROPERTY) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(WAYPOINTS) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(NAME) - TOKEN_TABLE(POINT) - TOKEN_TABLE(EDITOR_SELECTED_POINT) - TOKEN_TABLE(EDITOR_SELECTED) - TOKEN_TABLE(PROPERTY) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_WAYPOINTS) { - _gameRef->LOG(0, "'WAYPOINTS' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_POINT: { - int x, y; - parser.scanStr((char *)params, "%d,%d", &x, &y); - _points.add(new BasePoint(x, y)); - } - break; - - case TOKEN_EDITOR_SELECTED: - parser.scanStr((char *)params, "%b", &_editorSelected); - break; - - case TOKEN_EDITOR_SELECTED_POINT: - parser.scanStr((char *)params, "%d", &_editorSelectedPoint); - break; - - case TOKEN_PROPERTY: - parseProperty(params, false); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in WAYPOINTS definition"); - return STATUS_FAILED; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "WAYPOINTS {\n"); - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "EDITOR_SELECTED_POINT=%d\n", _editorSelectedPoint); - - if (_scProp) { - _scProp->saveAsText(buffer, indent + 2); - } - BaseClass::saveAsText(buffer, indent + 2); - - for (uint32 i = 0; i < _points.size(); i++) { - buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); - } - - buffer->putTextIndent(indent, "}\n"); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::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; -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *AdWaypointGroup::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("waypoint-group"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Active") == 0) { - _scValue->setBool(_active); - return _scValue; - } else { - return BaseObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Active - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Active") == 0) { - _active = value->getBool(); - return STATUS_OK; - } - - else { - return BaseObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool AdWaypointGroup::mimic(AdWaypointGroup *wpt, float scale, int argX, int argY) { - if (scale == _lastMimicScale && argX == _lastMimicX && argY == _lastMimicY) { - return STATUS_OK; - } - - cleanup(); - - for (uint32 i = 0; i < wpt->_points.size(); i++) { - int x = (int)((float)wpt->_points[i]->x * scale / 100.0f); - int y = (int)((float)wpt->_points[i]->y * scale / 100.0f); - - _points.add(new BasePoint(x + argX, y + argY)); - } - - _lastMimicScale = scale; - _lastMimicX = argX; - _lastMimicY = argY; - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_waypoint_group.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_region.h" +#include "engines/wintermute/base/base_file_manager.h" +#include + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(AdWaypointGroup, false) + +////////////////////////////////////////////////////////////////////////// +AdWaypointGroup::AdWaypointGroup(BaseGame *inGame) : BaseObject(inGame) { + _active = true; + _editorSelectedPoint = -1; + _lastMimicScale = -1; + _lastMimicX = _lastMimicY = INT_MIN; +} + + +////////////////////////////////////////////////////////////////////////// +AdWaypointGroup::~AdWaypointGroup() { + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void AdWaypointGroup::cleanup() { + for (uint32 i = 0; i < _points.size(); i++) { + delete _points[i]; + } + _points.clear(); + _editorSelectedPoint = -1; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "AdWaypointGroup::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 WAYPOINTS file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(WAYPOINTS) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(NAME) +TOKEN_DEF(POINT) +TOKEN_DEF(EDITOR_SELECTED_POINT) +TOKEN_DEF(EDITOR_SELECTED) +TOKEN_DEF(PROPERTY) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(WAYPOINTS) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(NAME) + TOKEN_TABLE(POINT) + TOKEN_TABLE(EDITOR_SELECTED_POINT) + TOKEN_TABLE(EDITOR_SELECTED) + TOKEN_TABLE(PROPERTY) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_WAYPOINTS) { + _gameRef->LOG(0, "'WAYPOINTS' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_POINT: { + int x, y; + parser.scanStr((char *)params, "%d,%d", &x, &y); + _points.add(new BasePoint(x, y)); + } + break; + + case TOKEN_EDITOR_SELECTED: + parser.scanStr((char *)params, "%b", &_editorSelected); + break; + + case TOKEN_EDITOR_SELECTED_POINT: + parser.scanStr((char *)params, "%d", &_editorSelectedPoint); + break; + + case TOKEN_PROPERTY: + parseProperty(params, false); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in WAYPOINTS definition"); + return STATUS_FAILED; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "WAYPOINTS {\n"); + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "EDITOR_SELECTED=%s\n", _editorSelected ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "EDITOR_SELECTED_POINT=%d\n", _editorSelectedPoint); + + if (_scProp) { + _scProp->saveAsText(buffer, indent + 2); + } + BaseClass::saveAsText(buffer, indent + 2); + + for (uint32 i = 0; i < _points.size(); i++) { + buffer->putTextIndent(indent + 2, "POINT {%d,%d}\n", _points[i]->x, _points[i]->y); + } + + buffer->putTextIndent(indent, "}\n"); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::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; +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *AdWaypointGroup::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("waypoint-group"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Active") == 0) { + _scValue->setBool(_active); + return _scValue; + } else { + return BaseObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Active + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Active") == 0) { + _active = value->getBool(); + return STATUS_OK; + } + + else { + return BaseObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool AdWaypointGroup::mimic(AdWaypointGroup *wpt, float scale, int argX, int argY) { + if (scale == _lastMimicScale && argX == _lastMimicX && argY == _lastMimicY) { + return STATUS_OK; + } + + cleanup(); + + for (uint32 i = 0; i < wpt->_points.size(); i++) { + int x = (int)((float)wpt->_points[i]->x * scale / 100.0f); + int y = (int)((float)wpt->_points[i]->y * scale / 100.0f); + + _points.add(new BasePoint(x + argX, y + argY)); + } + + _lastMimicScale = scale; + _lastMimicX = argX; + _lastMimicY = argY; + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ad/ad_waypoint_group.h b/engines/wintermute/ad/ad_waypoint_group.h index a83c942652d7..5cf6da1d1a5a 100644 --- a/engines/wintermute/ad/ad_waypoint_group.h +++ b/engines/wintermute/ad/ad_waypoint_group.h @@ -1,58 +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_ADWAYPOINTGROUP_H -#define WINTERMUTE_ADWAYPOINTGROUP_H - -#include "engines/wintermute/base/base_object.h" - -namespace Wintermute { -class BasePoint; -class AdWaypointGroup : public BaseObject { -public: - float _lastMimicScale; - int _lastMimicX; - int _lastMimicY; - void cleanup(); - bool mimic(AdWaypointGroup *wpt, float scale = 100.0f, int x = 0, int y = 0); - DECLARE_PERSISTENT(AdWaypointGroup, BaseObject) - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - bool _active; - AdWaypointGroup(BaseGame *inGame); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual ~AdWaypointGroup(); - BaseArray _points; - int _editorSelectedPoint; - virtual ScValue *scGetProperty(const char *name); - virtual bool scSetProperty(const char *name, ScValue *value); -}; - -} // end of namespace Wintermute - -#endif +/* 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_ADWAYPOINTGROUP_H +#define WINTERMUTE_ADWAYPOINTGROUP_H + +#include "engines/wintermute/base/base_object.h" + +namespace Wintermute { +class BasePoint; +class AdWaypointGroup : public BaseObject { +public: + float _lastMimicScale; + int _lastMimicX; + int _lastMimicY; + void cleanup(); + bool mimic(AdWaypointGroup *wpt, float scale = 100.0f, int x = 0, int y = 0); + DECLARE_PERSISTENT(AdWaypointGroup, BaseObject) + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + bool _active; + AdWaypointGroup(BaseGame *inGame); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual ~AdWaypointGroup(); + BaseArray _points; + int _editorSelectedPoint; + virtual ScValue *scGetProperty(const char *name); + virtual bool scSetProperty(const char *name, ScValue *value); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/base.cpp b/engines/wintermute/base/base.cpp index 11f308a5226c..e351792e61d5 100644 --- a/engines/wintermute/base/base.cpp +++ b/engines/wintermute/base/base.cpp @@ -1,185 +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 **)¶ms) != 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 **)¶ms)) > 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 +/* 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 **)¶ms) != 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 **)¶ms)) > 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 index f4c1cf0739e8..24820c748afc 100644 --- a/engines/wintermute/base/base.h +++ b/engines/wintermute/base/base.h @@ -1,62 +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 _editorProps; - Common::HashMap::iterator _editorPropsIter; -}; - -} // end of namespace Wintermute - -#endif +/* 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 _editorProps; + Common::HashMap::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 index 46870a0d299f..d754cf011438 100644 --- a/engines/wintermute/base/base_active_rect.cpp +++ b/engines/wintermute/base/base_active_rect.cpp @@ -1,110 +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, ®ion->_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 +/* 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, ®ion->_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 index 3c2cccfeed2e..fcd2619b03b6 100644 --- a/engines/wintermute/base/base_active_rect.h +++ b/engines/wintermute/base/base_active_rect.h @@ -1,60 +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 +/* 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 index b49d4ce15028..fc48e93c2bd6 100644 --- a/engines/wintermute/base/base_dynamic_buffer.cpp +++ b/engines/wintermute/base/base_dynamic_buffer.cpp @@ -1,204 +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 +/* 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 index df35ad817df2..b6f3e12b9cd0 100644 --- a/engines/wintermute/base/base_dynamic_buffer.h +++ b/engines/wintermute/base/base_dynamic_buffer.h @@ -1,66 +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 +/* 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_fader.cpp b/engines/wintermute/base/base_fader.cpp index 580a7afeb450..08e6f689ba8f 100644 --- a/engines/wintermute/base/base_fader.cpp +++ b/engines/wintermute/base/base_fader.cpp @@ -1,194 +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 +/* 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 index 30072babfad9..d3ced4aaccac 100644 --- a/engines/wintermute/base/base_fader.h +++ b/engines/wintermute/base/base_fader.h @@ -1,63 +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 +/* 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 index f139d9914630..b726c0c66f5c 100644 --- a/engines/wintermute/base/base_file_manager.cpp +++ b/engines/wintermute/base/base_file_manager.cpp @@ -1,340 +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 +/* 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 index 3fb4434e9c52..70aff49bbb35 100644 --- a/engines/wintermute/base/base_file_manager.h +++ b/engines/wintermute/base/base_file_manager.h @@ -1,76 +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 _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 +/* 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 _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 index ed2c7acaca07..e1b29a3a5c85 100644 --- a/engines/wintermute/base/base_frame.cpp +++ b/engines/wintermute/base/base_frame.cpp @@ -1,760 +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, ¶ms)) > 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 +/* 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, ¶ms)) > 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 index c89fb49e6133..ea5467b6fe33 100644 --- a/engines/wintermute/base/base_frame.h +++ b/engines/wintermute/base/base_frame.h @@ -1,73 +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 _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 _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 +/* 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 _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 _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 index e8aaac6c40af..622e85cc1194 100644 --- a/engines/wintermute/base/base_game.cpp +++ b/engines/wintermute/base/base_game.cpp @@ -1,4483 +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 **)¶ms) != TOKEN_GAME) { - _gameRef->LOG(0, "'GAME' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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 **)¶ms) != 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 **)¶ms)) > 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 +/* 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 **)¶ms) != TOKEN_GAME) { + _gameRef->LOG(0, "'GAME' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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 **)¶ms) != 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 **)¶ms)) > 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 index aecbe3172230..93cbc4536bf9 100644 --- a/engines/wintermute/base/base_game.h +++ b/engines/wintermute/base/base_game.h @@ -1,362 +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 _quickMessages; - BaseArray _windows; - BaseArray _viewportStack; - BaseArray _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 +/* 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 _quickMessages; + BaseArray _windows; + BaseArray _viewportStack; + BaseArray _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 index d5c2027a0d09..fd5f2b0e1d5d 100644 --- a/engines/wintermute/base/base_keyboard_state.cpp +++ b/engines/wintermute/base/base_keyboard_state.cpp @@ -1,309 +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 +/* 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 index 4b1826d48355..ebc0c83ee10f 100644 --- a/engines/wintermute/base/base_keyboard_state.h +++ b/engines/wintermute/base/base_keyboard_state.h @@ -1,75 +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 +/* 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 index d95dd3e25be7..915bf24d7f8b 100644 --- a/engines/wintermute/base/base_named_object.cpp +++ b/engines/wintermute/base/base_named_object.cpp @@ -1,71 +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 +/* 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 index 9818708605a3..77a00cee459e 100644 --- a/engines/wintermute/base/base_named_object.h +++ b/engines/wintermute/base/base_named_object.h @@ -1,51 +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 +/* 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 index ff8fcd0bf27f..b6a688762436 100644 --- a/engines/wintermute/base/base_object.cpp +++ b/engines/wintermute/base/base_object.cpp @@ -1,1246 +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 +/* 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 index e1a21e91bac1..34adbdb58537 100644 --- a/engines/wintermute/base/base_object.h +++ b/engines/wintermute/base/base_object.h @@ -1,147 +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 +/* 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 index 007f93e443a7..9a0e9e3ad9b6 100644 --- a/engines/wintermute/base/base_parser.cpp +++ b/engines/wintermute/base/base_parser.cpp @@ -1,467 +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 +/* 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 index 6b4f733d74b5..76ca8ea85615 100644 --- a/engines/wintermute/base/base_parser.h +++ b/engines/wintermute/base/base_parser.h @@ -1,88 +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 +/* 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 index 94588eff3217..4cb67b87e10e 100644 --- a/engines/wintermute/base/base_persistence_manager.cpp +++ b/engines/wintermute/base/base_persistence_manager.cpp @@ -1,828 +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 +/* 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 index fb5a73d0d3da..a262c92a0b7d 100644 --- a/engines/wintermute/base/base_persistence_manager.h +++ b/engines/wintermute/base/base_persistence_manager.h @@ -1,118 +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 +/* 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 index 73e7e4690af0..fbd896089446 100644 --- a/engines/wintermute/base/base_point.cpp +++ b/engines/wintermute/base/base_point.cpp @@ -1,63 +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 +/* 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 index 43f8f960f101..c0bbd3102eea 100644 --- a/engines/wintermute/base/base_point.h +++ b/engines/wintermute/base/base_point.h @@ -1,50 +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 +/* 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 index dfe25b474b80..0a9907ac6b66 100644 --- a/engines/wintermute/base/base_quick_msg.cpp +++ b/engines/wintermute/base/base_quick_msg.cpp @@ -1,57 +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 +/* 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 index d00b302baf5e..4fed5ffc2e61 100644 --- a/engines/wintermute/base/base_quick_msg.h +++ b/engines/wintermute/base/base_quick_msg.h @@ -1,48 +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 +/* 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 index 4d7f3487f0a1..e332ffe9ff46 100644 --- a/engines/wintermute/base/base_region.cpp +++ b/engines/wintermute/base/base_region.cpp @@ -1,535 +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 - -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 **)¶ms) != 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 **)¶ms)) > 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 +/* 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 + +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 **)¶ms) != 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 **)¶ms)) > 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 index e7ae9bda1395..8dd02fe9282b 100644 --- a/engines/wintermute/base/base_region.h +++ b/engines/wintermute/base/base_region.h @@ -1,69 +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 _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 +/* 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 _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 index 8cd15ccf1d9a..186e1234a86f 100644 --- a/engines/wintermute/base/base_save_thumb_helper.cpp +++ b/engines/wintermute/base/base_save_thumb_helper.cpp @@ -1,80 +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 +/* 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 index 0af3103f717e..8863508ac968 100644 --- a/engines/wintermute/base/base_save_thumb_helper.h +++ b/engines/wintermute/base/base_save_thumb_helper.h @@ -1,51 +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 +/* 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 index e4132351e044..d3e6078d439f 100644 --- a/engines/wintermute/base/base_script_holder.cpp +++ b/engines/wintermute/base/base_script_holder.cpp @@ -1,502 +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(""); - - _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 **)¶ms) != 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 **)¶ms)) > 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(), "") != 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 +/* 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(""); + + _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 **)¶ms) != 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 **)¶ms)) > 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(), "") != 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 index cab0d4f693c7..0c3d7a1a7075 100644 --- a/engines/wintermute/base/base_script_holder.h +++ b/engines/wintermute/base/base_script_holder.h @@ -1,76 +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 _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 +/* 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 _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 index 6e5b30f7b6a6..143934402ba9 100644 --- a/engines/wintermute/base/base_scriptable.cpp +++ b/engines/wintermute/base/base_scriptable.cpp @@ -1,191 +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 +/* 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 index 11cb0bcf9f20..b006e6e07c63 100644 --- a/engines/wintermute/base/base_scriptable.h +++ b/engines/wintermute/base/base_scriptable.h @@ -1,83 +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 +/* 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 index ae0e844cb51d..e2dd8bbd3923 100644 --- a/engines/wintermute/base/base_sprite.cpp +++ b/engines/wintermute/base/base_sprite.cpp @@ -1,814 +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 **)¶ms) != 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 **)¶ms)) > 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 +/* 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 **)¶ms) != 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 **)¶ms)) > 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 index db9931c6f353..c861ca9930fb 100644 --- a/engines/wintermute/base/base_sprite.h +++ b/engines/wintermute/base/base_sprite.h @@ -1,90 +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 _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 +/* 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 _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 index 3b5e5e377461..2f890beea1d8 100644 --- a/engines/wintermute/base/base_string_table.cpp +++ b/engines/wintermute/base/base_string_table.cpp @@ -1,255 +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 +/* 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 index 09d8aecce431..128807bd1a02 100644 --- a/engines/wintermute/base/base_string_table.h +++ b/engines/wintermute/base/base_string_table.h @@ -1,55 +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 _strings; - typedef Common::HashMap::const_iterator StringsIter; - -}; - -} // end of namespace Wintermute - -#endif +/* 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 _strings; + typedef Common::HashMap::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 index 3ddfd1bb14e9..6a9246efd475 100644 --- a/engines/wintermute/base/base_sub_frame.cpp +++ b/engines/wintermute/base/base_sub_frame.cpp @@ -1,655 +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, ¶ms)) > 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 +/* 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, ¶ms)) > 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 index e89a189e2dbe..b174c6e5f009 100644 --- a/engines/wintermute/base/base_sub_frame.h +++ b/engines/wintermute/base/base_sub_frame.h @@ -1,92 +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 +/* 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 index c87da898dbbf..1dcebb059595 100644 --- a/engines/wintermute/base/base_surface_storage.cpp +++ b/engines/wintermute/base/base_surface_storage.cpp @@ -1,207 +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 +/* 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 index 28c36bebca01..aef8ad23f936 100644 --- a/engines/wintermute/base/base_surface_storage.h +++ b/engines/wintermute/base/base_surface_storage.h @@ -1,57 +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 _surfaces; -}; - -} // end of namespace Wintermute - -#endif +/* 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 _surfaces; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/base_transition_manager.cpp b/engines/wintermute/base/base_transition_manager.cpp index d71bce1084a6..5c28f36d3011 100644 --- a/engines/wintermute/base/base_transition_manager.cpp +++ b/engines/wintermute/base/base_transition_manager.cpp @@ -1,136 +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 +/* 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 index 1a989fbcfdde..d16a44c88ea8 100644 --- a/engines/wintermute/base/base_transition_manager.h +++ b/engines/wintermute/base/base_transition_manager.h @@ -1,54 +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 +/* 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 index af36a4fdd720..3b003e1c4903 100644 --- a/engines/wintermute/base/base_viewport.cpp +++ b/engines/wintermute/base/base_viewport.cpp @@ -1,98 +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 +/* 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 index c94beeb2b1e3..98ad1c1e142f 100644 --- a/engines/wintermute/base/base_viewport.h +++ b/engines/wintermute/base/base_viewport.h @@ -1,55 +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 +/* 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 index 8fff78a32a84..2d3951b02631 100644 --- a/engines/wintermute/base/file/base_disk_file.cpp +++ b/engines/wintermute/base/file/base_disk_file.cpp @@ -1,196 +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 +/* 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 index 69644408d0e1..c9f93b80d926 100644 --- a/engines/wintermute/base/file/base_disk_file.h +++ b/engines/wintermute/base/file/base_disk_file.h @@ -1,41 +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 +/* 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 index f2a347ee0fa4..f52a13211e24 100644 --- a/engines/wintermute/base/file/base_file.cpp +++ b/engines/wintermute/base/file/base_file.cpp @@ -1,68 +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 +/* 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 index 7ae36d5ad170..82f6ce355452 100644 --- a/engines/wintermute/base/file/base_file.h +++ b/engines/wintermute/base/file/base_file.h @@ -1,67 +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 +/* 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 index 82ddf7c90e1a..b9805d78dddb 100644 --- a/engines/wintermute/base/file/base_file_entry.cpp +++ b/engines/wintermute/base/file/base_file_entry.cpp @@ -1,73 +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 +/* 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 index 6dd4bc08a400..6e4823d99478 100644 --- a/engines/wintermute/base/file/base_file_entry.h +++ b/engines/wintermute/base/file/base_file_entry.h @@ -1,60 +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 +/* 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 index c5a62299e2a1..978099265260 100644 --- a/engines/wintermute/base/file/base_package.cpp +++ b/engines/wintermute/base/file/base_package.cpp @@ -1,276 +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::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::const_iterator it; - it = _files.find(upcName.c_str()); - return (it != _files.end()); -} - -int PackageSet::listMembers(Common::ArchiveMemberList &list) const { - Common::HashMap::const_iterator it = _files.begin(); - Common::HashMap::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::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::const_iterator it; - it = _files.find(upcName.c_str()); - if (it != _files.end()) { - return it->_value->createReadStream(); - } - return NULL; -} - -} // end of namespace Wintermute +/* 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::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::const_iterator it; + it = _files.find(upcName.c_str()); + return (it != _files.end()); +} + +int PackageSet::listMembers(Common::ArchiveMemberList &list) const { + Common::HashMap::const_iterator it = _files.begin(); + Common::HashMap::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::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::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 index 23d7d7690fa2..2882eb03b7af 100644 --- a/engines/wintermute/base/file/base_package.h +++ b/engines/wintermute/base/file/base_package.h @@ -1,90 +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 _packages; - Common::HashMap _files; - Common::HashMap::iterator _filesIter; -}; - -} // end of namespace Wintermute - -#endif +/* 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 _packages; + Common::HashMap _files; + Common::HashMap::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 index a8bda164dcc5..0b32cb0c4f95 100644 --- a/engines/wintermute/base/file/base_resources.cpp +++ b/engines/wintermute/base/file/base_resources.cpp @@ -1,2830 +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 +/* 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 index 48a0f534d0cf..91c30bcfa715 100644 --- a/engines/wintermute/base/file/base_resources.h +++ b/engines/wintermute/base/file/base_resources.h @@ -1,45 +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 +/* 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 index 515d8870d74f..5bdab0853ed9 100644 --- a/engines/wintermute/base/file/base_save_thumb_file.cpp +++ b/engines/wintermute/base/file/base_save_thumb_file.cpp @@ -1,154 +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 +/* 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 index 377e06f02c38..3b217525fdef 100644 --- a/engines/wintermute/base/file/base_save_thumb_file.h +++ b/engines/wintermute/base/file/base_save_thumb_file.h @@ -1,52 +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 +/* 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 index 82f1998527aa..2234139408b8 100644 --- a/engines/wintermute/base/file/dcpackage.h +++ b/engines/wintermute/base/file/dcpackage.h @@ -1,80 +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 +/* 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 index cb70c4add89b..87dd3da5a336 100644 --- a/engines/wintermute/base/font/base_font.cpp +++ b/engines/wintermute/base/font/base_font.cpp @@ -1,140 +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 **)¶ms) == TOKEN_TTFONT) { - ret = true; - } - - delete[] buffer; - return ret; -} - -} // end of namespace Wintermute +/* 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 **)¶ms) == 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 index acd424ac0659..0abe62ab98d8 100644 --- a/engines/wintermute/base/font/base_font.h +++ b/engines/wintermute/base/font/base_font.h @@ -1,61 +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 +/* 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 index 062f4801cf62..fced08c7e2cb 100644 --- a/engines/wintermute/base/font/base_font_bitmap.cpp +++ b/engines/wintermute/base/font/base_font_bitmap.cpp @@ -1,589 +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 **)¶ms) != 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 **)¶ms)) > 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 +/* 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 **)¶ms) != 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 **)¶ms)) > 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 index 14a6e1cc874b..2f3a69d0974c 100644 --- a/engines/wintermute/base/font/base_font_bitmap.h +++ b/engines/wintermute/base/font/base_font_bitmap.h @@ -1,71 +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 +/* 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 index 298417ec322e..d26fa1d5930e 100644 --- a/engines/wintermute/base/font/base_font_storage.cpp +++ b/engines/wintermute/base/font/base_font_storage.cpp @@ -1,142 +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 +/* 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 index 733e1c5da345..60874167e72f 100644 --- a/engines/wintermute/base/font/base_font_storage.h +++ b/engines/wintermute/base/font/base_font_storage.h @@ -1,55 +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 _fonts; - bool initLoop(); -}; - -} // end of namespace Wintermute - -#endif +/* 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 _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 index 171f33d8abbd..599010bbd580 100644 --- a/engines/wintermute/base/font/base_font_truetype.cpp +++ b/engines/wintermute/base/font/base_font_truetype.cpp @@ -1,605 +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 - -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 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::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 **)¶ms) != 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 **)¶ms)) > 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 **)¶ms)) > 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 lines; - _font->wordWrapText(text, maxWidth, lines); - Common::Array::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 +/* 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 + +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 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::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 **)¶ms) != 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 **)¶ms)) > 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 **)¶ms)) > 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 lines; + _font->wordWrapText(text, maxWidth, lines); + Common::Array::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 index a93e4efacbcb..02dca7439fca 100644 --- a/engines/wintermute/base/font/base_font_truetype.h +++ b/engines/wintermute/base/font/base_font_truetype.h @@ -1,152 +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 _layers; - void clearCache(); - -}; - -} // end of namespace Wintermute - -#endif +/* 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 _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 index bf11e15307c9..4b15d563ed90 100644 --- a/engines/wintermute/base/gfx/base_image.cpp +++ b/engines/wintermute/base/gfx/base_image.cpp @@ -1,231 +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 +/* 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 index 560a5f0d74cf..6d01b84184ab 100644 --- a/engines/wintermute/base/gfx/base_image.h +++ b/engines/wintermute/base/gfx/base_image.h @@ -1,72 +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 +/* 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 index 202c8646832a..9205438a5b09 100644 --- a/engines/wintermute/base/gfx/base_renderer.cpp +++ b/engines/wintermute/base/gfx/base_renderer.cpp @@ -1,381 +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 +/* 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 index 0ff4e6a3beb3..04758244640c 100644 --- a/engines/wintermute/base/gfx/base_renderer.h +++ b/engines/wintermute/base/gfx/base_renderer.h @@ -1,221 +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 _rectList; -}; - -BaseRenderer *makeOSystemRenderer(BaseGame *inGame); // Implemented in BRenderSDL.cpp - -} // end of namespace Wintermute - -#endif +/* 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 _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 index cbd665591aa3..d882adf5ad7d 100644 --- a/engines/wintermute/base/gfx/base_surface.cpp +++ b/engines/wintermute/base/gfx/base_surface.cpp @@ -1,149 +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 +/* 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 index f45856f65205..ee53c03e779a 100644 --- a/engines/wintermute/base/gfx/base_surface.h +++ b/engines/wintermute/base/gfx/base_surface.h @@ -1,99 +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 +/* 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 index 7a862e4441cc..6d6725303833 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.cpp @@ -1,604 +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::iterator pos; - for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { - if ((*pos)->_drawNum >= _drawNum) { - break; - } - } - _renderQueue.insert(pos, renderTicket); - Common::List::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 +/* 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::iterator pos; + for (pos = _renderQueue.begin(); pos != _renderQueue.end(); pos++) { + if ((*pos)->_drawNum >= _drawNum) { + break; + } + } + _renderQueue.insert(pos, renderTicket); + Common::List::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 index aebb4cf888d6..1e72508cd0b7 100644 --- a/engines/wintermute/base/gfx/osystem/base_render_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_render_osystem.h @@ -1,131 +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::iterator RenderQueueIterator; - Common::Rect *_dirtyRect; - Common::List _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 +/* 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::iterator RenderQueueIterator; + Common::Rect *_dirtyRect; + Common::List _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 index 7724a934815f..d5464782a395 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.cpp @@ -1,429 +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(_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(_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(_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(_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(_gameRef->_renderer); - renderer->invalidateTicketsFromSurface(this); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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(_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(_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(_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(_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(_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 index b68fac4e3b72..43422ef4e786 100644 --- a/engines/wintermute/base/gfx/osystem/base_surface_osystem.h +++ b/engines/wintermute/base/gfx/osystem/base_surface_osystem.h @@ -1,99 +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 +/* 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 index 7012bef86fbc..3655b8913105 100644 --- a/engines/wintermute/base/particles/part_emitter.cpp +++ b/engines/wintermute/base/particles/part_emitter.cpp @@ -1,1256 +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 +/* 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 index dd02cf7f177e..9a35cd9bbc35 100644 --- a/engines/wintermute/base/particles/part_emitter.h +++ b/engines/wintermute/base/particles/part_emitter.h @@ -1,140 +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 _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 _particles; - BaseArray _sprites; -}; - -} // end of namespace Wintermute - -#endif +/* 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 _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 _particles; + BaseArray _sprites; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/base/particles/part_force.cpp b/engines/wintermute/base/particles/part_force.cpp index abbaa2819df9..df841625040e 100644 --- a/engines/wintermute/base/particles/part_force.cpp +++ b/engines/wintermute/base/particles/part_force.cpp @@ -1,65 +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 +/* 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 index 6903a919e94a..27f4cb7d901d 100644 --- a/engines/wintermute/base/particles/part_force.h +++ b/engines/wintermute/base/particles/part_force.h @@ -1,57 +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 +/* 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 index 5f523612b877..0b850d961836 100644 --- a/engines/wintermute/base/particles/part_particle.cpp +++ b/engines/wintermute/base/particles/part_particle.cpp @@ -1,269 +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 +/* 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 index 3c8fc2c68b97..4b8c2f131eb8 100644 --- a/engines/wintermute/base/particles/part_particle.h +++ b/engines/wintermute/base/particles/part_particle.h @@ -1,90 +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 +/* 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/scriptables/dcscript.h b/engines/wintermute/base/scriptables/dcscript.h index 6810fdf665a5..4aae897dc263 100644 --- a/engines/wintermute/base/scriptables/dcscript.h +++ b/engines/wintermute/base/scriptables/dcscript.h @@ -1,141 +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 +/* 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 index 269ea1ea032d..9469bd46a70b 100644 --- a/engines/wintermute/base/scriptables/script.cpp +++ b/engines/wintermute/base/scriptables/script.cpp @@ -1,1467 +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 +/* 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 index 4daeacd02624..0616bce58a7a 100644 --- a/engines/wintermute/base/scriptables/script.h +++ b/engines/wintermute/base/scriptables/script.h @@ -1,174 +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 _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 +/* 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 _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 index 02f60809587d..20e2ccadd11c 100644 --- a/engines/wintermute/base/scriptables/script_engine.cpp +++ b/engines/wintermute/base/scriptables/script_engine.cpp @@ -1,610 +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 > TimeVector; - TimeVector times; - - ScriptTimes::iterator it; - for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) { - times.push_back(std::pair (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 +/* 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 > TimeVector; + TimeVector times; + + ScriptTimes::iterator it; + for (it = _scriptTimes.begin(); it != _scriptTimes.end(); ++it) { + times.push_back(std::pair (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 index f526353368d4..1a023326eb91 100644 --- a/engines/wintermute/base/scriptables/script_engine.h +++ b/engines/wintermute/base/scriptables/script_engine.h @@ -1,135 +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 _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 _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 ScriptTimes; - ScriptTimes _scriptTimes; - -}; - -} // end of namespace Wintermute - -#endif +/* 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 _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 _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 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 index c8d4f64ae99a..5ed07f0da63b 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.cpp +++ b/engines/wintermute/base/scriptables/script_ext_array.cpp @@ -1,252 +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 +/* 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 index 614f829950c2..d9805ef94f0f 100644 --- a/engines/wintermute/base/scriptables/script_ext_array.h +++ b/engines/wintermute/base/scriptables/script_ext_array.h @@ -1,56 +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 +/* 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 index 772601508197..11eead3b9cd5 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.cpp +++ b/engines/wintermute/base/scriptables/script_ext_date.cpp @@ -1,293 +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 +/* 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 index 7cdf57e689d2..f6f04dd7e646 100644 --- a/engines/wintermute/base/scriptables/script_ext_date.h +++ b/engines/wintermute/base/scriptables/script_ext_date.h @@ -1,54 +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 +/* 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 index 53d551119d42..ab574d464b34 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.cpp +++ b/engines/wintermute/base/scriptables/script_ext_file.cpp @@ -1,829 +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; iDeleteProp(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 +/* 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; iDeleteProp(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 index 389974a48e49..b91a53e69501 100644 --- a/engines/wintermute/base/scriptables/script_ext_file.h +++ b/engines/wintermute/base/scriptables/script_ext_file.h @@ -1,66 +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 +/* 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 index f7d0ba20b991..598b80cff372 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.cpp +++ b/engines/wintermute/base/scriptables/script_ext_math.cpp @@ -1,295 +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 - -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 +/* 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 + +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 index b195c0785d5b..f86d59fe7b37 100644 --- a/engines/wintermute/base/scriptables/script_ext_math.h +++ b/engines/wintermute/base/scriptables/script_ext_math.h @@ -1,53 +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 +/* 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 index eef1931d8b25..5ed9bd5313f0 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.cpp @@ -1,529 +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; iDeleteProp(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 +/* 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; iDeleteProp(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 index 0a16167b586c..d2662b303642 100644 --- a/engines/wintermute/base/scriptables/script_ext_mem_buffer.h +++ b/engines/wintermute/base/scriptables/script_ext_mem_buffer.h @@ -1,60 +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 +/* 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 index 40c9b885cdb3..b87aac81f95e 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.cpp +++ b/engines/wintermute/base/scriptables/script_ext_object.cpp @@ -1,67 +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 +/* 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 index 32aa00776e41..c85d16d44edc 100644 --- a/engines/wintermute/base/scriptables/script_ext_object.h +++ b/engines/wintermute/base/scriptables/script_ext_object.h @@ -1,46 +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 +/* 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 index 9bcfe28bbf7b..8d87a92dc19d 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.cpp +++ b/engines/wintermute/base/scriptables/script_ext_string.cpp @@ -1,436 +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 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::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 +/* 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 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::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 index c2de3860edbb..255b9c57ebca 100644 --- a/engines/wintermute/base/scriptables/script_ext_string.h +++ b/engines/wintermute/base/scriptables/script_ext_string.h @@ -1,58 +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 +/* 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 index d27748abe621..77367045c2f3 100644 --- a/engines/wintermute/base/scriptables/script_stack.cpp +++ b/engines/wintermute/base/scriptables/script_stack.cpp @@ -1,232 +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 +/* 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 index 0e2adae5183f..86d246cf3487 100644 --- a/engines/wintermute/base/scriptables/script_stack.h +++ b/engines/wintermute/base/scriptables/script_stack.h @@ -1,66 +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 _values; - int _sP; - -}; - -} // end of namespace Wintermute - -#endif +/* 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 _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 index 03ca69ac7ebb..0bc7ab58070c 100644 --- a/engines/wintermute/base/scriptables/script_value.cpp +++ b/engines/wintermute/base/scriptables/script_value.cpp @@ -1,995 +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 +/* 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 index af31014bac62..bf7d9cd8a1b2 100644 --- a/engines/wintermute/base/scriptables/script_value.h +++ b/engines/wintermute/base/scriptables/script_value.h @@ -1,113 +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 _valObject; - Common::HashMap::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 +/* 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 _valObject; + Common::HashMap::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 index aac68baccdc8..00d07cd3c2b9 100644 --- a/engines/wintermute/base/sound/base_sound.cpp +++ b/engines/wintermute/base/sound/base_sound.cpp @@ -1,292 +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 +/* 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 index d65757474ae5..637061b7cccf 100644 --- a/engines/wintermute/base/sound/base_sound.h +++ b/engines/wintermute/base/sound/base_sound.h @@ -1,87 +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 +/* 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 index e2d9c8c13fa1..3fd6c4d5f2be 100644 --- a/engines/wintermute/base/sound/base_sound_buffer.cpp +++ b/engines/wintermute/base/sound/base_sound_buffer.cpp @@ -1,297 +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 +/* 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 index 29402ee76eee..9c39f4c34b90 100644 --- a/engines/wintermute/base/sound/base_sound_buffer.h +++ b/engines/wintermute/base/sound/base_sound_buffer.h @@ -1,100 +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 +/* 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 index 2bfe0499f9ed..f7788cd2559a 100644 --- a/engines/wintermute/base/sound/base_sound_manager.cpp +++ b/engines/wintermute/base/sound/base_sound_manager.cpp @@ -1,282 +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 +/* 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 index d0b782b2b71b..36a729b5ae31 100644 --- a/engines/wintermute/base/sound/base_sound_manager.h +++ b/engines/wintermute/base/sound/base_sound_manager.h @@ -1,68 +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 _sounds; - void saveSettings(); -}; - -} // end of namespace Wintermute - -#endif +/* 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 _sounds; + void saveSettings(); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/coll_templ.h b/engines/wintermute/coll_templ.h index 389636cfe64e..493ea0701595 100644 --- a/engines/wintermute/coll_templ.h +++ b/engines/wintermute/coll_templ.h @@ -1,86 +1,86 @@ -/* 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_COLL_TEMPL_H -#define WINTERMUTE_COLL_TEMPL_H - -#include "common/array.h" -#include "engines/wintermute/base/base_persistence_manager.h" - -namespace Wintermute { - -// Basically Common::Array with peristence-support. -template -class BaseArray : public Common::Array { -public: -// TODO: Might want to make sure that destructors are called when replacing/deleting/getting destructed - bool persist(BasePersistenceManager *persistMgr) { - int j; - if (persistMgr->getIsSaving()) { - j = Common::Array::size(); - persistMgr->transfer("ArraySize", &j); - typename Common::Array::const_iterator it = Common::Array::begin(); - for (; it != Common::Array::end(); ++it) { - TYPE obj = *it; - persistMgr->transfer("", &obj); - } - } else { - Common::Array::clear(); - persistMgr->transfer("ArraySize", &j); - for (int i = 0; i < j; i++) { - TYPE obj; - persistMgr->transfer("", &obj); - add(obj); - } - } - return true; - } - int add(TYPE newElement) { - Common::Array::push_back(newElement); - return Common::Array::size() - 1; - } - void remove_at(uint32 idx) { - Common::Array::remove_at(idx); - } - void remove_at(uint32 idx, uint32 num) { - while (num) { - if (idx >= Common::Array::size()) { - break; - } - Common::Array::remove_at(idx); - } - } - template - void copy(const BaseArray &src) { - Common::Array::insert_at(0, src); - } -}; - -} // end of namespace Wintermute - -#endif +/* 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_COLL_TEMPL_H +#define WINTERMUTE_COLL_TEMPL_H + +#include "common/array.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace Wintermute { + +// Basically Common::Array with peristence-support. +template +class BaseArray : public Common::Array { +public: +// TODO: Might want to make sure that destructors are called when replacing/deleting/getting destructed + bool persist(BasePersistenceManager *persistMgr) { + int j; + if (persistMgr->getIsSaving()) { + j = Common::Array::size(); + persistMgr->transfer("ArraySize", &j); + typename Common::Array::const_iterator it = Common::Array::begin(); + for (; it != Common::Array::end(); ++it) { + TYPE obj = *it; + persistMgr->transfer("", &obj); + } + } else { + Common::Array::clear(); + persistMgr->transfer("ArraySize", &j); + for (int i = 0; i < j; i++) { + TYPE obj; + persistMgr->transfer("", &obj); + add(obj); + } + } + return true; + } + int add(TYPE newElement) { + Common::Array::push_back(newElement); + return Common::Array::size() - 1; + } + void remove_at(uint32 idx) { + Common::Array::remove_at(idx); + } + void remove_at(uint32 idx, uint32 num) { + while (num) { + if (idx >= Common::Array::size()) { + break; + } + Common::Array::remove_at(idx); + } + } + template + void copy(const BaseArray &src) { + Common::Array::insert_at(0, src); + } +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/dcgf.h b/engines/wintermute/dcgf.h index 867300e2d388..fc4174094be1 100644 --- a/engines/wintermute/dcgf.h +++ b/engines/wintermute/dcgf.h @@ -1,51 +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_DCGF_H -#define WINTERMUTE_DCGF_H - - -////////////////////////////////////////////////////////////////////////// -#define DCGF_VER_MAJOR 1 -#define DCGF_VER_MINOR 1 -#define DCGF_VER_BUILD 1 -#define DCGF_VER_SUFFIX "beta" -#define DCGF_VER_BETA true - -#define DCGF_NAME "WME Lite" -#define DCGF_MAGIC 0xDEC0ADDE - -// minimal saved game version we support -#define SAVEGAME_VER_MAJOR 1 -#define SAVEGAME_VER_MINOR 1 -#define SAVEGAME_VER_BUILD 1 -////////////////////////////////////////////////////////////////////////// - -#define COMPRESSED_FILE_MAGIC 0x504D435A // ZCMP - -#endif +/* 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_DCGF_H +#define WINTERMUTE_DCGF_H + + +////////////////////////////////////////////////////////////////////////// +#define DCGF_VER_MAJOR 1 +#define DCGF_VER_MINOR 1 +#define DCGF_VER_BUILD 1 +#define DCGF_VER_SUFFIX "beta" +#define DCGF_VER_BETA true + +#define DCGF_NAME "WME Lite" +#define DCGF_MAGIC 0xDEC0ADDE + +// minimal saved game version we support +#define SAVEGAME_VER_MAJOR 1 +#define SAVEGAME_VER_MINOR 1 +#define SAVEGAME_VER_BUILD 1 +////////////////////////////////////////////////////////////////////////// + +#define COMPRESSED_FILE_MAGIC 0x504D435A // ZCMP + +#endif diff --git a/engines/wintermute/dctypes.h b/engines/wintermute/dctypes.h index cab54fd144af..bd4966eb6b1d 100644 --- a/engines/wintermute/dctypes.h +++ b/engines/wintermute/dctypes.h @@ -1,225 +1,225 @@ -/* 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_DCTYPES_H -#define WINTERMUTE_DCTYPES_H - - -#include "common/str.h" -#include "common/list.h" -#include "common/array.h" - -namespace Wintermute { - -//typedef std::string AnsiString; -//typedef std::string Utf8String; -//typedef std::wstring WideString; -typedef Common::String AnsiString; -typedef Common::String Utf8String; -typedef Common::String WideString; // NB: Not actually true I presume. - -typedef Common::List WideStringList; -typedef Common::List AnsiStringList; - -typedef Common::Array WideStringArray; -typedef Common::Array AnsiStringArray; - - -enum TGameState { - GAME_RUNNING, - GAME_FROZEN, - GAME_SEMI_FROZEN -}; - - -enum TImageType { - IMG_PALETTED8, - IMG_TRUECOLOR -}; - - -enum TTextAlign { - TAL_LEFT = 0, - TAL_RIGHT, - TAL_CENTER, - NUM_TEXT_ALIGN -}; - - -enum TVerticalAlign { - VAL_TOP = 0, - VAL_CENTER, - VAL_BOTTOM, - NUM_VERTICAL_ALIGN -}; - - -enum TDirection { - DI_UP = 0, - DI_UPRIGHT = 1, - DI_RIGHT = 2, - DI_DOWNRIGHT = 3, - DI_DOWN = 4, - DI_DOWNLEFT = 5, - DI_LEFT = 6, - DI_UPLEFT = 7, - NUM_DIRECTIONS = 8, - DI_NONE = 9 -}; - -enum TEventType { - EVENT_NONE = 0, - EVENT_INIT = 1, - EVENT_SHUTDOWN = 2, - EVENT_LEFT_CLICK = 3, - EVENT_RIGHT_CLICK = 4, - EVENT_MIDDLE_CLICK = 5, - EVENT_LEFT_DBLCLICK = 6, - EVENT_PRESS = 7, - EVENT_IDLE = 8, - EVENT_MOUSE_OVER = 9, - EVENT_LEFT_RELEASE = 10, - EVENT_RIGHT_RELEASE = 11, - EVENT_MIDDLE_RELEASE = 12, - NUM_EVENTS -}; - -enum TUIObjectType { - UI_UNKNOWN, - UI_BUTTON, - UI_WINDOW, - UI_STATIC, - UI_EDIT, - UI_HTML, - UI_CUSTOM -}; - - -enum TRendererState { - RSTATE_3D, - RSTATE_2D, - RSTATE_LINES, - RSTATE_NONE -}; - - -enum TDynamicConstructor { - DYNAMIC_CONSTRUCTOR -}; - - -enum TVideoMode { - VIDEO_WINDOW, - VIDEO_FULLSCREEN, - VIDEO_ANY -}; - - -enum TVideoPlayback { - VID_PLAY_POS = 0, - VID_PLAY_STRETCH = 1, - VID_PLAY_CENTER = 2 -}; - - -enum TMouseEvent { - MOUSE_CLICK, - MOUSE_RELEASE, - MOUSE_DBLCLICK -}; - - -enum TMouseButton { - MOUSE_BUTTON_LEFT, - MOUSE_BUTTON_RIGHT, - MOUSE_BUTTON_MIDDLE -}; - - -enum TTransMgrState { - TRANS_MGR_RUNNING, - TRANS_MGR_READY -}; - - -enum TTransitionType { - TRANSITION_NONE = 0, - TRANSITION_FADE_OUT = 1, - TRANSITION_FADE_IN = 2, - NUM_TRANSITION_TYPES -}; - - -enum TWindowMode { - WINDOW_NORMAL, - WINDOW_EXCLUSIVE, - WINDOW_SYSTEM_EXCLUSIVE -}; - -enum TSFXType { - SFX_NONE, - SFX_ECHO, - SFX_REVERB -}; - - -enum TSpriteCacheType { - CACHE_ALL, - CACHE_HALF -}; - -enum TTextEncoding { - TEXT_ANSI = 0, - TEXT_UTF8 = 1, - NUM_TEXT_ENCODINGS -}; - -enum TSpriteBlendMode { - BLEND_UNKNOWN = -1, - BLEND_NORMAL = 0, - BLEND_ADDITIVE = 1, - BLEND_SUBTRACTIVE = 2, - NUM_BLEND_MODES -}; - -enum TTTSType { - TTS_CAPTION = 0, - TTS_TALK, - TTS_KEYPRESS -}; - -enum TShadowType { - SHADOW_NONE = 0, - SHADOW_SIMPLE = 1, - SHADOW_FLAT = 2, - SHADOW_STENCIL = 3 -}; - -} // end of namespace Wintermute - -#endif +/* 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_DCTYPES_H +#define WINTERMUTE_DCTYPES_H + + +#include "common/str.h" +#include "common/list.h" +#include "common/array.h" + +namespace Wintermute { + +//typedef std::string AnsiString; +//typedef std::string Utf8String; +//typedef std::wstring WideString; +typedef Common::String AnsiString; +typedef Common::String Utf8String; +typedef Common::String WideString; // NB: Not actually true I presume. + +typedef Common::List WideStringList; +typedef Common::List AnsiStringList; + +typedef Common::Array WideStringArray; +typedef Common::Array AnsiStringArray; + + +enum TGameState { + GAME_RUNNING, + GAME_FROZEN, + GAME_SEMI_FROZEN +}; + + +enum TImageType { + IMG_PALETTED8, + IMG_TRUECOLOR +}; + + +enum TTextAlign { + TAL_LEFT = 0, + TAL_RIGHT, + TAL_CENTER, + NUM_TEXT_ALIGN +}; + + +enum TVerticalAlign { + VAL_TOP = 0, + VAL_CENTER, + VAL_BOTTOM, + NUM_VERTICAL_ALIGN +}; + + +enum TDirection { + DI_UP = 0, + DI_UPRIGHT = 1, + DI_RIGHT = 2, + DI_DOWNRIGHT = 3, + DI_DOWN = 4, + DI_DOWNLEFT = 5, + DI_LEFT = 6, + DI_UPLEFT = 7, + NUM_DIRECTIONS = 8, + DI_NONE = 9 +}; + +enum TEventType { + EVENT_NONE = 0, + EVENT_INIT = 1, + EVENT_SHUTDOWN = 2, + EVENT_LEFT_CLICK = 3, + EVENT_RIGHT_CLICK = 4, + EVENT_MIDDLE_CLICK = 5, + EVENT_LEFT_DBLCLICK = 6, + EVENT_PRESS = 7, + EVENT_IDLE = 8, + EVENT_MOUSE_OVER = 9, + EVENT_LEFT_RELEASE = 10, + EVENT_RIGHT_RELEASE = 11, + EVENT_MIDDLE_RELEASE = 12, + NUM_EVENTS +}; + +enum TUIObjectType { + UI_UNKNOWN, + UI_BUTTON, + UI_WINDOW, + UI_STATIC, + UI_EDIT, + UI_HTML, + UI_CUSTOM +}; + + +enum TRendererState { + RSTATE_3D, + RSTATE_2D, + RSTATE_LINES, + RSTATE_NONE +}; + + +enum TDynamicConstructor { + DYNAMIC_CONSTRUCTOR +}; + + +enum TVideoMode { + VIDEO_WINDOW, + VIDEO_FULLSCREEN, + VIDEO_ANY +}; + + +enum TVideoPlayback { + VID_PLAY_POS = 0, + VID_PLAY_STRETCH = 1, + VID_PLAY_CENTER = 2 +}; + + +enum TMouseEvent { + MOUSE_CLICK, + MOUSE_RELEASE, + MOUSE_DBLCLICK +}; + + +enum TMouseButton { + MOUSE_BUTTON_LEFT, + MOUSE_BUTTON_RIGHT, + MOUSE_BUTTON_MIDDLE +}; + + +enum TTransMgrState { + TRANS_MGR_RUNNING, + TRANS_MGR_READY +}; + + +enum TTransitionType { + TRANSITION_NONE = 0, + TRANSITION_FADE_OUT = 1, + TRANSITION_FADE_IN = 2, + NUM_TRANSITION_TYPES +}; + + +enum TWindowMode { + WINDOW_NORMAL, + WINDOW_EXCLUSIVE, + WINDOW_SYSTEM_EXCLUSIVE +}; + +enum TSFXType { + SFX_NONE, + SFX_ECHO, + SFX_REVERB +}; + + +enum TSpriteCacheType { + CACHE_ALL, + CACHE_HALF +}; + +enum TTextEncoding { + TEXT_ANSI = 0, + TEXT_UTF8 = 1, + NUM_TEXT_ENCODINGS +}; + +enum TSpriteBlendMode { + BLEND_UNKNOWN = -1, + BLEND_NORMAL = 0, + BLEND_ADDITIVE = 1, + BLEND_SUBTRACTIVE = 2, + NUM_BLEND_MODES +}; + +enum TTTSType { + TTS_CAPTION = 0, + TTS_TALK, + TTS_KEYPRESS +}; + +enum TShadowType { + SHADOW_NONE = 0, + SHADOW_SIMPLE = 1, + SHADOW_FLAT = 2, + SHADOW_STENCIL = 3 +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/math/math_util.cpp b/engines/wintermute/math/math_util.cpp index 434e0e016b44..31af77538a62 100644 --- a/engines/wintermute/math/math_util.cpp +++ b/engines/wintermute/math/math_util.cpp @@ -1,52 +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 - */ - -#include "engines/wintermute/math/math_util.h" -#include - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -float MathUtil::round(float val) { - float result = floor(val); - if (val - result >= 0.5f) { - result += 1.0; - } - return result; -} - -////////////////////////////////////////////////////////////////////////// -float MathUtil::roundUp(float val) { - float result = floor(val); - if (val - result > 0) { - result += 1.0; - } - return result; -} - -} // end of namespace Wintermute +/* 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/math/math_util.h" +#include + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +float MathUtil::round(float val) { + float result = floor(val); + if (val - result >= 0.5f) { + result += 1.0; + } + return result; +} + +////////////////////////////////////////////////////////////////////////// +float MathUtil::roundUp(float val) { + float result = floor(val); + if (val - result > 0) { + result += 1.0; + } + return result; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/math/math_util.h b/engines/wintermute/math/math_util.h index 5f13c416d72e..38b6d9abf914 100644 --- a/engines/wintermute/math/math_util.h +++ b/engines/wintermute/math/math_util.h @@ -1,42 +1,42 @@ -/* 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_MATHUTIL_H -#define WINTERMUTE_MATHUTIL_H - -namespace Wintermute { - -class MathUtil { -public: - static float round(float val); - static float roundUp(float val); -}; - -} // end of namespace Wintermute - -#endif +/* 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_MATHUTIL_H +#define WINTERMUTE_MATHUTIL_H + +namespace Wintermute { + +class MathUtil { +public: + static float round(float val); + static float roundUp(float val); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/math/matrix4.cpp b/engines/wintermute/math/matrix4.cpp index e38833d09475..ca1eae881399 100644 --- a/engines/wintermute/math/matrix4.cpp +++ b/engines/wintermute/math/matrix4.cpp @@ -1,86 +1,86 @@ -/* 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/math/matrix4.h" -#include "engines/wintermute/math/vector2.h" -#include - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -Matrix4::Matrix4() { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - m[i][j] = 0.0f; - } - } -} - -////////////////////////////////////////////////////////////////////////// -Matrix4::~Matrix4() { -} - - -////////////////////////////////////////////////////////////////////////// -void Matrix4::identity() { - for (int i = 0; i < 4; i++) { - for (int j = 0; j < 4; j++) { - m[i][j] = 0.0f; - } - } - m[0][0] = 1.0f; - m[1][1] = 1.0f; - m[2][2] = 1.0f; - m[3][3] = 1.0f; - -} - -////////////////////////////////////////////////////////////////////////// -void Matrix4::rotationZ(float angle) { - identity(); - - m[0][0] = cos(angle); - m[1][1] = cos(angle); - m[0][1] = sin(angle); - m[1][0] = -sin(angle); -} - -////////////////////////////////////////////////////////////////////////// -void Matrix4::transformVector2(Vector2 &vec) { - float norm; - - norm = m[0][3] * vec.x + m[1][3] * vec.y + m[3][3]; - - float x = (m[0][0] * vec.x + m[1][0] * vec.y + m[3][0]) / norm; - float y = (m[0][1] * vec.x + m[1][1] * vec.y + m[3][1]) / norm; - - vec.x = x; - vec.y = y; -} - -} // end of namespace Wintermute +/* 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/math/matrix4.h" +#include "engines/wintermute/math/vector2.h" +#include + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +Matrix4::Matrix4() { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + m[i][j] = 0.0f; + } + } +} + +////////////////////////////////////////////////////////////////////////// +Matrix4::~Matrix4() { +} + + +////////////////////////////////////////////////////////////////////////// +void Matrix4::identity() { + for (int i = 0; i < 4; i++) { + for (int j = 0; j < 4; j++) { + m[i][j] = 0.0f; + } + } + m[0][0] = 1.0f; + m[1][1] = 1.0f; + m[2][2] = 1.0f; + m[3][3] = 1.0f; + +} + +////////////////////////////////////////////////////////////////////////// +void Matrix4::rotationZ(float angle) { + identity(); + + m[0][0] = cos(angle); + m[1][1] = cos(angle); + m[0][1] = sin(angle); + m[1][0] = -sin(angle); +} + +////////////////////////////////////////////////////////////////////////// +void Matrix4::transformVector2(Vector2 &vec) { + float norm; + + norm = m[0][3] * vec.x + m[1][3] * vec.y + m[3][3]; + + float x = (m[0][0] * vec.x + m[1][0] * vec.y + m[3][0]) / norm; + float y = (m[0][1] * vec.x + m[1][1] * vec.y + m[3][1]) / norm; + + vec.x = x; + vec.y = y; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/math/matrix4.h b/engines/wintermute/math/matrix4.h index c95bd364ffb6..273633f72330 100644 --- a/engines/wintermute/math/matrix4.h +++ b/engines/wintermute/math/matrix4.h @@ -1,50 +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_MATRIX4_H -#define WINTERMUTE_MATRIX4_H - -namespace Wintermute { - -class Vector2; - -class Matrix4 { -public: - Matrix4(); - ~Matrix4(); - - void identity(); - void rotationZ(float angle); - void transformVector2(Vector2 &vec); - - float m[4][4]; -}; - -} // end of namespace Wintermute - -#endif +/* 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_MATRIX4_H +#define WINTERMUTE_MATRIX4_H + +namespace Wintermute { + +class Vector2; + +class Matrix4 { +public: + Matrix4(); + ~Matrix4(); + + void identity(); + void rotationZ(float angle); + void transformVector2(Vector2 &vec); + + float m[4][4]; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/math/vector2.cpp b/engines/wintermute/math/vector2.cpp index 40c2b346d7b6..74c5586d62a0 100644 --- a/engines/wintermute/math/vector2.cpp +++ b/engines/wintermute/math/vector2.cpp @@ -1,55 +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 - */ - -#include "engines/wintermute/math/vector2.h" -#include - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -Vector2::Vector2() { - x = y = 0.0f; -} - -////////////////////////////////////////////////////////////////////////// -Vector2::Vector2(float xVal, float yVal) { - this->x = xVal; - this->y = yVal; -} - -////////////////////////////////////////////////////////////////////////// -Vector2::~Vector2() { -} - - -////////////////////////////////////////////////////////////////////////// -float Vector2::length() const { - return (float)sqrt(x * x + y * y); -} - -} // end of namespace Wintermute +/* 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/math/vector2.h" +#include + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +Vector2::Vector2() { + x = y = 0.0f; +} + +////////////////////////////////////////////////////////////////////////// +Vector2::Vector2(float xVal, float yVal) { + this->x = xVal; + this->y = yVal; +} + +////////////////////////////////////////////////////////////////////////// +Vector2::~Vector2() { +} + + +////////////////////////////////////////////////////////////////////////// +float Vector2::length() const { + return (float)sqrt(x * x + y * y); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/math/vector2.h b/engines/wintermute/math/vector2.h index dfed1824f034..31f31daaa0b4 100644 --- a/engines/wintermute/math/vector2.h +++ b/engines/wintermute/math/vector2.h @@ -1,75 +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_VECTOR2_H -#define WINTERMUTE_VECTOR2_H - -namespace Wintermute { - -class Vector2 { -public: - Vector2(); - Vector2(float x, float y); - ~Vector2(); - - float length() const; - - inline Vector2 &operator= (const Vector2 &other) { - x = other.x; - y = other.y; - - return *this; - } - - inline Vector2 operator+ (const Vector2 &other) const { - return Vector2(x + other.x, y + other.y); - } - - inline Vector2 operator- (const Vector2 &other) const { - return Vector2(x - other.x, y - other.y); - } - - inline Vector2 operator* (const float scalar) const { - return Vector2(x * scalar, y * scalar); - } - - inline Vector2 &operator+= (const Vector2 &other) { - x += other.x; - y += other.y; - - return *this; - } - - - float x; - float y; -}; - -} // end of namespace Wintermute - -#endif +/* 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_VECTOR2_H +#define WINTERMUTE_VECTOR2_H + +namespace Wintermute { + +class Vector2 { +public: + Vector2(); + Vector2(float x, float y); + ~Vector2(); + + float length() const; + + inline Vector2 &operator= (const Vector2 &other) { + x = other.x; + y = other.y; + + return *this; + } + + inline Vector2 operator+ (const Vector2 &other) const { + return Vector2(x + other.x, y + other.y); + } + + inline Vector2 operator- (const Vector2 &other) const { + return Vector2(x - other.x, y - other.y); + } + + inline Vector2 operator* (const float scalar) const { + return Vector2(x * scalar, y * scalar); + } + + inline Vector2 &operator+= (const Vector2 &other) { + x += other.x; + y += other.y; + + return *this; + } + + + float x; + float y; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/platform_osystem.cpp b/engines/wintermute/platform_osystem.cpp index c50645df95e2..0bd99b11cd8c 100644 --- a/engines/wintermute/platform_osystem.cpp +++ b/engines/wintermute/platform_osystem.cpp @@ -1,262 +1,262 @@ -/* 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/gfx/osystem/base_render_osystem.h" -#include "engines/wintermute/platform_osystem.h" -#include "common/str.h" -#include "common/textconsole.h" -#include "common/system.h" - -namespace Wintermute { - -BaseGame *BasePlatform::_gameRef = NULL; - -#define CLASS_NAME "GF_FRAME" -int BasePlatform::initialize(BaseGame *inGame, int argc, char *argv[]) { - _gameRef = inGame; - return true; -} - -////////////////////////////////////////////////////////////////////////// -void BasePlatform::handleEvent(Common::Event *event) { - switch (event->type) { - - case Common::EVENT_LBUTTONDOWN: - if (_gameRef) { - if (_gameRef->isLeftDoubleClick()) { - _gameRef->onMouseLeftDblClick(); - } else { - _gameRef->onMouseLeftDown(); - } - } - break; - case Common::EVENT_RBUTTONDOWN: - if (_gameRef) { - if (_gameRef->isRightDoubleClick()) { - _gameRef->onMouseRightDblClick(); - } else { - _gameRef->onMouseRightDown(); - } - } - break; - case Common::EVENT_MBUTTONDOWN: - if (_gameRef) { - _gameRef->onMouseMiddleDown(); - } - break; - case Common::EVENT_LBUTTONUP: - if (_gameRef) { - _gameRef->onMouseLeftUp(); - } - break; - case Common::EVENT_RBUTTONUP: - if (_gameRef) { - _gameRef->onMouseRightUp(); - } - break; - case Common::EVENT_MBUTTONUP: - if (_gameRef) { - _gameRef->onMouseMiddleUp(); - } - break; - case Common::EVENT_KEYDOWN: - if (_gameRef) { - _gameRef->handleKeypress(event); - } - break; - case Common::EVENT_KEYUP: - if (_gameRef) { - _gameRef->handleKeyRelease(event); - } - break; - case Common::EVENT_WHEELUP: - case Common::EVENT_WHEELDOWN: - if (_gameRef) { - _gameRef->handleMouseWheel(event->mouse.y); - } - break; -// Focus-events have been removed (_gameRef->onActivate originally) - case Common::EVENT_RTL: - _gameRef->_quitting = true; - break; - case Common::EVENT_QUIT: -// Block kept in case we want to support autoSaveOnExit. -// Originally this was the behaviour for WME Lite on iOS: -// if (_gameRef) { -// _gameRef->AutoSaveOnExit(); -// _gameRef->_quitting = true; -// } - if (_gameRef) { - _gameRef->onWindowClose(); - } - break; - default: - // TODO: Do we care about any other events? - break; - - } -} - - -////////////////////////////////////////////////////////////////////////// -// Win32 API bindings -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::getCursorPos(Point32 *lpPoint) { - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - - Common::Point p = g_system->getEventManager()->getMousePos(); - lpPoint->x = p.x; - lpPoint->y = p.y; - - renderer->pointFromScreen(lpPoint); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::setCursorPos(int x, int y) { - BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); - - Point32 p; - p.x = x; - p.y = y; - renderer->pointToScreen(&p); - - g_system->warpMouse(x, y); - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::showWindow(int nCmdShow) { - return false; -} - -////////////////////////////////////////////////////////////////////////// -void BasePlatform::setCapture() { - return; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::releaseCapture() { - return false; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::setRectEmpty(Rect32 *lprc) { - lprc->left = lprc->right = lprc->top = lprc->bottom = 0; - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::isRectEmpty(const Rect32 *lprc) { - return (lprc->left >= lprc->right) || (lprc->top >= lprc->bottom); -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::ptInRect(Rect32 *lprc, Point32 p) { - return (p.x >= lprc->left) && (p.x < lprc->right) && (p.y >= lprc->top) && (p.y < lprc->bottom); -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::setRect(Rect32 *lprc, int left, int top, int right, int bottom) { - lprc->left = left; - lprc->top = top; - lprc->right = right; - lprc->bottom = bottom; - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2) { - if (isRectEmpty(lprcSrc1) || isRectEmpty(lprcSrc2) || - lprcSrc1->left >= lprcSrc2->right || lprcSrc2->left >= lprcSrc1->right || - lprcSrc1->top >= lprcSrc2->bottom || lprcSrc2->top >= lprcSrc1->bottom) { - setRectEmpty(lprcDst); - return false; - } - lprcDst->left = MAX(lprcSrc1->left, lprcSrc2->left); - lprcDst->right = MIN(lprcSrc1->right, lprcSrc2->right); - lprcDst->top = MAX(lprcSrc1->top, lprcSrc2->top); - lprcDst->bottom = MIN(lprcSrc1->bottom, lprcSrc2->bottom); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2) { - if (isRectEmpty(lprcSrc1)) { - if (isRectEmpty(lprcSrc2)) { - setRectEmpty(lprcDst); - return false; - } else { - *lprcDst = *lprcSrc2; - } - } else { - if (isRectEmpty(lprcSrc2)) { - *lprcDst = *lprcSrc1; - } else { - lprcDst->left = MIN(lprcSrc1->left, lprcSrc2->left); - lprcDst->top = MIN(lprcSrc1->top, lprcSrc2->top); - lprcDst->right = MAX(lprcSrc1->right, lprcSrc2->right); - lprcDst->bottom = MAX(lprcSrc1->bottom, lprcSrc2->bottom); - } - } - - return true; -} - -////////////////////////////////////////////////////////////////////////// -bool BasePlatform::copyRect(Rect32 *lprcDst, Rect32 *lprcSrc) { - if (lprcDst == NULL || lprcSrc == NULL) { - return false; - } - - *lprcDst = *lprcSrc; - return true; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString BasePlatform::getPlatformName() { - // TODO: Should conform to the WME-spec. - //return AnsiString(SDL_GetPlatform()); - return AnsiString("ScummVM"); -} - -////////////////////////////////////////////////////////////////////////// -char *BasePlatform::strlwr(char *string) { - if (string) { - for (size_t i = 0; i < strlen(string); ++i) { - string[i] = tolower(string[i]); - } - } - return string; -} - -} // end of namespace Wintermute +/* 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/gfx/osystem/base_render_osystem.h" +#include "engines/wintermute/platform_osystem.h" +#include "common/str.h" +#include "common/textconsole.h" +#include "common/system.h" + +namespace Wintermute { + +BaseGame *BasePlatform::_gameRef = NULL; + +#define CLASS_NAME "GF_FRAME" +int BasePlatform::initialize(BaseGame *inGame, int argc, char *argv[]) { + _gameRef = inGame; + return true; +} + +////////////////////////////////////////////////////////////////////////// +void BasePlatform::handleEvent(Common::Event *event) { + switch (event->type) { + + case Common::EVENT_LBUTTONDOWN: + if (_gameRef) { + if (_gameRef->isLeftDoubleClick()) { + _gameRef->onMouseLeftDblClick(); + } else { + _gameRef->onMouseLeftDown(); + } + } + break; + case Common::EVENT_RBUTTONDOWN: + if (_gameRef) { + if (_gameRef->isRightDoubleClick()) { + _gameRef->onMouseRightDblClick(); + } else { + _gameRef->onMouseRightDown(); + } + } + break; + case Common::EVENT_MBUTTONDOWN: + if (_gameRef) { + _gameRef->onMouseMiddleDown(); + } + break; + case Common::EVENT_LBUTTONUP: + if (_gameRef) { + _gameRef->onMouseLeftUp(); + } + break; + case Common::EVENT_RBUTTONUP: + if (_gameRef) { + _gameRef->onMouseRightUp(); + } + break; + case Common::EVENT_MBUTTONUP: + if (_gameRef) { + _gameRef->onMouseMiddleUp(); + } + break; + case Common::EVENT_KEYDOWN: + if (_gameRef) { + _gameRef->handleKeypress(event); + } + break; + case Common::EVENT_KEYUP: + if (_gameRef) { + _gameRef->handleKeyRelease(event); + } + break; + case Common::EVENT_WHEELUP: + case Common::EVENT_WHEELDOWN: + if (_gameRef) { + _gameRef->handleMouseWheel(event->mouse.y); + } + break; +// Focus-events have been removed (_gameRef->onActivate originally) + case Common::EVENT_RTL: + _gameRef->_quitting = true; + break; + case Common::EVENT_QUIT: +// Block kept in case we want to support autoSaveOnExit. +// Originally this was the behaviour for WME Lite on iOS: +// if (_gameRef) { +// _gameRef->AutoSaveOnExit(); +// _gameRef->_quitting = true; +// } + if (_gameRef) { + _gameRef->onWindowClose(); + } + break; + default: + // TODO: Do we care about any other events? + break; + + } +} + + +////////////////////////////////////////////////////////////////////////// +// Win32 API bindings +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::getCursorPos(Point32 *lpPoint) { + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + + Common::Point p = g_system->getEventManager()->getMousePos(); + lpPoint->x = p.x; + lpPoint->y = p.y; + + renderer->pointFromScreen(lpPoint); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::setCursorPos(int x, int y) { + BaseRenderOSystem *renderer = static_cast(_gameRef->_renderer); + + Point32 p; + p.x = x; + p.y = y; + renderer->pointToScreen(&p); + + g_system->warpMouse(x, y); + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::showWindow(int nCmdShow) { + return false; +} + +////////////////////////////////////////////////////////////////////////// +void BasePlatform::setCapture() { + return; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::releaseCapture() { + return false; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::setRectEmpty(Rect32 *lprc) { + lprc->left = lprc->right = lprc->top = lprc->bottom = 0; + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::isRectEmpty(const Rect32 *lprc) { + return (lprc->left >= lprc->right) || (lprc->top >= lprc->bottom); +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::ptInRect(Rect32 *lprc, Point32 p) { + return (p.x >= lprc->left) && (p.x < lprc->right) && (p.y >= lprc->top) && (p.y < lprc->bottom); +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::setRect(Rect32 *lprc, int left, int top, int right, int bottom) { + lprc->left = left; + lprc->top = top; + lprc->right = right; + lprc->bottom = bottom; + + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2) { + if (isRectEmpty(lprcSrc1) || isRectEmpty(lprcSrc2) || + lprcSrc1->left >= lprcSrc2->right || lprcSrc2->left >= lprcSrc1->right || + lprcSrc1->top >= lprcSrc2->bottom || lprcSrc2->top >= lprcSrc1->bottom) { + setRectEmpty(lprcDst); + return false; + } + lprcDst->left = MAX(lprcSrc1->left, lprcSrc2->left); + lprcDst->right = MIN(lprcSrc1->right, lprcSrc2->right); + lprcDst->top = MAX(lprcSrc1->top, lprcSrc2->top); + lprcDst->bottom = MIN(lprcSrc1->bottom, lprcSrc2->bottom); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2) { + if (isRectEmpty(lprcSrc1)) { + if (isRectEmpty(lprcSrc2)) { + setRectEmpty(lprcDst); + return false; + } else { + *lprcDst = *lprcSrc2; + } + } else { + if (isRectEmpty(lprcSrc2)) { + *lprcDst = *lprcSrc1; + } else { + lprcDst->left = MIN(lprcSrc1->left, lprcSrc2->left); + lprcDst->top = MIN(lprcSrc1->top, lprcSrc2->top); + lprcDst->right = MAX(lprcSrc1->right, lprcSrc2->right); + lprcDst->bottom = MAX(lprcSrc1->bottom, lprcSrc2->bottom); + } + } + + return true; +} + +////////////////////////////////////////////////////////////////////////// +bool BasePlatform::copyRect(Rect32 *lprcDst, Rect32 *lprcSrc) { + if (lprcDst == NULL || lprcSrc == NULL) { + return false; + } + + *lprcDst = *lprcSrc; + return true; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString BasePlatform::getPlatformName() { + // TODO: Should conform to the WME-spec. + //return AnsiString(SDL_GetPlatform()); + return AnsiString("ScummVM"); +} + +////////////////////////////////////////////////////////////////////////// +char *BasePlatform::strlwr(char *string) { + if (string) { + for (size_t i = 0; i < strlen(string); ++i) { + string[i] = tolower(string[i]); + } + } + return string; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/platform_osystem.h b/engines/wintermute/platform_osystem.h index 9f281c89cd8c..21a77e0a0e5e 100644 --- a/engines/wintermute/platform_osystem.h +++ b/engines/wintermute/platform_osystem.h @@ -1,73 +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_PLATFORMSDL_H -#define WINTERMUTE_PLATFORMSDL_H - -#include "engines/wintermute/dctypes.h" -#include "engines/wintermute/math/rect32.h" -#include "common/events.h" - -namespace Wintermute { - -class BaseGame; - -////////////////////////////////////////////////////////////////////////// -class BasePlatform { -public: - static int initialize(BaseGame *inGame, int argc, char *argv[]); - static void handleEvent(Common::Event *event); - static AnsiString getPlatformName(); - - // Win32 API bindings - static bool getCursorPos(Point32 *lpPoint); - static bool setCursorPos(int x, int y); - static bool showWindow(int nCmdShow); - - static void setCapture(); - static bool releaseCapture(); - - static bool setRectEmpty(Rect32 *lprc); - static bool isRectEmpty(const Rect32 *lprc); - static bool ptInRect(Rect32 *lprc, Point32 p); - static bool setRect(Rect32 *lprc, int left, int top, int right, int bottom); - static bool intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2); - static bool unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2); - static bool copyRect(Rect32 *lprcDst, Rect32 *lprcSrc); - - // string functions - static char *strlwr(char *string); - -private: - // Set by initialize on game-startup, the object referred to is also deleted by deinit in WintermuteEngine - static BaseGame *_gameRef; -}; - -} // end of namespace Wintermute - -#endif +/* 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_PLATFORMSDL_H +#define WINTERMUTE_PLATFORMSDL_H + +#include "engines/wintermute/dctypes.h" +#include "engines/wintermute/math/rect32.h" +#include "common/events.h" + +namespace Wintermute { + +class BaseGame; + +////////////////////////////////////////////////////////////////////////// +class BasePlatform { +public: + static int initialize(BaseGame *inGame, int argc, char *argv[]); + static void handleEvent(Common::Event *event); + static AnsiString getPlatformName(); + + // Win32 API bindings + static bool getCursorPos(Point32 *lpPoint); + static bool setCursorPos(int x, int y); + static bool showWindow(int nCmdShow); + + static void setCapture(); + static bool releaseCapture(); + + static bool setRectEmpty(Rect32 *lprc); + static bool isRectEmpty(const Rect32 *lprc); + static bool ptInRect(Rect32 *lprc, Point32 p); + static bool setRect(Rect32 *lprc, int left, int top, int right, int bottom); + static bool intersectRect(Rect32 *lprcDst, const Rect32 *lprcSrc1, const Rect32 *lprcSrc2); + static bool unionRect(Rect32 *lprcDst, Rect32 *lprcSrc1, Rect32 *lprcSrc2); + static bool copyRect(Rect32 *lprcDst, Rect32 *lprcSrc); + + // string functions + static char *strlwr(char *string); + +private: + // Set by initialize on game-startup, the object referred to is also deleted by deinit in WintermuteEngine + static BaseGame *_gameRef; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/system/sys_class.cpp b/engines/wintermute/system/sys_class.cpp index bce9a04aeced..06b36b84ded1 100644 --- a/engines/wintermute/system/sys_class.cpp +++ b/engines/wintermute/system/sys_class.cpp @@ -1,220 +1,220 @@ -/* 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/system/sys_instance.h" -#include "engines/wintermute/system/sys_class.h" -#include "engines/wintermute/system/sys_class_registry.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_persistence_manager.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -SystemClass::SystemClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistentClass) { - _name = name; - - _build = build; - _load = load; - _next = NULL; - _savedID = -1; - _persistent = persistentClass; - _numInst = 0; - - SystemClassRegistry::getInstance()->registerClass(this); -} - - -////////////////////////////////////////////////////////////////////////// -SystemClass::~SystemClass() { - SystemClassRegistry::getInstance()->unregisterClass(this); - removeAllInstances(); -} - -////////////////////////////////////////////////////////////////////////// -bool SystemClass::removeAllInstances() { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - delete(it->_value); - } - _instances.clear(); - _instanceMap.clear(); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -SystemInstance *SystemClass::addInstance(void *instance, int id, int savedId) { - SystemInstance *inst = new SystemInstance(instance, id, this); - inst->setSavedID(savedId); - _instances[inst] = (inst); - - _instanceMap[instance] = inst; - - SystemClassRegistry::getInstance()->addInstanceToTable(inst, instance); - - return inst; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClass::removeInstance(void *instance) { - InstanceMap::iterator mapIt = _instanceMap.find(instance); - if (mapIt == _instanceMap.end()) { - return false; - } - - Instances::iterator it = _instances.find((mapIt->_value)); - if (it != _instances.end()) { - delete(it->_value); - _instances.erase(it); - } - - _instanceMap.erase(mapIt); - - return false; -} - -////////////////////////////////////////////////////////////////////////// -int SystemClass::getInstanceID(void *pointer) { - InstanceMap::iterator mapIt = _instanceMap.find(pointer); - if (mapIt == _instanceMap.end()) { - return -1; - } else { - return (mapIt->_value)->getID(); - } -} - -////////////////////////////////////////////////////////////////////////// -void *SystemClass::idToPointer(int savedID) { - //slow - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - if ((it->_value)->getSavedID() == savedID) { - return (it->_value)->getInstance(); - } - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -int SystemClass::getNumInstances() { - return _instances.size(); -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::dump(Common::WriteStream *stream) { - Common::String str; - str = Common::String::format("%03d %c %-20s instances: %d\n", _iD, _persistent ? 'p' : ' ', _name.c_str(), getNumInstances()); - stream->write(str.c_str(), str.size()); -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::saveTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { - persistMgr->putString(_name.c_str()); - persistMgr->putDWORD(_iD); - persistMgr->putDWORD(_instances.size()); - - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - persistMgr->putDWORD((it->_value)->getID()); - } -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::loadTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { - _savedID = persistMgr->getDWORD(); - int numInstances = persistMgr->getDWORD(); - - for (int i = 0; i < numInstances; i++) { - int instID = persistMgr->getDWORD(); - if (_persistent) { - - if (i > 0) { - gameRef->LOG(0, "Warning: attempting to load multiple instances of persistent class %s (%d)", _name.c_str(), numInstances); - continue; - } - - Instances::iterator it = _instances.begin(); - if (it != _instances.end()) { - (it->_value)->setSavedID(instID); - SystemClassRegistry::getInstance()->addInstanceToTable((it->_value), (it->_value)->getInstance()); - } else { - gameRef->LOG(0, "Warning: instance %d of persistent class %s not found", i, _name.c_str()); - } - } - // normal instances, create empty objects - else { - void *emptyObject = _build(); - if (!emptyObject) { - warning("HALT"); - } - - addInstance(emptyObject, SystemClassRegistry::getInstance()->getNextID(), instID); - } - - } -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::saveInstances(BaseGame *Game, BasePersistenceManager *persistMgr) { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - // write instace header - persistMgr->putString(""); - persistMgr->putDWORD(_iD); - persistMgr->putDWORD((it->_value)->getID()); - persistMgr->putString(""); - _load((it->_value)->getInstance(), persistMgr); - persistMgr->putString(""); - } -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::loadInstance(void *instance, BasePersistenceManager *persistMgr) { - _load(instance, persistMgr); -} - - -////////////////////////////////////////////////////////////////////////// -void SystemClass::resetSavedIDs() { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - (it->_value)->setSavedID(-1); - } -} - -////////////////////////////////////////////////////////////////////////// -void SystemClass::instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData) { - Instances::iterator it; - for (it = _instances.begin(); it != _instances.end(); ++it) { - lpCallback((it->_value)->getInstance(), lpData); - } -} - -} // end of namespace Wintermute +/* 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/system/sys_instance.h" +#include "engines/wintermute/system/sys_class.h" +#include "engines/wintermute/system/sys_class_registry.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_persistence_manager.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +SystemClass::SystemClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistentClass) { + _name = name; + + _build = build; + _load = load; + _next = NULL; + _savedID = -1; + _persistent = persistentClass; + _numInst = 0; + + SystemClassRegistry::getInstance()->registerClass(this); +} + + +////////////////////////////////////////////////////////////////////////// +SystemClass::~SystemClass() { + SystemClassRegistry::getInstance()->unregisterClass(this); + removeAllInstances(); +} + +////////////////////////////////////////////////////////////////////////// +bool SystemClass::removeAllInstances() { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + delete(it->_value); + } + _instances.clear(); + _instanceMap.clear(); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +SystemInstance *SystemClass::addInstance(void *instance, int id, int savedId) { + SystemInstance *inst = new SystemInstance(instance, id, this); + inst->setSavedID(savedId); + _instances[inst] = (inst); + + _instanceMap[instance] = inst; + + SystemClassRegistry::getInstance()->addInstanceToTable(inst, instance); + + return inst; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClass::removeInstance(void *instance) { + InstanceMap::iterator mapIt = _instanceMap.find(instance); + if (mapIt == _instanceMap.end()) { + return false; + } + + Instances::iterator it = _instances.find((mapIt->_value)); + if (it != _instances.end()) { + delete(it->_value); + _instances.erase(it); + } + + _instanceMap.erase(mapIt); + + return false; +} + +////////////////////////////////////////////////////////////////////////// +int SystemClass::getInstanceID(void *pointer) { + InstanceMap::iterator mapIt = _instanceMap.find(pointer); + if (mapIt == _instanceMap.end()) { + return -1; + } else { + return (mapIt->_value)->getID(); + } +} + +////////////////////////////////////////////////////////////////////////// +void *SystemClass::idToPointer(int savedID) { + //slow + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + if ((it->_value)->getSavedID() == savedID) { + return (it->_value)->getInstance(); + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +int SystemClass::getNumInstances() { + return _instances.size(); +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::dump(Common::WriteStream *stream) { + Common::String str; + str = Common::String::format("%03d %c %-20s instances: %d\n", _iD, _persistent ? 'p' : ' ', _name.c_str(), getNumInstances()); + stream->write(str.c_str(), str.size()); +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::saveTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { + persistMgr->putString(_name.c_str()); + persistMgr->putDWORD(_iD); + persistMgr->putDWORD(_instances.size()); + + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + persistMgr->putDWORD((it->_value)->getID()); + } +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::loadTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { + _savedID = persistMgr->getDWORD(); + int numInstances = persistMgr->getDWORD(); + + for (int i = 0; i < numInstances; i++) { + int instID = persistMgr->getDWORD(); + if (_persistent) { + + if (i > 0) { + gameRef->LOG(0, "Warning: attempting to load multiple instances of persistent class %s (%d)", _name.c_str(), numInstances); + continue; + } + + Instances::iterator it = _instances.begin(); + if (it != _instances.end()) { + (it->_value)->setSavedID(instID); + SystemClassRegistry::getInstance()->addInstanceToTable((it->_value), (it->_value)->getInstance()); + } else { + gameRef->LOG(0, "Warning: instance %d of persistent class %s not found", i, _name.c_str()); + } + } + // normal instances, create empty objects + else { + void *emptyObject = _build(); + if (!emptyObject) { + warning("HALT"); + } + + addInstance(emptyObject, SystemClassRegistry::getInstance()->getNextID(), instID); + } + + } +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::saveInstances(BaseGame *Game, BasePersistenceManager *persistMgr) { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + // write instace header + persistMgr->putString(""); + persistMgr->putDWORD(_iD); + persistMgr->putDWORD((it->_value)->getID()); + persistMgr->putString(""); + _load((it->_value)->getInstance(), persistMgr); + persistMgr->putString(""); + } +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::loadInstance(void *instance, BasePersistenceManager *persistMgr) { + _load(instance, persistMgr); +} + + +////////////////////////////////////////////////////////////////////////// +void SystemClass::resetSavedIDs() { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + (it->_value)->setSavedID(-1); + } +} + +////////////////////////////////////////////////////////////////////////// +void SystemClass::instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData) { + Instances::iterator it; + for (it = _instances.begin(); it != _instances.end(); ++it) { + lpCallback((it->_value)->getInstance(), lpData); + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/system/sys_class.h b/engines/wintermute/system/sys_class.h index 28d718bb47f9..3f91723ed860 100644 --- a/engines/wintermute/system/sys_class.h +++ b/engines/wintermute/system/sys_class.h @@ -1,130 +1,130 @@ -/* 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_SYSCLASS_H -#define WINTERMUTE_SYSCLASS_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/dctypes.h" -#include "common/hashmap.h" -#include "common/func.h" -#include "common/stream.h" - -namespace Wintermute { -class SystemInstance; -class BaseGame; -class BasePersistenceManager; -class SystemClass; - -} - -namespace Common { -template struct Hash; - -template<> struct Hash : public UnaryFunction { - uint operator()(void *val) const { - return (uint)((size_t)val); - } -}; - -template<> struct Hash : public UnaryFunction { - uint operator()(Wintermute::SystemInstance *val) const { - return (uint)((size_t)val); - } -}; - - -} - -namespace Wintermute { - -class SystemClass { -public: - SystemClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistentClass); - ~SystemClass(); - - int getNumInstances(); - bool removeInstance(void *instance); - SystemInstance *addInstance(void *instance, int id, int savedId = -1); - bool removeAllInstances(); - - int getInstanceID(void *pointer); - void *idToPointer(int savedID); - - void setID(int id) { - _iD = id; - } - int getID() const { - return _iD; - } - - int getSavedID() const { - return _savedID; - } - - bool isPersistent() const { - return _persistent; - } - - AnsiString getName() const { - return _name; - } - - void saveTable(BaseGame *Game, BasePersistenceManager *PersistMgr); - void loadTable(BaseGame *Game, BasePersistenceManager *PersistMgr); - - void saveInstances(BaseGame *Game, BasePersistenceManager *PersistMgr); - void loadInstance(void *instance, BasePersistenceManager *PersistMgr); - - void instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData); - - void resetSavedIDs(); - - void dump(Common::WriteStream *stream); - -private: - int _numInst; - bool _persistent; - SystemClass *_next; - int _iD; - int _savedID; - AnsiString _name; - PERSISTBUILD _build; - PERSISTLOAD _load; - - //typedef std::set Instances; - typedef Common::HashMap Instances; - Instances _instances; - - typedef Common::HashMap InstanceMap; - InstanceMap _instanceMap; -}; - -} // end of namespace Wintermute - -#endif +/* 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_SYSCLASS_H +#define WINTERMUTE_SYSCLASS_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/dctypes.h" +#include "common/hashmap.h" +#include "common/func.h" +#include "common/stream.h" + +namespace Wintermute { +class SystemInstance; +class BaseGame; +class BasePersistenceManager; +class SystemClass; + +} + +namespace Common { +template struct Hash; + +template<> struct Hash : public UnaryFunction { + uint operator()(void *val) const { + return (uint)((size_t)val); + } +}; + +template<> struct Hash : public UnaryFunction { + uint operator()(Wintermute::SystemInstance *val) const { + return (uint)((size_t)val); + } +}; + + +} + +namespace Wintermute { + +class SystemClass { +public: + SystemClass(const AnsiString &name, PERSISTBUILD build, PERSISTLOAD load, bool persistentClass); + ~SystemClass(); + + int getNumInstances(); + bool removeInstance(void *instance); + SystemInstance *addInstance(void *instance, int id, int savedId = -1); + bool removeAllInstances(); + + int getInstanceID(void *pointer); + void *idToPointer(int savedID); + + void setID(int id) { + _iD = id; + } + int getID() const { + return _iD; + } + + int getSavedID() const { + return _savedID; + } + + bool isPersistent() const { + return _persistent; + } + + AnsiString getName() const { + return _name; + } + + void saveTable(BaseGame *Game, BasePersistenceManager *PersistMgr); + void loadTable(BaseGame *Game, BasePersistenceManager *PersistMgr); + + void saveInstances(BaseGame *Game, BasePersistenceManager *PersistMgr); + void loadInstance(void *instance, BasePersistenceManager *PersistMgr); + + void instanceCallback(SYS_INSTANCE_CALLBACK lpCallback, void *lpData); + + void resetSavedIDs(); + + void dump(Common::WriteStream *stream); + +private: + int _numInst; + bool _persistent; + SystemClass *_next; + int _iD; + int _savedID; + AnsiString _name; + PERSISTBUILD _build; + PERSISTLOAD _load; + + //typedef std::set Instances; + typedef Common::HashMap Instances; + Instances _instances; + + typedef Common::HashMap InstanceMap; + InstanceMap _instanceMap; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/system/sys_class_registry.cpp b/engines/wintermute/system/sys_class_registry.cpp index d836b32635f7..5e3b968c5cd9 100644 --- a/engines/wintermute/system/sys_class_registry.cpp +++ b/engines/wintermute/system/sys_class_registry.cpp @@ -1,335 +1,335 @@ -/* 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_engine.h" -#include "engines/wintermute/system/sys_instance.h" -#include "engines/wintermute/system/sys_class_registry.h" -#include "engines/wintermute/system/sys_class.h" -#include "engines/wintermute/wintermute.h" -#include "common/stream.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -SystemClassRegistry::SystemClassRegistry() { - _count = 0; - _disabled = false; -} - - -////////////////////////////////////////////////////////////////////////// -SystemClassRegistry::~SystemClassRegistry() { - unregisterClasses(); -} - -////////////////////////////////////////////////////////////////////////// -SystemClassRegistry *SystemClassRegistry::getInstance() { - return BaseEngine::instance().getClassRegistry(); -} - -void SystemClassRegistry::unregisterClasses() { - // SystemClass calls UnregisterClass upon destruction. - while (_classes.size() > 0) { - delete _classes.begin()->_value; - } -} - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::registerClass(SystemClass *classObj) { - classObj->setID(_count++); - //_classes.insert(classObj); - _classes[classObj] = classObj; - - _nameMap[classObj->getName()] = classObj; - _idMap[classObj->getID()] = classObj; - - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::unregisterClass(SystemClass *classObj) { - - Classes::iterator it = _classes.find(classObj); - if (it == _classes.end()) { - return false; - } - - if (classObj->getNumInstances() != 0) { - debugC(Wintermute::kWintermuteDebugSaveGame, "Memory leak@class %-20s: %d instance(s) left\n", classObj->getName().c_str(), classObj->getNumInstances()); - } - _classes.erase(it); - - NameMap::iterator mapIt = _nameMap.find(classObj->getName()); - if (mapIt != _nameMap.end()) { - _nameMap.erase(mapIt); - } - - IdMap::iterator idIt = _idMap.find(classObj->getID()); - if (idIt != _idMap.end()) { - _idMap.erase(idIt); - } - - - return true; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::registerInstance(const char *className, void *instance) { - if (_disabled) { - return true; - } - - NameMap::iterator mapIt = _nameMap.find(className); - if (mapIt == _nameMap.end()) { - return false; - } - - SystemInstance *inst = (*mapIt)._value->addInstance(instance, _count++); - return (inst != NULL); -} - -////////////////////////////////////////////////////////////////////////// -void SystemClassRegistry::addInstanceToTable(SystemInstance *instance, void *pointer) { - _instanceMap[pointer] = instance; - - if (instance->getSavedID() >= 0) { - _savedInstanceMap[instance->getSavedID()] = instance; - } -} - -////////////////////////////////////////////////////////////////////////// -int SystemClassRegistry::getNextID() { - return _count++; -} - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::unregisterInstance(const char *className, void *instance) { - NameMap::iterator mapIt = _nameMap.find(className); - if (mapIt == _nameMap.end()) { - return false; - } - (*mapIt)._value->removeInstance(instance); - - InstanceMap::iterator instIt = _instanceMap.find(instance); - if (instIt != _instanceMap.end()) { - _instanceMap.erase(instIt); - return true; - } else { - return false; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::getPointerID(void *pointer, int *classID, int *instanceID) { - if (pointer == NULL) { - return true; - } - - InstanceMap::iterator it = _instanceMap.find(pointer); - if (it == _instanceMap.end()) { - return false; - } - - - SystemInstance *inst = (*it)._value; - *instanceID = inst->getID(); - *classID = inst->getClass()->getID(); - - return true; -} - -////////////////////////////////////////////////////////////////////////// -void *SystemClassRegistry::idToPointer(int classID, int instanceID) { - SavedInstanceMap::iterator it = _savedInstanceMap.find(instanceID); - if (it == _savedInstanceMap.end()) { - return NULL; - } else { - return (*it)._value->getInstance(); - } -} - -bool checkHeader(const char *tag, BasePersistenceManager *pm) { - char *test = pm->getString(); - Common::String verify = test; - delete[] test; - bool retVal = (verify == tag); - if (!retVal) { - error("Expected %s in Save-file not found", tag); - } - return retVal; -} - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::saveTable(BaseGame *gameRef, BasePersistenceManager *persistMgr, bool quickSave) { - persistMgr->putString(""); - persistMgr->putDWORD(_classes.size()); - - int counter = 0; - - Classes::iterator it; - for (it = _classes.begin(); it != _classes.end(); ++it) { - counter++; - - if (!quickSave) { - gameRef->_renderer->setIndicatorVal((int)(50.0f / (float)((float)_classes.size() / (float)counter))); - } - - (it->_value)->saveTable(gameRef, persistMgr); - } - persistMgr->putString(""); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::loadTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { - checkHeader("", persistMgr); - - // reset SavedID of current instances - Classes::iterator it; - for (it = _classes.begin(); it != _classes.end(); ++it) { - (it->_value)->resetSavedIDs(); - } - - for (it = _classes.begin(); it != _classes.end(); ++it) { - if ((it->_value)->isPersistent()) { - continue; - } - (it->_value)->removeAllInstances(); - } - - _instanceMap.clear(); - - uint32 numClasses = persistMgr->getDWORD(); - - for (uint32 i = 0; i < numClasses; i++) { - gameRef->_renderer->setIndicatorVal((int)(50.0f / (float)((float)numClasses / (float)i))); - - Common::String className = persistMgr->getStringObj(); - NameMap::iterator mapIt = _nameMap.find(className); - if (mapIt != _nameMap.end()) { - (*mapIt)._value->loadTable(gameRef, persistMgr); - } - } - - checkHeader("", persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::saveInstances(BaseGame *gameRef, BasePersistenceManager *persistMgr, bool quickSave) { - - Classes::iterator it; - - // count total instances - int numInstances = 0; - for (it = _classes.begin(); it != _classes.end(); ++it) { - numInstances += (it->_value)->getNumInstances(); - } - - persistMgr->putDWORD(numInstances); - - int counter = 0; - for (it = _classes.begin(); it != _classes.end(); ++it) { - counter++; - - if (!quickSave) { - if (counter % 20 == 0) { - gameRef->_renderer->setIndicatorVal((int)(50.0f + 50.0f / (float)((float)_classes.size() / (float)counter))); - } - } - gameRef->miniUpdate(); - - (it->_value)->saveInstances(gameRef, persistMgr); - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::loadInstances(BaseGame *gameRef, BasePersistenceManager *persistMgr) { - // get total instances - int numInstances = persistMgr->getDWORD(); - - for (int i = 0; i < numInstances; i++) { - if (i % 20 == 0) { - gameRef->_renderer->setIndicatorVal((int)(50.0f + 50.0f / (float)((float)numInstances / (float)i))); - } - - checkHeader("", persistMgr); - - int classID = persistMgr->getDWORD(); - int instanceID = persistMgr->getDWORD(); - void *instance = idToPointer(classID, instanceID); - - checkHeader("", persistMgr); - - Classes::iterator it; - for (it = _classes.begin(); it != _classes.end(); ++it) { - if ((it->_value)->getSavedID() == classID) { - (it->_value)->loadInstance(instance, persistMgr); - break; - } - } - checkHeader("", persistMgr); - } - - _savedInstanceMap.clear(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool SystemClassRegistry::enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData) { - NameMap::iterator mapIt = _nameMap.find(className); - if (mapIt == _nameMap.end()) { - return STATUS_FAILED; - } - - (*mapIt)._value->instanceCallback(lpCallback, lpData); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void SystemClassRegistry::dumpClasses(Common::WriteStream *stream) { - Classes::iterator it; - for (it = _classes.begin(); it != _classes.end(); ++it) { - (it->_value)->dump(stream); - } -} - -} // end of namespace Wintermute +/* 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_engine.h" +#include "engines/wintermute/system/sys_instance.h" +#include "engines/wintermute/system/sys_class_registry.h" +#include "engines/wintermute/system/sys_class.h" +#include "engines/wintermute/wintermute.h" +#include "common/stream.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +SystemClassRegistry::SystemClassRegistry() { + _count = 0; + _disabled = false; +} + + +////////////////////////////////////////////////////////////////////////// +SystemClassRegistry::~SystemClassRegistry() { + unregisterClasses(); +} + +////////////////////////////////////////////////////////////////////////// +SystemClassRegistry *SystemClassRegistry::getInstance() { + return BaseEngine::instance().getClassRegistry(); +} + +void SystemClassRegistry::unregisterClasses() { + // SystemClass calls UnregisterClass upon destruction. + while (_classes.size() > 0) { + delete _classes.begin()->_value; + } +} + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::registerClass(SystemClass *classObj) { + classObj->setID(_count++); + //_classes.insert(classObj); + _classes[classObj] = classObj; + + _nameMap[classObj->getName()] = classObj; + _idMap[classObj->getID()] = classObj; + + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::unregisterClass(SystemClass *classObj) { + + Classes::iterator it = _classes.find(classObj); + if (it == _classes.end()) { + return false; + } + + if (classObj->getNumInstances() != 0) { + debugC(Wintermute::kWintermuteDebugSaveGame, "Memory leak@class %-20s: %d instance(s) left\n", classObj->getName().c_str(), classObj->getNumInstances()); + } + _classes.erase(it); + + NameMap::iterator mapIt = _nameMap.find(classObj->getName()); + if (mapIt != _nameMap.end()) { + _nameMap.erase(mapIt); + } + + IdMap::iterator idIt = _idMap.find(classObj->getID()); + if (idIt != _idMap.end()) { + _idMap.erase(idIt); + } + + + return true; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::registerInstance(const char *className, void *instance) { + if (_disabled) { + return true; + } + + NameMap::iterator mapIt = _nameMap.find(className); + if (mapIt == _nameMap.end()) { + return false; + } + + SystemInstance *inst = (*mapIt)._value->addInstance(instance, _count++); + return (inst != NULL); +} + +////////////////////////////////////////////////////////////////////////// +void SystemClassRegistry::addInstanceToTable(SystemInstance *instance, void *pointer) { + _instanceMap[pointer] = instance; + + if (instance->getSavedID() >= 0) { + _savedInstanceMap[instance->getSavedID()] = instance; + } +} + +////////////////////////////////////////////////////////////////////////// +int SystemClassRegistry::getNextID() { + return _count++; +} + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::unregisterInstance(const char *className, void *instance) { + NameMap::iterator mapIt = _nameMap.find(className); + if (mapIt == _nameMap.end()) { + return false; + } + (*mapIt)._value->removeInstance(instance); + + InstanceMap::iterator instIt = _instanceMap.find(instance); + if (instIt != _instanceMap.end()) { + _instanceMap.erase(instIt); + return true; + } else { + return false; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::getPointerID(void *pointer, int *classID, int *instanceID) { + if (pointer == NULL) { + return true; + } + + InstanceMap::iterator it = _instanceMap.find(pointer); + if (it == _instanceMap.end()) { + return false; + } + + + SystemInstance *inst = (*it)._value; + *instanceID = inst->getID(); + *classID = inst->getClass()->getID(); + + return true; +} + +////////////////////////////////////////////////////////////////////////// +void *SystemClassRegistry::idToPointer(int classID, int instanceID) { + SavedInstanceMap::iterator it = _savedInstanceMap.find(instanceID); + if (it == _savedInstanceMap.end()) { + return NULL; + } else { + return (*it)._value->getInstance(); + } +} + +bool checkHeader(const char *tag, BasePersistenceManager *pm) { + char *test = pm->getString(); + Common::String verify = test; + delete[] test; + bool retVal = (verify == tag); + if (!retVal) { + error("Expected %s in Save-file not found", tag); + } + return retVal; +} + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::saveTable(BaseGame *gameRef, BasePersistenceManager *persistMgr, bool quickSave) { + persistMgr->putString(""); + persistMgr->putDWORD(_classes.size()); + + int counter = 0; + + Classes::iterator it; + for (it = _classes.begin(); it != _classes.end(); ++it) { + counter++; + + if (!quickSave) { + gameRef->_renderer->setIndicatorVal((int)(50.0f / (float)((float)_classes.size() / (float)counter))); + } + + (it->_value)->saveTable(gameRef, persistMgr); + } + persistMgr->putString(""); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::loadTable(BaseGame *gameRef, BasePersistenceManager *persistMgr) { + checkHeader("", persistMgr); + + // reset SavedID of current instances + Classes::iterator it; + for (it = _classes.begin(); it != _classes.end(); ++it) { + (it->_value)->resetSavedIDs(); + } + + for (it = _classes.begin(); it != _classes.end(); ++it) { + if ((it->_value)->isPersistent()) { + continue; + } + (it->_value)->removeAllInstances(); + } + + _instanceMap.clear(); + + uint32 numClasses = persistMgr->getDWORD(); + + for (uint32 i = 0; i < numClasses; i++) { + gameRef->_renderer->setIndicatorVal((int)(50.0f / (float)((float)numClasses / (float)i))); + + Common::String className = persistMgr->getStringObj(); + NameMap::iterator mapIt = _nameMap.find(className); + if (mapIt != _nameMap.end()) { + (*mapIt)._value->loadTable(gameRef, persistMgr); + } + } + + checkHeader("", persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::saveInstances(BaseGame *gameRef, BasePersistenceManager *persistMgr, bool quickSave) { + + Classes::iterator it; + + // count total instances + int numInstances = 0; + for (it = _classes.begin(); it != _classes.end(); ++it) { + numInstances += (it->_value)->getNumInstances(); + } + + persistMgr->putDWORD(numInstances); + + int counter = 0; + for (it = _classes.begin(); it != _classes.end(); ++it) { + counter++; + + if (!quickSave) { + if (counter % 20 == 0) { + gameRef->_renderer->setIndicatorVal((int)(50.0f + 50.0f / (float)((float)_classes.size() / (float)counter))); + } + } + gameRef->miniUpdate(); + + (it->_value)->saveInstances(gameRef, persistMgr); + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::loadInstances(BaseGame *gameRef, BasePersistenceManager *persistMgr) { + // get total instances + int numInstances = persistMgr->getDWORD(); + + for (int i = 0; i < numInstances; i++) { + if (i % 20 == 0) { + gameRef->_renderer->setIndicatorVal((int)(50.0f + 50.0f / (float)((float)numInstances / (float)i))); + } + + checkHeader("", persistMgr); + + int classID = persistMgr->getDWORD(); + int instanceID = persistMgr->getDWORD(); + void *instance = idToPointer(classID, instanceID); + + checkHeader("", persistMgr); + + Classes::iterator it; + for (it = _classes.begin(); it != _classes.end(); ++it) { + if ((it->_value)->getSavedID() == classID) { + (it->_value)->loadInstance(instance, persistMgr); + break; + } + } + checkHeader("", persistMgr); + } + + _savedInstanceMap.clear(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool SystemClassRegistry::enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData) { + NameMap::iterator mapIt = _nameMap.find(className); + if (mapIt == _nameMap.end()) { + return STATUS_FAILED; + } + + (*mapIt)._value->instanceCallback(lpCallback, lpData); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void SystemClassRegistry::dumpClasses(Common::WriteStream *stream) { + Classes::iterator it; + for (it = _classes.begin(); it != _classes.end(); ++it) { + (it->_value)->dump(stream); + } +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/system/sys_class_registry.h b/engines/wintermute/system/sys_class_registry.h index e612ab3e82be..ef7218c7c18c 100644 --- a/engines/wintermute/system/sys_class_registry.h +++ b/engines/wintermute/system/sys_class_registry.h @@ -1,106 +1,106 @@ -/* 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_SYSCLASSREGISTRY_H -#define WINTERMUTE_SYSCLASSREGISTRY_H - -#include "engines/wintermute/wintypes.h" -#include "engines/wintermute/dctypes.h" -#include "engines/wintermute/system/sys_class.h" -#include "common/hashmap.h" -#include "common/hash-str.h" -#include "common/func.h" -#include "common/stream.h" - -namespace Wintermute { -class SystemClass; -} - -namespace Common { -template struct Hash; -template<> struct Hash : public UnaryFunction { - uint operator()(Wintermute::SystemClass *val) const { - return (uint)((size_t)val); - } -}; - -} - -namespace Wintermute { - -class BaseGame; -class BasePersistenceManager; -class SystemInstance; - -class SystemClassRegistry { - void unregisterClasses(); -public: - void registerClasses(); // persistent.cpp - static SystemClassRegistry *getInstance(); - - SystemClassRegistry(); - virtual ~SystemClassRegistry(); - - bool enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData); - bool loadTable(BaseGame *Game, BasePersistenceManager *PersistMgr); - bool saveTable(BaseGame *Game, BasePersistenceManager *PersistMgr, bool quickSave); - bool loadInstances(BaseGame *Game, BasePersistenceManager *PersistMgr); - bool saveInstances(BaseGame *Game, BasePersistenceManager *PersistMgr, bool quickSave); - void *idToPointer(int classID, int instanceID); - bool getPointerID(void *pointer, int *classID, int *instanceID); - bool registerClass(SystemClass *classObj); - bool unregisterClass(SystemClass *classObj); - bool registerInstance(const char *className, void *instance); - bool unregisterInstance(const char *className, void *instance); - void dumpClasses(Common::WriteStream *stream); - int getNextID(); - void addInstanceToTable(SystemInstance *instance, void *pointer); - - bool _disabled; - int _count; - - typedef Common::HashMap Classes; - Classes _classes; - - typedef Common::HashMap NameMap; - NameMap _nameMap; - - typedef Common::HashMap IdMap; - IdMap _idMap; - - typedef Common::HashMap InstanceMap; - InstanceMap _instanceMap; - - typedef Common::HashMap SavedInstanceMap; - SavedInstanceMap _savedInstanceMap; - -}; - -} // end of namespace Wintermute - -#endif +/* 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_SYSCLASSREGISTRY_H +#define WINTERMUTE_SYSCLASSREGISTRY_H + +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/dctypes.h" +#include "engines/wintermute/system/sys_class.h" +#include "common/hashmap.h" +#include "common/hash-str.h" +#include "common/func.h" +#include "common/stream.h" + +namespace Wintermute { +class SystemClass; +} + +namespace Common { +template struct Hash; +template<> struct Hash : public UnaryFunction { + uint operator()(Wintermute::SystemClass *val) const { + return (uint)((size_t)val); + } +}; + +} + +namespace Wintermute { + +class BaseGame; +class BasePersistenceManager; +class SystemInstance; + +class SystemClassRegistry { + void unregisterClasses(); +public: + void registerClasses(); // persistent.cpp + static SystemClassRegistry *getInstance(); + + SystemClassRegistry(); + virtual ~SystemClassRegistry(); + + bool enumInstances(SYS_INSTANCE_CALLBACK lpCallback, const char *className, void *lpData); + bool loadTable(BaseGame *Game, BasePersistenceManager *PersistMgr); + bool saveTable(BaseGame *Game, BasePersistenceManager *PersistMgr, bool quickSave); + bool loadInstances(BaseGame *Game, BasePersistenceManager *PersistMgr); + bool saveInstances(BaseGame *Game, BasePersistenceManager *PersistMgr, bool quickSave); + void *idToPointer(int classID, int instanceID); + bool getPointerID(void *pointer, int *classID, int *instanceID); + bool registerClass(SystemClass *classObj); + bool unregisterClass(SystemClass *classObj); + bool registerInstance(const char *className, void *instance); + bool unregisterInstance(const char *className, void *instance); + void dumpClasses(Common::WriteStream *stream); + int getNextID(); + void addInstanceToTable(SystemInstance *instance, void *pointer); + + bool _disabled; + int _count; + + typedef Common::HashMap Classes; + Classes _classes; + + typedef Common::HashMap NameMap; + NameMap _nameMap; + + typedef Common::HashMap IdMap; + IdMap _idMap; + + typedef Common::HashMap InstanceMap; + InstanceMap _instanceMap; + + typedef Common::HashMap SavedInstanceMap; + SavedInstanceMap _savedInstanceMap; + +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/system/sys_instance.cpp b/engines/wintermute/system/sys_instance.cpp index 132338215294..d106119dbae5 100644 --- a/engines/wintermute/system/sys_instance.cpp +++ b/engines/wintermute/system/sys_instance.cpp @@ -1,49 +1,49 @@ -/* 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_instance.h" -#include "engines/wintermute/system/sys_class_registry.h" -#include "engines/wintermute/system/sys_class.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -SystemInstance::SystemInstance(void *instance, int id, SystemClass *sysClass) { - _instance = instance; - _id = id; - _savedID = -1; - _class = sysClass; - - _used = false; -} - -////////////////////////////////////////////////////////////////////////// -SystemInstance::~SystemInstance() { -} - -} // end of namespace Wintermute +/* 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_instance.h" +#include "engines/wintermute/system/sys_class_registry.h" +#include "engines/wintermute/system/sys_class.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +SystemInstance::SystemInstance(void *instance, int id, SystemClass *sysClass) { + _instance = instance; + _id = id; + _savedID = -1; + _class = sysClass; + + _used = false; +} + +////////////////////////////////////////////////////////////////////////// +SystemInstance::~SystemInstance() { +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/system/sys_instance.h b/engines/wintermute/system/sys_instance.h index 78eb27c12265..215a6d1437b6 100644 --- a/engines/wintermute/system/sys_instance.h +++ b/engines/wintermute/system/sys_instance.h @@ -1,68 +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_SYSINSTANCE_H -#define WINTERMUTE_SYSINSTANCE_H - -namespace Wintermute { - -class SystemClass; - -class SystemInstance { -public: - SystemInstance(void *instance, int id, SystemClass *sysClass); - virtual ~SystemInstance(); - - int getID() const { - return _id; - } - int getSavedID() const { - return _savedID; - } - void *getInstance() const { - return _instance; - } - SystemClass *getClass() const { - return _class; - } - - void setSavedID(int id) { - _savedID = id; - } - -private: - bool _used; - int _id; - int _savedID; - void *_instance; - SystemClass *_class; -}; - -} // end of namespace Wintermute - -#endif +/* 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_SYSINSTANCE_H +#define WINTERMUTE_SYSINSTANCE_H + +namespace Wintermute { + +class SystemClass; + +class SystemInstance { +public: + SystemInstance(void *instance, int id, SystemClass *sysClass); + virtual ~SystemInstance(); + + int getID() const { + return _id; + } + int getSavedID() const { + return _savedID; + } + void *getInstance() const { + return _instance; + } + SystemClass *getClass() const { + return _class; + } + + void setSavedID(int id) { + _savedID = id; + } + +private: + bool _used; + int _id; + int _savedID; + void *_instance; + SystemClass *_class; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ui/ui_button.cpp b/engines/wintermute/ui/ui_button.cpp index c5ca63081cc3..f2ac5b2fddb8 100644 --- a/engines/wintermute/ui/ui_button.cpp +++ b/engines/wintermute/ui/ui_button.cpp @@ -1,1208 +1,1208 @@ -/* 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_dynamic_buffer.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/ui/ui_button.h" -#include "engines/wintermute/ui/ui_tiled_image.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_active_rect.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.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(UIButton, false) - -////////////////////////////////////////////////////////////////////////// -UIButton::UIButton(BaseGame *inGame) : UIObject(inGame) { - _backPress = _backHover = _backDisable = _backFocus = NULL; - - _fontHover = _fontPress = _fontDisable = _fontFocus = NULL; - - _imageDisable = _imagePress = _imageHover = _imageFocus = NULL; - - _align = TAL_CENTER; - - _hover = _press = false; - - _type = UI_BUTTON; - - _canFocus = false; - _stayPressed = false; - - _oneTimePress = false; - _centerImage = false; - - _pixelPerfect = false; -} - - -////////////////////////////////////////////////////////////////////////// -UIButton::~UIButton() { - delete _backPress; - delete _backHover; - delete _backDisable; - delete _backFocus; - - if (!_sharedFonts) { - if (_fontHover) { - _gameRef->_fontStorage->removeFont(_fontHover); - } - if (_fontPress) { - _gameRef->_fontStorage->removeFont(_fontPress); - } - if (_fontDisable) { - _gameRef->_fontStorage->removeFont(_fontDisable); - } - if (_fontFocus) { - _gameRef->_fontStorage->removeFont(_fontFocus); - } - } - - if (!_sharedImages) { - delete _imageHover; - delete _imagePress; - delete _imageDisable; - delete _imageFocus; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIButton::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UIButton::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 BUTTON file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(BUTTON) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(DISABLED) -TOKEN_DEF(VISIBLE) -TOKEN_DEF(FOCUSABLE) -TOKEN_DEF(BACK_HOVER) -TOKEN_DEF(BACK_PRESS) -TOKEN_DEF(BACK_DISABLE) -TOKEN_DEF(BACK_FOCUS) -TOKEN_DEF(BACK) -TOKEN_DEF(CENTER_IMAGE) -TOKEN_DEF(IMAGE_HOVER) -TOKEN_DEF(IMAGE_PRESS) -TOKEN_DEF(IMAGE_DISABLE) -TOKEN_DEF(IMAGE_FOCUS) -TOKEN_DEF(IMAGE) -TOKEN_DEF(FONT_HOVER) -TOKEN_DEF(FONT_PRESS) -TOKEN_DEF(FONT_DISABLE) -TOKEN_DEF(FONT_FOCUS) -TOKEN_DEF(FONT) -TOKEN_DEF(TEXT_ALIGN) -TOKEN_DEF(TEXT) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(WIDTH) -TOKEN_DEF(HEIGHT) -TOKEN_DEF(CURSOR) -TOKEN_DEF(NAME) -TOKEN_DEF(EVENTS) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PARENT_NOTIFY) -TOKEN_DEF(PRESSED) -TOKEN_DEF(PIXEL_PERFECT) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UIButton::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(BUTTON) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(DISABLED) - TOKEN_TABLE(VISIBLE) - TOKEN_TABLE(FOCUSABLE) - TOKEN_TABLE(BACK_HOVER) - TOKEN_TABLE(BACK_PRESS) - TOKEN_TABLE(BACK_DISABLE) - TOKEN_TABLE(BACK_FOCUS) - TOKEN_TABLE(BACK) - TOKEN_TABLE(CENTER_IMAGE) - TOKEN_TABLE(IMAGE_HOVER) - TOKEN_TABLE(IMAGE_PRESS) - TOKEN_TABLE(IMAGE_DISABLE) - TOKEN_TABLE(IMAGE_FOCUS) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(FONT_HOVER) - TOKEN_TABLE(FONT_PRESS) - TOKEN_TABLE(FONT_DISABLE) - TOKEN_TABLE(FONT_FOCUS) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TEXT_ALIGN) - TOKEN_TABLE(TEXT) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(WIDTH) - TOKEN_TABLE(HEIGHT) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(NAME) - TOKEN_TABLE(EVENTS) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PARENT_NOTIFY) - TOKEN_TABLE(PRESSED) - TOKEN_TABLE(PIXEL_PERFECT) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_BUTTON) { - _gameRef->LOG(0, "'BUTTON' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: - delete _back; - _back = new UITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BACK_HOVER: - delete _backHover; - _backHover = new UITiledImage(_gameRef); - if (!_backHover || DID_FAIL(_backHover->loadFile((char *)params))) { - delete _backHover; - _backHover = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BACK_PRESS: - delete _backPress; - _backPress = new UITiledImage(_gameRef); - if (!_backPress || DID_FAIL(_backPress->loadFile((char *)params))) { - delete _backPress; - _backPress = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BACK_DISABLE: - delete _backDisable; - _backDisable = new UITiledImage(_gameRef); - if (!_backDisable || DID_FAIL(_backDisable->loadFile((char *)params))) { - delete _backDisable; - _backDisable = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BACK_FOCUS: - delete _backFocus; - _backFocus = new UITiledImage(_gameRef); - if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) { - delete _backFocus; - _backFocus = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new BaseSprite(_gameRef); - if (!_image || DID_FAIL(_image->loadFile((char *)params))) { - delete _image; - _image = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_HOVER: - delete _imageHover; - _imageHover = new BaseSprite(_gameRef); - if (!_imageHover || DID_FAIL(_imageHover->loadFile((char *)params))) { - delete _imageHover; - _imageHover = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_PRESS: - delete _imagePress; - _imagePress = new BaseSprite(_gameRef); - if (!_imagePress || DID_FAIL(_imagePress->loadFile((char *)params))) { - delete _imagePress; - _imagePress = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_DISABLE: - delete _imageDisable; - _imageDisable = new BaseSprite(_gameRef); - if (!_imageDisable || DID_FAIL(_imageDisable->loadFile((char *)params))) { - delete _imageDisable; - _imageDisable = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_FOCUS: - delete _imageFocus; - _imageFocus = new BaseSprite(_gameRef); - if (!_imageFocus || DID_FAIL(_imageFocus->loadFile((char *)params))) { - delete _imageFocus; - _imageFocus = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT: - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont((char *)params); - if (!_font) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_HOVER: - if (_fontHover) { - _gameRef->_fontStorage->removeFont(_fontHover); - } - _fontHover = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontHover) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_PRESS: - if (_fontPress) { - _gameRef->_fontStorage->removeFont(_fontPress); - } - _fontPress = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontPress) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_DISABLE: - if (_fontDisable) { - _gameRef->_fontStorage->removeFont(_fontDisable); - } - _fontDisable = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontDisable) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_FOCUS: - if (_fontFocus) { - _gameRef->_fontStorage->removeFont(_fontFocus); - } - _fontFocus = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontFocus) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_TEXT: - setText((char *)params); - _gameRef->_stringTable->expand(&_text); - break; - - case TOKEN_TEXT_ALIGN: - if (scumm_stricmp((char *)params, "left") == 0) { - _align = TAL_LEFT; - } else if (scumm_stricmp((char *)params, "right") == 0) { - _align = TAL_RIGHT; - } else { - _align = TAL_CENTER; - } - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_WIDTH: - parser.scanStr((char *)params, "%d", &_width); - break; - - case TOKEN_HEIGHT: - parser.scanStr((char *)params, "%d", &_height); - 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_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PARENT_NOTIFY: - parser.scanStr((char *)params, "%b", &_parentNotify); - break; - - case TOKEN_DISABLED: - parser.scanStr((char *)params, "%b", &_disable); - break; - - case TOKEN_VISIBLE: - parser.scanStr((char *)params, "%b", &_visible); - break; - - case TOKEN_FOCUSABLE: - parser.scanStr((char *)params, "%b", &_canFocus); - break; - - case TOKEN_CENTER_IMAGE: - parser.scanStr((char *)params, "%b", &_centerImage); - break; - - case TOKEN_PRESSED: - parser.scanStr((char *)params, "%b", &_stayPressed); - break; - - case TOKEN_PIXEL_PERFECT: - parser.scanStr((char *)params, "%b", &_pixelPerfect); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in BUTTON definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading BUTTON definition"); - return STATUS_FAILED; - } - - correctSize(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIButton::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "BUTTON\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); - } - if (_backHover && _backHover->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK_HOVER=\"%s\"\n", _backHover->getFilename()); - } - if (_backPress && _backPress->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK_PRESS=\"%s\"\n", _backPress->getFilename()); - } - if (_backDisable && _backDisable->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK_DISABLE=\"%s\"\n", _backDisable->getFilename()); - } - if (_backFocus && _backFocus->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK_FOCUS=\"%s\"\n", _backFocus->getFilename()); - } - - if (_image && _image->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); - } - if (_imageHover && _imageHover->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE_HOVER=\"%s\"\n", _imageHover->getFilename()); - } - if (_imagePress && _imagePress->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE_PRESS=\"%s\"\n", _imagePress->getFilename()); - } - if (_imageDisable && _imageDisable->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE_DISABLE=\"%s\"\n", _imageDisable->getFilename()); - } - if (_imageFocus && _imageFocus->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE_FOCUS=\"%s\"\n", _imageFocus->getFilename()); - } - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - if (_fontHover && _fontHover->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->getFilename()); - } - if (_fontPress && _fontPress->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_PRESS=\"%s\"\n", _fontPress->getFilename()); - } - if (_fontDisable && _fontDisable->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_DISABLE=\"%s\"\n", _fontDisable->getFilename()); - } - if (_fontFocus && _fontFocus->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_FOCUS=\"%s\"\n", _fontFocus->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - - buffer->putTextIndent(indent + 2, "\n"); - - if (_text) { - buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); - } - - switch (_align) { - case TAL_LEFT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); - break; - case TAL_RIGHT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); - break; - case TAL_CENTER: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); - break; - default: - warning("UIButton::SaveAsText - unhandled enum"); - break; - } - - buffer->putTextIndent(indent + 2, "\n"); - - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); - buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); - - - buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "FOCUSABLE=%s\n", _canFocus ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "CENTER_IMAGE=%s\n", _centerImage ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PRESSED=%s\n", _stayPressed ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PIXEL_PERFECT=%s\n", _pixelPerfect ? "TRUE" : "FALSE"); - - buffer->putTextIndent(indent + 2, "\n"); - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void UIButton::correctSize() { - Rect32 rect; - - BaseSprite *img = NULL; - if (_image) { - img = _image; - } else if (_imageDisable) { - img = _imageDisable; - } else if (_imageHover) { - img = _imageHover; - } else if (_imagePress) { - img = _imagePress; - } else if (_imageFocus) { - img = _imageFocus; - } - - if (_width <= 0) { - if (img) { - img->getBoundingRect(&rect, 0, 0); - _width = rect.right - rect.left; - } else { - _width = 100; - } - } - - if (_height <= 0) { - if (img) { - img->getBoundingRect(&rect, 0, 0); - _height = rect.bottom - rect.top; - } - } - - if (_text) { - int text_height; - if (_font) { - text_height = _font->getTextHeight((byte *)_text, _width); - } else { - text_height = _gameRef->_systemFont->getTextHeight((byte *)_text, _width); - } - - if (text_height > _height) { - _height = text_height; - } - } - - if (_height <= 0) { - _height = 100; - } - - if (_back) { - _back->correctSize(&_width, &_height); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIButton::display(int offsetX, int offsetY) { - if (!_visible) { - return STATUS_OK; - } - - UITiledImage *back = NULL; - BaseSprite *image = NULL; - BaseFont *font = 0; - - //RECT rect; - //BasePlatform::setRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height); - //_hover = (!_disable && BasePlatform::ptInRect(&rect, _gameRef->_mousePos)!=FALSE); - _hover = (!_disable && _gameRef->_activeObject == this && (_gameRef->_interactive || _gameRef->_state == GAME_SEMI_FROZEN)); - - if ((_press && _hover && !_gameRef->_mouseLeftDown) || - (_oneTimePress && g_system->getMillis() - _oneTimePressTime >= 100)) { - press(); - } - - - if (_disable) { - if (_backDisable) { - back = _backDisable; - } - if (_imageDisable) { - image = _imageDisable; - } - if (_text && _fontDisable) { - font = _fontDisable; - } - } else if (_press || _oneTimePress || _stayPressed) { - if (_backPress) { - back = _backPress; - } - if (_imagePress) { - image = _imagePress; - } - if (_text && _fontPress) { - font = _fontPress; - } - } else if (_hover) { - if (_backHover) { - back = _backHover; - } - if (_imageHover) { - image = _imageHover; - } - if (_text && _fontHover) { - font = _fontHover; - } - } else if (_canFocus && isFocused()) { - if (_backFocus) { - back = _backFocus; - } - if (_imageFocus) { - image = _imageFocus; - } - if (_text && _fontFocus) { - font = _fontFocus; - } - } - - if (!back && _back) { - back = _back; - } - if (!image && _image) { - image = _image; - } - if (_text && !font) { - if (_font) { - font = _font; - } else { - font = _gameRef->_systemFont; - } - } - - int imageX = offsetX + _posX; - int imageY = offsetY + _posY; - - if (image && _centerImage) { - Rect32 rc; - image->getBoundingRect(&rc, 0, 0); - imageX += (_width - (rc.right - rc.left)) / 2; - imageY += (_height - (rc.bottom - rc.top)) / 2; - } - - if (back) { - back->display(offsetX + _posX, offsetY + _posY, _width, _height); - } - //if (image) image->Draw(ImageX +((_press||_oneTimePress)&&back?1:0), ImageY +((_press||_oneTimePress)&&back?1:0), NULL); - if (image) { - image->draw(imageX + ((_press || _oneTimePress) && back ? 1 : 0), imageY + ((_press || _oneTimePress) && back ? 1 : 0), _pixelPerfect ? this : NULL); - } - - if (font && _text) { - int text_offset = (_height - font->getTextHeight((byte *)_text, _width)) / 2; - font->drawText((byte *)_text, offsetX + _posX + ((_press || _oneTimePress) ? 1 : 0), offsetY + _posY + text_offset + ((_press || _oneTimePress) ? 1 : 0), _width, _align); - } - - if (!_pixelPerfect || !_image) { - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); - } - - // reset unused sprites - if (_image && _image != image) { - _image->reset(); - } - if (_imageDisable && _imageDisable != image) { - _imageDisable->reset(); - } - if (_imageFocus && _imageFocus != image) { - _imageFocus->reset(); - } - if (_imagePress && _imagePress != image) { - _imagePress->reset(); - } - if (_imageHover && _imageHover != image) { - _imageHover->reset(); - } - - _press = _hover && _gameRef->_mouseLeftDown && _gameRef->_capturedObject == this; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void UIButton::press() { - applyEvent("Press"); - if (_listenerObject) { - _listenerObject->listen(_listenerParamObject, _listenerParamDWORD); - } - if (_parentNotify && _parent) { - _parent->applyEvent(getName()); - } - - _oneTimePress = false; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetDisabledFont - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetDisabledFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (_fontDisable) { - _gameRef->_fontStorage->removeFont(_fontDisable); - } - if (val->isNULL()) { - _fontDisable = NULL; - stack->pushBool(true); - } else { - _fontDisable = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontDisable != NULL); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetHoverFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetHoverFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (_fontHover) { - _gameRef->_fontStorage->removeFont(_fontHover); - } - if (val->isNULL()) { - _fontHover = NULL; - stack->pushBool(true); - } else { - _fontHover = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontHover != NULL); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetPressedFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetPressedFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (_fontPress) { - _gameRef->_fontStorage->removeFont(_fontPress); - } - if (val->isNULL()) { - _fontPress = NULL; - stack->pushBool(true); - } else { - _fontPress = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontPress != NULL); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetFocusedFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetFocusedFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (_fontFocus) { - _gameRef->_fontStorage->removeFont(_fontFocus); - } - if (val->isNULL()) { - _fontFocus = NULL; - stack->pushBool(true); - } else { - _fontFocus = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_fontFocus != NULL); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetDisabledImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetDisabledImage") == 0) { - stack->correctParams(1); - - delete _imageDisable; - _imageDisable = new BaseSprite(_gameRef); - const char *filename = stack->pop()->getString(); - if (!_imageDisable || DID_FAIL(_imageDisable->loadFile(filename))) { - delete _imageDisable; - _imageDisable = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetDisabledImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetDisabledImage") == 0) { - stack->correctParams(0); - if (!_imageDisable || !_imageDisable->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_imageDisable->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetDisabledImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetDisabledImageObject") == 0) { - stack->correctParams(0); - if (!_imageDisable) { - stack->pushNULL(); - } else { - stack->pushNative(_imageDisable, true); - } - - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // SetHoverImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetHoverImage") == 0) { - stack->correctParams(1); - - delete _imageHover; - _imageHover = new BaseSprite(_gameRef); - const char *filename = stack->pop()->getString(); - if (!_imageHover || DID_FAIL(_imageHover->loadFile(filename))) { - delete _imageHover; - _imageHover = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverImage") == 0) { - stack->correctParams(0); - if (!_imageHover || !_imageHover->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_imageHover->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetHoverImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetHoverImageObject") == 0) { - stack->correctParams(0); - if (!_imageHover) { - stack->pushNULL(); - } else { - stack->pushNative(_imageHover, true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetPressedImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetPressedImage") == 0) { - stack->correctParams(1); - - delete _imagePress; - _imagePress = new BaseSprite(_gameRef); - const char *filename = stack->pop()->getString(); - if (!_imagePress || DID_FAIL(_imagePress->loadFile(filename))) { - delete _imagePress; - _imagePress = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetPressedImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetPressedImage") == 0) { - stack->correctParams(0); - if (!_imagePress || !_imagePress->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_imagePress->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetPressedImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetPressedImageObject") == 0) { - stack->correctParams(0); - if (!_imagePress) { - stack->pushNULL(); - } else { - stack->pushNative(_imagePress, true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetFocusedImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetFocusedImage") == 0) { - stack->correctParams(1); - - delete _imageFocus; - _imageFocus = new BaseSprite(_gameRef); - const char *filename = stack->pop()->getString(); - if (!_imageFocus || DID_FAIL(_imageFocus->loadFile(filename))) { - delete _imageFocus; - _imageFocus = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetFocusedImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetFocusedImage") == 0) { - stack->correctParams(0); - if (!_imageFocus || !_imageFocus->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_imageFocus->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetFocusedImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetFocusedImageObject") == 0) { - stack->correctParams(0); - if (!_imageFocus) { - stack->pushNULL(); - } else { - stack->pushNative(_imageFocus, true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Press - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Press") == 0) { - stack->correctParams(0); - - if (_visible && !_disable) { - _oneTimePress = true; - _oneTimePressTime = g_system->getMillis(); - } - stack->pushNULL(); - - return STATUS_OK; - } else { - return UIObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIButton::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("button"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TextAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TextAlign") == 0) { - _scValue->setInt(_align); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Focusable - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Focusable") == 0) { - _scValue->setBool(_canFocus); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // Pressed - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Pressed") == 0) { - _scValue->setBool(_stayPressed); - return _scValue; - } - ////////////////////////////////////////////////////////////////////////// - // PixelPerfect - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PixelPerfect") == 0) { - _scValue->setBool(_pixelPerfect); - return _scValue; - } else { - return UIObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIButton::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // TextAlign - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "TextAlign") == 0) { - int i = value->getInt(); - if (i < 0 || i >= NUM_TEXT_ALIGN) { - i = 0; - } - _align = (TTextAlign)i; - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Focusable - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Focusable") == 0) { - _canFocus = value->getBool(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // Pressed - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Pressed") == 0) { - _stayPressed = value->getBool(); - return STATUS_OK; - } - ////////////////////////////////////////////////////////////////////////// - // PixelPerfect - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PixelPerfect") == 0) { - _pixelPerfect = value->getBool(); - return STATUS_OK; - } else { - return UIObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIButton::scToString() { - return "[button]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIButton::persist(BasePersistenceManager *persistMgr) { - - UIObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER_INT(_align)); - persistMgr->transfer(TMEMBER(_backDisable)); - persistMgr->transfer(TMEMBER(_backFocus)); - persistMgr->transfer(TMEMBER(_backHover)); - persistMgr->transfer(TMEMBER(_backPress)); - persistMgr->transfer(TMEMBER(_centerImage)); - persistMgr->transfer(TMEMBER(_fontDisable)); - persistMgr->transfer(TMEMBER(_fontFocus)); - persistMgr->transfer(TMEMBER(_fontHover)); - persistMgr->transfer(TMEMBER(_fontPress)); - persistMgr->transfer(TMEMBER(_hover)); - persistMgr->transfer(TMEMBER(_image)); - persistMgr->transfer(TMEMBER(_imageDisable)); - persistMgr->transfer(TMEMBER(_imageFocus)); - persistMgr->transfer(TMEMBER(_imageHover)); - persistMgr->transfer(TMEMBER(_imagePress)); - persistMgr->transfer(TMEMBER(_pixelPerfect)); - persistMgr->transfer(TMEMBER(_press)); - persistMgr->transfer(TMEMBER(_stayPressed)); - - if (!persistMgr->getIsSaving()) { - _oneTimePress = false; - _oneTimePressTime = 0; - } - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_dynamic_buffer.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/ui/ui_button.h" +#include "engines/wintermute/ui/ui_tiled_image.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_active_rect.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.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(UIButton, false) + +////////////////////////////////////////////////////////////////////////// +UIButton::UIButton(BaseGame *inGame) : UIObject(inGame) { + _backPress = _backHover = _backDisable = _backFocus = NULL; + + _fontHover = _fontPress = _fontDisable = _fontFocus = NULL; + + _imageDisable = _imagePress = _imageHover = _imageFocus = NULL; + + _align = TAL_CENTER; + + _hover = _press = false; + + _type = UI_BUTTON; + + _canFocus = false; + _stayPressed = false; + + _oneTimePress = false; + _centerImage = false; + + _pixelPerfect = false; +} + + +////////////////////////////////////////////////////////////////////////// +UIButton::~UIButton() { + delete _backPress; + delete _backHover; + delete _backDisable; + delete _backFocus; + + if (!_sharedFonts) { + if (_fontHover) { + _gameRef->_fontStorage->removeFont(_fontHover); + } + if (_fontPress) { + _gameRef->_fontStorage->removeFont(_fontPress); + } + if (_fontDisable) { + _gameRef->_fontStorage->removeFont(_fontDisable); + } + if (_fontFocus) { + _gameRef->_fontStorage->removeFont(_fontFocus); + } + } + + if (!_sharedImages) { + delete _imageHover; + delete _imagePress; + delete _imageDisable; + delete _imageFocus; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIButton::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UIButton::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 BUTTON file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(BUTTON) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(DISABLED) +TOKEN_DEF(VISIBLE) +TOKEN_DEF(FOCUSABLE) +TOKEN_DEF(BACK_HOVER) +TOKEN_DEF(BACK_PRESS) +TOKEN_DEF(BACK_DISABLE) +TOKEN_DEF(BACK_FOCUS) +TOKEN_DEF(BACK) +TOKEN_DEF(CENTER_IMAGE) +TOKEN_DEF(IMAGE_HOVER) +TOKEN_DEF(IMAGE_PRESS) +TOKEN_DEF(IMAGE_DISABLE) +TOKEN_DEF(IMAGE_FOCUS) +TOKEN_DEF(IMAGE) +TOKEN_DEF(FONT_HOVER) +TOKEN_DEF(FONT_PRESS) +TOKEN_DEF(FONT_DISABLE) +TOKEN_DEF(FONT_FOCUS) +TOKEN_DEF(FONT) +TOKEN_DEF(TEXT_ALIGN) +TOKEN_DEF(TEXT) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(WIDTH) +TOKEN_DEF(HEIGHT) +TOKEN_DEF(CURSOR) +TOKEN_DEF(NAME) +TOKEN_DEF(EVENTS) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PARENT_NOTIFY) +TOKEN_DEF(PRESSED) +TOKEN_DEF(PIXEL_PERFECT) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UIButton::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(BUTTON) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(DISABLED) + TOKEN_TABLE(VISIBLE) + TOKEN_TABLE(FOCUSABLE) + TOKEN_TABLE(BACK_HOVER) + TOKEN_TABLE(BACK_PRESS) + TOKEN_TABLE(BACK_DISABLE) + TOKEN_TABLE(BACK_FOCUS) + TOKEN_TABLE(BACK) + TOKEN_TABLE(CENTER_IMAGE) + TOKEN_TABLE(IMAGE_HOVER) + TOKEN_TABLE(IMAGE_PRESS) + TOKEN_TABLE(IMAGE_DISABLE) + TOKEN_TABLE(IMAGE_FOCUS) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(FONT_HOVER) + TOKEN_TABLE(FONT_PRESS) + TOKEN_TABLE(FONT_DISABLE) + TOKEN_TABLE(FONT_FOCUS) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TEXT_ALIGN) + TOKEN_TABLE(TEXT) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(WIDTH) + TOKEN_TABLE(HEIGHT) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(NAME) + TOKEN_TABLE(EVENTS) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PARENT_NOTIFY) + TOKEN_TABLE(PRESSED) + TOKEN_TABLE(PIXEL_PERFECT) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_BUTTON) { + _gameRef->LOG(0, "'BUTTON' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: + delete _back; + _back = new UITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BACK_HOVER: + delete _backHover; + _backHover = new UITiledImage(_gameRef); + if (!_backHover || DID_FAIL(_backHover->loadFile((char *)params))) { + delete _backHover; + _backHover = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BACK_PRESS: + delete _backPress; + _backPress = new UITiledImage(_gameRef); + if (!_backPress || DID_FAIL(_backPress->loadFile((char *)params))) { + delete _backPress; + _backPress = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BACK_DISABLE: + delete _backDisable; + _backDisable = new UITiledImage(_gameRef); + if (!_backDisable || DID_FAIL(_backDisable->loadFile((char *)params))) { + delete _backDisable; + _backDisable = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BACK_FOCUS: + delete _backFocus; + _backFocus = new UITiledImage(_gameRef); + if (!_backFocus || DID_FAIL(_backFocus->loadFile((char *)params))) { + delete _backFocus; + _backFocus = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new BaseSprite(_gameRef); + if (!_image || DID_FAIL(_image->loadFile((char *)params))) { + delete _image; + _image = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_HOVER: + delete _imageHover; + _imageHover = new BaseSprite(_gameRef); + if (!_imageHover || DID_FAIL(_imageHover->loadFile((char *)params))) { + delete _imageHover; + _imageHover = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_PRESS: + delete _imagePress; + _imagePress = new BaseSprite(_gameRef); + if (!_imagePress || DID_FAIL(_imagePress->loadFile((char *)params))) { + delete _imagePress; + _imagePress = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_DISABLE: + delete _imageDisable; + _imageDisable = new BaseSprite(_gameRef); + if (!_imageDisable || DID_FAIL(_imageDisable->loadFile((char *)params))) { + delete _imageDisable; + _imageDisable = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_FOCUS: + delete _imageFocus; + _imageFocus = new BaseSprite(_gameRef); + if (!_imageFocus || DID_FAIL(_imageFocus->loadFile((char *)params))) { + delete _imageFocus; + _imageFocus = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT: + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont((char *)params); + if (!_font) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_HOVER: + if (_fontHover) { + _gameRef->_fontStorage->removeFont(_fontHover); + } + _fontHover = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontHover) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_PRESS: + if (_fontPress) { + _gameRef->_fontStorage->removeFont(_fontPress); + } + _fontPress = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontPress) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_DISABLE: + if (_fontDisable) { + _gameRef->_fontStorage->removeFont(_fontDisable); + } + _fontDisable = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontDisable) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_FOCUS: + if (_fontFocus) { + _gameRef->_fontStorage->removeFont(_fontFocus); + } + _fontFocus = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontFocus) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_TEXT: + setText((char *)params); + _gameRef->_stringTable->expand(&_text); + break; + + case TOKEN_TEXT_ALIGN: + if (scumm_stricmp((char *)params, "left") == 0) { + _align = TAL_LEFT; + } else if (scumm_stricmp((char *)params, "right") == 0) { + _align = TAL_RIGHT; + } else { + _align = TAL_CENTER; + } + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_WIDTH: + parser.scanStr((char *)params, "%d", &_width); + break; + + case TOKEN_HEIGHT: + parser.scanStr((char *)params, "%d", &_height); + 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_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PARENT_NOTIFY: + parser.scanStr((char *)params, "%b", &_parentNotify); + break; + + case TOKEN_DISABLED: + parser.scanStr((char *)params, "%b", &_disable); + break; + + case TOKEN_VISIBLE: + parser.scanStr((char *)params, "%b", &_visible); + break; + + case TOKEN_FOCUSABLE: + parser.scanStr((char *)params, "%b", &_canFocus); + break; + + case TOKEN_CENTER_IMAGE: + parser.scanStr((char *)params, "%b", &_centerImage); + break; + + case TOKEN_PRESSED: + parser.scanStr((char *)params, "%b", &_stayPressed); + break; + + case TOKEN_PIXEL_PERFECT: + parser.scanStr((char *)params, "%b", &_pixelPerfect); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in BUTTON definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading BUTTON definition"); + return STATUS_FAILED; + } + + correctSize(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIButton::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "BUTTON\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); + } + if (_backHover && _backHover->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK_HOVER=\"%s\"\n", _backHover->getFilename()); + } + if (_backPress && _backPress->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK_PRESS=\"%s\"\n", _backPress->getFilename()); + } + if (_backDisable && _backDisable->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK_DISABLE=\"%s\"\n", _backDisable->getFilename()); + } + if (_backFocus && _backFocus->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK_FOCUS=\"%s\"\n", _backFocus->getFilename()); + } + + if (_image && _image->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); + } + if (_imageHover && _imageHover->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE_HOVER=\"%s\"\n", _imageHover->getFilename()); + } + if (_imagePress && _imagePress->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE_PRESS=\"%s\"\n", _imagePress->getFilename()); + } + if (_imageDisable && _imageDisable->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE_DISABLE=\"%s\"\n", _imageDisable->getFilename()); + } + if (_imageFocus && _imageFocus->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE_FOCUS=\"%s\"\n", _imageFocus->getFilename()); + } + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + if (_fontHover && _fontHover->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_HOVER=\"%s\"\n", _fontHover->getFilename()); + } + if (_fontPress && _fontPress->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_PRESS=\"%s\"\n", _fontPress->getFilename()); + } + if (_fontDisable && _fontDisable->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_DISABLE=\"%s\"\n", _fontDisable->getFilename()); + } + if (_fontFocus && _fontFocus->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_FOCUS=\"%s\"\n", _fontFocus->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + + buffer->putTextIndent(indent + 2, "\n"); + + if (_text) { + buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); + } + + switch (_align) { + case TAL_LEFT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); + break; + case TAL_RIGHT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); + break; + case TAL_CENTER: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); + break; + default: + warning("UIButton::SaveAsText - unhandled enum"); + break; + } + + buffer->putTextIndent(indent + 2, "\n"); + + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); + buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); + + + buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "FOCUSABLE=%s\n", _canFocus ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "CENTER_IMAGE=%s\n", _centerImage ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PRESSED=%s\n", _stayPressed ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PIXEL_PERFECT=%s\n", _pixelPerfect ? "TRUE" : "FALSE"); + + buffer->putTextIndent(indent + 2, "\n"); + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void UIButton::correctSize() { + Rect32 rect; + + BaseSprite *img = NULL; + if (_image) { + img = _image; + } else if (_imageDisable) { + img = _imageDisable; + } else if (_imageHover) { + img = _imageHover; + } else if (_imagePress) { + img = _imagePress; + } else if (_imageFocus) { + img = _imageFocus; + } + + if (_width <= 0) { + if (img) { + img->getBoundingRect(&rect, 0, 0); + _width = rect.right - rect.left; + } else { + _width = 100; + } + } + + if (_height <= 0) { + if (img) { + img->getBoundingRect(&rect, 0, 0); + _height = rect.bottom - rect.top; + } + } + + if (_text) { + int text_height; + if (_font) { + text_height = _font->getTextHeight((byte *)_text, _width); + } else { + text_height = _gameRef->_systemFont->getTextHeight((byte *)_text, _width); + } + + if (text_height > _height) { + _height = text_height; + } + } + + if (_height <= 0) { + _height = 100; + } + + if (_back) { + _back->correctSize(&_width, &_height); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIButton::display(int offsetX, int offsetY) { + if (!_visible) { + return STATUS_OK; + } + + UITiledImage *back = NULL; + BaseSprite *image = NULL; + BaseFont *font = 0; + + //RECT rect; + //BasePlatform::setRect(&rect, OffsetX + _posX, OffsetY + _posY, OffsetX+_posX+_width, OffsetY+_posY+_height); + //_hover = (!_disable && BasePlatform::ptInRect(&rect, _gameRef->_mousePos)!=FALSE); + _hover = (!_disable && _gameRef->_activeObject == this && (_gameRef->_interactive || _gameRef->_state == GAME_SEMI_FROZEN)); + + if ((_press && _hover && !_gameRef->_mouseLeftDown) || + (_oneTimePress && g_system->getMillis() - _oneTimePressTime >= 100)) { + press(); + } + + + if (_disable) { + if (_backDisable) { + back = _backDisable; + } + if (_imageDisable) { + image = _imageDisable; + } + if (_text && _fontDisable) { + font = _fontDisable; + } + } else if (_press || _oneTimePress || _stayPressed) { + if (_backPress) { + back = _backPress; + } + if (_imagePress) { + image = _imagePress; + } + if (_text && _fontPress) { + font = _fontPress; + } + } else if (_hover) { + if (_backHover) { + back = _backHover; + } + if (_imageHover) { + image = _imageHover; + } + if (_text && _fontHover) { + font = _fontHover; + } + } else if (_canFocus && isFocused()) { + if (_backFocus) { + back = _backFocus; + } + if (_imageFocus) { + image = _imageFocus; + } + if (_text && _fontFocus) { + font = _fontFocus; + } + } + + if (!back && _back) { + back = _back; + } + if (!image && _image) { + image = _image; + } + if (_text && !font) { + if (_font) { + font = _font; + } else { + font = _gameRef->_systemFont; + } + } + + int imageX = offsetX + _posX; + int imageY = offsetY + _posY; + + if (image && _centerImage) { + Rect32 rc; + image->getBoundingRect(&rc, 0, 0); + imageX += (_width - (rc.right - rc.left)) / 2; + imageY += (_height - (rc.bottom - rc.top)) / 2; + } + + if (back) { + back->display(offsetX + _posX, offsetY + _posY, _width, _height); + } + //if (image) image->Draw(ImageX +((_press||_oneTimePress)&&back?1:0), ImageY +((_press||_oneTimePress)&&back?1:0), NULL); + if (image) { + image->draw(imageX + ((_press || _oneTimePress) && back ? 1 : 0), imageY + ((_press || _oneTimePress) && back ? 1 : 0), _pixelPerfect ? this : NULL); + } + + if (font && _text) { + int text_offset = (_height - font->getTextHeight((byte *)_text, _width)) / 2; + font->drawText((byte *)_text, offsetX + _posX + ((_press || _oneTimePress) ? 1 : 0), offsetY + _posY + text_offset + ((_press || _oneTimePress) ? 1 : 0), _width, _align); + } + + if (!_pixelPerfect || !_image) { + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); + } + + // reset unused sprites + if (_image && _image != image) { + _image->reset(); + } + if (_imageDisable && _imageDisable != image) { + _imageDisable->reset(); + } + if (_imageFocus && _imageFocus != image) { + _imageFocus->reset(); + } + if (_imagePress && _imagePress != image) { + _imagePress->reset(); + } + if (_imageHover && _imageHover != image) { + _imageHover->reset(); + } + + _press = _hover && _gameRef->_mouseLeftDown && _gameRef->_capturedObject == this; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void UIButton::press() { + applyEvent("Press"); + if (_listenerObject) { + _listenerObject->listen(_listenerParamObject, _listenerParamDWORD); + } + if (_parentNotify && _parent) { + _parent->applyEvent(getName()); + } + + _oneTimePress = false; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIButton::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetDisabledFont + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetDisabledFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (_fontDisable) { + _gameRef->_fontStorage->removeFont(_fontDisable); + } + if (val->isNULL()) { + _fontDisable = NULL; + stack->pushBool(true); + } else { + _fontDisable = _gameRef->_fontStorage->addFont(val->getString()); + stack->pushBool(_fontDisable != NULL); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetHoverFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetHoverFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (_fontHover) { + _gameRef->_fontStorage->removeFont(_fontHover); + } + if (val->isNULL()) { + _fontHover = NULL; + stack->pushBool(true); + } else { + _fontHover = _gameRef->_fontStorage->addFont(val->getString()); + stack->pushBool(_fontHover != NULL); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetPressedFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetPressedFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (_fontPress) { + _gameRef->_fontStorage->removeFont(_fontPress); + } + if (val->isNULL()) { + _fontPress = NULL; + stack->pushBool(true); + } else { + _fontPress = _gameRef->_fontStorage->addFont(val->getString()); + stack->pushBool(_fontPress != NULL); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetFocusedFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetFocusedFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (_fontFocus) { + _gameRef->_fontStorage->removeFont(_fontFocus); + } + if (val->isNULL()) { + _fontFocus = NULL; + stack->pushBool(true); + } else { + _fontFocus = _gameRef->_fontStorage->addFont(val->getString()); + stack->pushBool(_fontFocus != NULL); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetDisabledImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetDisabledImage") == 0) { + stack->correctParams(1); + + delete _imageDisable; + _imageDisable = new BaseSprite(_gameRef); + const char *filename = stack->pop()->getString(); + if (!_imageDisable || DID_FAIL(_imageDisable->loadFile(filename))) { + delete _imageDisable; + _imageDisable = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetDisabledImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetDisabledImage") == 0) { + stack->correctParams(0); + if (!_imageDisable || !_imageDisable->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_imageDisable->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetDisabledImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetDisabledImageObject") == 0) { + stack->correctParams(0); + if (!_imageDisable) { + stack->pushNULL(); + } else { + stack->pushNative(_imageDisable, true); + } + + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // SetHoverImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetHoverImage") == 0) { + stack->correctParams(1); + + delete _imageHover; + _imageHover = new BaseSprite(_gameRef); + const char *filename = stack->pop()->getString(); + if (!_imageHover || DID_FAIL(_imageHover->loadFile(filename))) { + delete _imageHover; + _imageHover = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverImage") == 0) { + stack->correctParams(0); + if (!_imageHover || !_imageHover->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_imageHover->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetHoverImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetHoverImageObject") == 0) { + stack->correctParams(0); + if (!_imageHover) { + stack->pushNULL(); + } else { + stack->pushNative(_imageHover, true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetPressedImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetPressedImage") == 0) { + stack->correctParams(1); + + delete _imagePress; + _imagePress = new BaseSprite(_gameRef); + const char *filename = stack->pop()->getString(); + if (!_imagePress || DID_FAIL(_imagePress->loadFile(filename))) { + delete _imagePress; + _imagePress = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetPressedImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetPressedImage") == 0) { + stack->correctParams(0); + if (!_imagePress || !_imagePress->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_imagePress->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetPressedImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetPressedImageObject") == 0) { + stack->correctParams(0); + if (!_imagePress) { + stack->pushNULL(); + } else { + stack->pushNative(_imagePress, true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetFocusedImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetFocusedImage") == 0) { + stack->correctParams(1); + + delete _imageFocus; + _imageFocus = new BaseSprite(_gameRef); + const char *filename = stack->pop()->getString(); + if (!_imageFocus || DID_FAIL(_imageFocus->loadFile(filename))) { + delete _imageFocus; + _imageFocus = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFocusedImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFocusedImage") == 0) { + stack->correctParams(0); + if (!_imageFocus || !_imageFocus->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_imageFocus->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetFocusedImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetFocusedImageObject") == 0) { + stack->correctParams(0); + if (!_imageFocus) { + stack->pushNULL(); + } else { + stack->pushNative(_imageFocus, true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Press + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Press") == 0) { + stack->correctParams(0); + + if (_visible && !_disable) { + _oneTimePress = true; + _oneTimePressTime = g_system->getMillis(); + } + stack->pushNULL(); + + return STATUS_OK; + } else { + return UIObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIButton::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("button"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TextAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TextAlign") == 0) { + _scValue->setInt(_align); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Focusable + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Focusable") == 0) { + _scValue->setBool(_canFocus); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // Pressed + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Pressed") == 0) { + _scValue->setBool(_stayPressed); + return _scValue; + } + ////////////////////////////////////////////////////////////////////////// + // PixelPerfect + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PixelPerfect") == 0) { + _scValue->setBool(_pixelPerfect); + return _scValue; + } else { + return UIObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIButton::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // TextAlign + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "TextAlign") == 0) { + int i = value->getInt(); + if (i < 0 || i >= NUM_TEXT_ALIGN) { + i = 0; + } + _align = (TTextAlign)i; + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Focusable + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Focusable") == 0) { + _canFocus = value->getBool(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // Pressed + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Pressed") == 0) { + _stayPressed = value->getBool(); + return STATUS_OK; + } + ////////////////////////////////////////////////////////////////////////// + // PixelPerfect + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PixelPerfect") == 0) { + _pixelPerfect = value->getBool(); + return STATUS_OK; + } else { + return UIObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIButton::scToString() { + return "[button]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIButton::persist(BasePersistenceManager *persistMgr) { + + UIObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER_INT(_align)); + persistMgr->transfer(TMEMBER(_backDisable)); + persistMgr->transfer(TMEMBER(_backFocus)); + persistMgr->transfer(TMEMBER(_backHover)); + persistMgr->transfer(TMEMBER(_backPress)); + persistMgr->transfer(TMEMBER(_centerImage)); + persistMgr->transfer(TMEMBER(_fontDisable)); + persistMgr->transfer(TMEMBER(_fontFocus)); + persistMgr->transfer(TMEMBER(_fontHover)); + persistMgr->transfer(TMEMBER(_fontPress)); + persistMgr->transfer(TMEMBER(_hover)); + persistMgr->transfer(TMEMBER(_image)); + persistMgr->transfer(TMEMBER(_imageDisable)); + persistMgr->transfer(TMEMBER(_imageFocus)); + persistMgr->transfer(TMEMBER(_imageHover)); + persistMgr->transfer(TMEMBER(_imagePress)); + persistMgr->transfer(TMEMBER(_pixelPerfect)); + persistMgr->transfer(TMEMBER(_press)); + persistMgr->transfer(TMEMBER(_stayPressed)); + + if (!persistMgr->getIsSaving()) { + _oneTimePress = false; + _oneTimePressTime = 0; + } + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_button.h b/engines/wintermute/ui/ui_button.h index 88ba8dafc74a..9342f766cca5 100644 --- a/engines/wintermute/ui/ui_button.h +++ b/engines/wintermute/ui/ui_button.h @@ -1,80 +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 WINTERMUTE_UIBUTTON_H -#define WINTERMUTE_UIBUTTON_H - - -#include "engines/wintermute/ui/ui_object.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView - -namespace Wintermute { - -class UIButton : public UIObject { -public: - bool _pixelPerfect; - bool _stayPressed; - bool _centerImage; - bool _oneTimePress; - uint32 _oneTimePressTime; - DECLARE_PERSISTENT(UIButton, UIObject) - void press(); - virtual bool display() { return display(0, 0); } - virtual bool display(int offsetX, int offsetY); - bool _press; - bool _hover; - void correctSize(); - TTextAlign _align; - BaseSprite *_imageHover; - BaseSprite *_imagePress; - BaseSprite *_imageDisable; - BaseSprite *_imageFocus; - BaseFont *_fontDisable; - BaseFont *_fontPress; - BaseFont *_fontHover; - BaseFont *_fontFocus; - UITiledImage *_backPress; - UITiledImage *_backHover; - UITiledImage *_backDisable; - UITiledImage *_backFocus; - UIButton(BaseGame *inGame = NULL); - virtual ~UIButton(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual 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 +/* 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_UIBUTTON_H +#define WINTERMUTE_UIBUTTON_H + + +#include "engines/wintermute/ui/ui_object.h" +#include "engines/wintermute/dctypes.h" // Added by ClassView + +namespace Wintermute { + +class UIButton : public UIObject { +public: + bool _pixelPerfect; + bool _stayPressed; + bool _centerImage; + bool _oneTimePress; + uint32 _oneTimePressTime; + DECLARE_PERSISTENT(UIButton, UIObject) + void press(); + virtual bool display() { return display(0, 0); } + virtual bool display(int offsetX, int offsetY); + bool _press; + bool _hover; + void correctSize(); + TTextAlign _align; + BaseSprite *_imageHover; + BaseSprite *_imagePress; + BaseSprite *_imageDisable; + BaseSprite *_imageFocus; + BaseFont *_fontDisable; + BaseFont *_fontPress; + BaseFont *_fontHover; + BaseFont *_fontFocus; + UITiledImage *_backPress; + UITiledImage *_backHover; + UITiledImage *_backDisable; + UITiledImage *_backFocus; + UIButton(BaseGame *inGame = NULL); + virtual ~UIButton(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual 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/ui/ui_edit.cpp b/engines/wintermute/ui/ui_edit.cpp index 2ea44cd64c04..94d11255ce22 100644 --- a/engines/wintermute/ui/ui_edit.cpp +++ b/engines/wintermute/ui/ui_edit.cpp @@ -1,951 +1,951 @@ -/* 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/ui/ui_edit.h" -#include "engines/wintermute/ui/ui_object.h" -#include "engines/wintermute/ui/ui_tiled_image.h" -#include "engines/wintermute/utils/string_util.h" -#include "engines/wintermute/base/base_active_rect.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/base_keyboard_state.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/utils/utils.h" -#include "common/util.h" -#include "common/keyboard.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(UIEdit, false) - -////////////////////////////////////////////////////////////////////////// -UIEdit::UIEdit(BaseGame *inGame) : UIObject(inGame) { - _type = UI_EDIT; - - _fontSelected = NULL; - - _selStart = _selEnd = 10000; - _scrollOffset = 0; - - _cursorChar = NULL; - setCursorChar("|"); - - _cursorBlinkRate = 600; - - _frameWidth = 0; - - setText(""); - - _lastBlinkTime = 0; - _cursorVisible = true; - - _maxLength = -1; - - _canFocus = true; -} - - -////////////////////////////////////////////////////////////////////////// -UIEdit::~UIEdit() { - if (!_sharedFonts) { - if (_fontSelected) { - _gameRef->_fontStorage->removeFont(_fontSelected); - } - } - - delete[] _cursorChar; - _cursorChar = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UIEdit::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 EDIT file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(DISABLED) -TOKEN_DEF(VISIBLE) -TOKEN_DEF(BACK) -TOKEN_DEF(IMAGE) -TOKEN_DEF(FONT_SELECTED) -TOKEN_DEF(FONT) -TOKEN_DEF(TEXT) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(WIDTH) -TOKEN_DEF(HEIGHT) -TOKEN_DEF(CURSOR_BLINK_RATE) -TOKEN_DEF(CURSOR) -TOKEN_DEF(FRAME_WIDTH) -TOKEN_DEF(NAME) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(PARENT_NOTIFY) -TOKEN_DEF(MAX_LENGTH) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(EDIT) -TOKEN_DEF(CAPTION) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UIEdit::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(DISABLED) - TOKEN_TABLE(VISIBLE) - TOKEN_TABLE(BACK) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(FONT_SELECTED) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TEXT) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(WIDTH) - TOKEN_TABLE(HEIGHT) - TOKEN_TABLE(CURSOR_BLINK_RATE) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(FRAME_WIDTH) - TOKEN_TABLE(NAME) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(PARENT_NOTIFY) - TOKEN_TABLE(MAX_LENGTH) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(EDIT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_EDIT) { - _gameRef->LOG(0, "'EDIT' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: - delete _back; - _back = new UITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new BaseSprite(_gameRef); - if (!_image || DID_FAIL(_image->loadFile((char *)params))) { - delete _image; - _image = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT: - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont((char *)params); - if (!_font) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_SELECTED: - if (_fontSelected) { - _gameRef->_fontStorage->removeFont(_fontSelected); - } - _fontSelected = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontSelected) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_TEXT: - setText((char *)params); - _gameRef->_stringTable->expand(&_text); - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_WIDTH: - parser.scanStr((char *)params, "%d", &_width); - break; - - case TOKEN_HEIGHT: - parser.scanStr((char *)params, "%d", &_height); - break; - - case TOKEN_MAX_LENGTH: - parser.scanStr((char *)params, "%d", &_maxLength); - break; - - case TOKEN_CAPTION: - setCaption((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_CURSOR_BLINK_RATE: - parser.scanStr((char *)params, "%d", &_cursorBlinkRate); - break; - - case TOKEN_FRAME_WIDTH: - parser.scanStr((char *)params, "%d", &_frameWidth); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PARENT_NOTIFY: - parser.scanStr((char *)params, "%b", &_parentNotify); - break; - - case TOKEN_DISABLED: - parser.scanStr((char *)params, "%b", &_disable); - break; - - case TOKEN_VISIBLE: - parser.scanStr((char *)params, "%b", &_visible); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in EDIT definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading EDIT definition"); - return STATUS_FAILED; - } - - correctSize(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "EDIT\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); - } - - if (_image && _image->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); - } - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - if (_fontSelected && _fontSelected->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - buffer->putTextIndent(indent + 2, "\n"); - - if (_text) { - buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); - } - - buffer->putTextIndent(indent + 2, "\n"); - - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); - buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); - buffer->putTextIndent(indent + 2, "MAX_LENGTH=%d\n", _maxLength); - buffer->putTextIndent(indent + 2, "CURSOR_BLINK_RATE=%d\n", _cursorBlinkRate); - buffer->putTextIndent(indent + 2, "FRAME_WIDTH=%d\n", _frameWidth); - - buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIEdit::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetSelectedFont - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetSelectedFont") == 0) { - stack->correctParams(1); - - if (_fontSelected) { - _gameRef->_fontStorage->removeFont(_fontSelected); - } - _fontSelected = _gameRef->_fontStorage->addFont(stack->pop()->getString()); - stack->pushBool(_fontSelected != NULL); - - return STATUS_OK; - } else { - return UIObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIEdit::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("editor"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SelStart - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SelStart") == 0) { - _scValue->setInt(_selStart); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SelEnd - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SelEnd") == 0) { - _scValue->setInt(_selEnd); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorBlinkRate - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorBlinkRate") == 0) { - _scValue->setInt(_cursorBlinkRate); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorChar - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorChar") == 0) { - _scValue->setString(_cursorChar); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // FrameWidth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FrameWidth") == 0) { - _scValue->setInt(_frameWidth); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // MaxLength - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxLength") == 0) { - _scValue->setInt(_maxLength); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Text - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Text") == 0) { - if (_gameRef->_textEncoding == TEXT_UTF8) { - WideString wstr = StringUtil::ansiToWide(_text); - _scValue->setString(StringUtil::wideToUtf8(wstr).c_str()); - } else { - _scValue->setString(_text); - } - return _scValue; - } else { - return UIObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // SelStart - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SelStart") == 0) { - _selStart = value->getInt(); - _selStart = MAX(_selStart, 0); - _selStart = (int)MIN((size_t)_selStart, strlen(_text)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SelEnd - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SelEnd") == 0) { - _selEnd = value->getInt(); - _selEnd = MAX(_selEnd, 0); - _selEnd = (int)MIN((size_t)_selEnd, strlen(_text)); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorBlinkRate - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorBlinkRate") == 0) { - _cursorBlinkRate = (uint32)value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CursorChar - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CursorChar") == 0) { - setCursorChar(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // FrameWidth - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FrameWidth") == 0) { - _frameWidth = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MaxLength - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MaxLength") == 0) { - _maxLength = value->getInt(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Text - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Text") == 0) { - if (_gameRef->_textEncoding == TEXT_UTF8) { - WideString wstr = StringUtil::utf8ToWide(value->getString()); - setText(StringUtil::wideToAnsi(wstr).c_str()); - } else { - setText(value->getString()); - } - return STATUS_OK; - } else { - return UIObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIEdit::scToString() { - return "[edit]"; -} - - -////////////////////////////////////////////////////////////////////////// -void UIEdit::setCursorChar(const char *character) { - if (!character) { - return; - } - delete[] _cursorChar; - _cursorChar = new char [strlen(character) + 1]; - if (_cursorChar) { - strcpy(_cursorChar, character); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::display(int offsetX, int offsetY) { - if (!_visible) { - return STATUS_OK; - } - - - // hack! - TTextEncoding OrigEncoding = _gameRef->_textEncoding; - _gameRef->_textEncoding = TEXT_ANSI; - - if (_back) { - _back->display(offsetX + _posX, offsetY + _posY, _width, _height); - } - if (_image) { - _image->draw(offsetX + _posX, offsetY + _posY, NULL); - } - - // prepare fonts - BaseFont *font; - BaseFont *sfont; - - if (_font) { - font = _font; - } else { - font = _gameRef->_systemFont; - } - - if (_fontSelected) { - sfont = _fontSelected; - } else { - sfont = font; - } - - bool focused = isFocused(); - - _selStart = MAX(_selStart, 0); - _selEnd = MAX(_selEnd, 0); - - _selStart = (int)MIN((size_t)_selStart, strlen(_text)); - _selEnd = (int)MIN((size_t)_selEnd, strlen(_text)); - - //int CursorWidth = font->GetCharWidth(_cursorChar[0]); - int cursorWidth = font->getTextWidth((byte *)_cursorChar); - - int s1, s2; - bool curFirst; - // modify scroll offset - if (_selStart >= _selEnd) { - while (font->getTextWidth((byte *)_text + _scrollOffset, MAX(0, _selEnd - _scrollOffset)) > _width - cursorWidth - 2 * _frameWidth) { - _scrollOffset++; - if (_scrollOffset >= (int)strlen(_text)) { - break; - } - } - - _scrollOffset = MIN(_scrollOffset, _selEnd); - - s1 = _selEnd; - s2 = _selStart; - curFirst = true; - } else { - while (font->getTextWidth((byte *)_text + _scrollOffset, MAX(0, _selStart - _scrollOffset)) + - sfont->getTextWidth((byte *)(_text + MAX(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart)) - - > _width - cursorWidth - 2 * _frameWidth) { - _scrollOffset++; - if (_scrollOffset >= (int)strlen(_text)) { - break; - } - } - - _scrollOffset = MIN(_scrollOffset, _selEnd); - - s1 = _selStart; - s2 = _selEnd; - curFirst = false; - } - - - int alignOffset = 0; - - for (int count = 0; count < 2; count++) { - // draw text - int xxx, yyy, width, height; - - xxx = _posX + _frameWidth + offsetX; - yyy = _posY + _frameWidth + offsetY; - - width = _posX + _width + offsetX - _frameWidth; - height = MAX(font->getLetterHeight(), sfont->getLetterHeight()); - - if (_gameRef->_textRTL) { - xxx += alignOffset; - } - - TTextAlign align = TAL_LEFT; - - - // unselected 1 - if (s1 > _scrollOffset) { - if (count) { - font->drawText((byte *)_text + _scrollOffset, xxx, yyy, width - xxx, align, height, s1 - _scrollOffset); - } - xxx += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset); - alignOffset += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset); - } - - // cursor - if (focused && curFirst) { - if (count) { - if (g_system->getMillis() - _lastBlinkTime >= _cursorBlinkRate) { - _lastBlinkTime = g_system->getMillis(); - _cursorVisible = !_cursorVisible; - } - if (_cursorVisible) { - font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1); - } - } - xxx += cursorWidth; - alignOffset += cursorWidth; - } - - // selected - int s3 = MAX(s1, _scrollOffset); - - if (s2 - s3 > 0) { - if (count) { - sfont->drawText((byte *)_text + s3, xxx, yyy, width - xxx, align, height, s2 - s3); - } - xxx += sfont->getTextWidth((byte *)_text + s3, s2 - s3); - alignOffset += sfont->getTextWidth((byte *)_text + s3, s2 - s3); - } - - // cursor - if (focused && !curFirst) { - if (count) { - if (g_system->getMillis() - _lastBlinkTime >= _cursorBlinkRate) { - _lastBlinkTime = g_system->getMillis(); - _cursorVisible = !_cursorVisible; - } - if (_cursorVisible) { - font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1); - } - } - xxx += cursorWidth; - alignOffset += cursorWidth; - } - - // unselected 2 - if (count) { - font->drawText((byte *)_text + s2, xxx, yyy, width - xxx, align, height); - } - alignOffset += font->getTextWidth((byte *)_text + s2); - - alignOffset = (_width - 2 * _frameWidth) - alignOffset; - if (alignOffset < 0) { - alignOffset = 0; - } - } - - - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); - - - _gameRef->_textEncoding = OrigEncoding; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::handleKeypress(Common::Event *event, bool printable) { - bool handled = false; - - if (event->type == Common::EVENT_KEYDOWN && !printable) { - switch (event->kbd.keycode) { - case Common::KEYCODE_ESCAPE: - case Common::KEYCODE_TAB: - case Common::KEYCODE_RETURN: - return false; - - // ctrl+A - case Common::KEYCODE_a: - if (BaseKeyboardState::isControlDown()) { - _selStart = 0; - _selEnd = strlen(_text); - handled = true; - } - break; - - case Common::KEYCODE_BACKSPACE: - if (_selStart == _selEnd) { - if (_gameRef->_textRTL) { - deleteChars(_selStart, _selStart + 1); - } else { - deleteChars(_selStart - 1, _selStart); - } - } else { - deleteChars(_selStart, _selEnd); - } - if (_selEnd >= _selStart) { - _selEnd -= MAX(1, _selEnd - _selStart); - } - _selStart = _selEnd; - - handled = true; - break; - - case Common::KEYCODE_LEFT: - case Common::KEYCODE_UP: - _selEnd--; - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - handled = true; - break; - - case Common::KEYCODE_RIGHT: - case Common::KEYCODE_DOWN: - _selEnd++; - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - handled = true; - break; - - case Common::KEYCODE_HOME: - if (_gameRef->_textRTL) { - _selEnd = strlen(_text); - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - } else { - _selEnd = 0; - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - } - handled = true; - break; - - case Common::KEYCODE_END: - if (_gameRef->_textRTL) { - _selEnd = 0; - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - } else { - _selEnd = strlen(_text); - if (!BaseKeyboardState::isShiftDown()) { - _selStart = _selEnd; - } - } - handled = true; - break; - - case Common::KEYCODE_DELETE: - if (_selStart == _selEnd) { - if (_gameRef->_textRTL) { - deleteChars(_selStart - 1, _selStart); - _selEnd--; - if (_selEnd < 0) { - _selEnd = 0; - } - } else { - deleteChars(_selStart, _selStart + 1); - } - } else { - deleteChars(_selStart, _selEnd); - } - if (_selEnd > _selStart) { - _selEnd -= (_selEnd - _selStart); - } - - _selStart = _selEnd; - handled = true; - break; - default: - break; - } - return handled; - } else if (event->type == Common::EVENT_KEYDOWN && printable) { - if (_selStart != _selEnd) { - deleteChars(_selStart, _selEnd); - } - - //WideString wstr = StringUtil::Utf8ToWide(event->kbd.ascii); - WideString wstr; - wstr += (char)event->kbd.ascii; - _selEnd += insertChars(_selEnd, (const byte *)StringUtil::wideToAnsi(wstr).c_str(), 1); - - if (_gameRef->_textRTL) { - _selEnd = _selStart; - } else { - _selStart = _selEnd; - } - - return true; - } - - return false; -} - - - -////////////////////////////////////////////////////////////////////////// -int UIEdit::deleteChars(int start, int end) { - if (start > end) { - BaseUtils::swap(&start, &end); - } - - start = MAX(start, (int)0); - end = MIN((size_t)end, strlen(_text)); - - char *str = new char[strlen(_text) - (end - start) + 1]; - if (str) { - if (start > 0) { - memcpy(str, _text, start); - } - memcpy(str + MAX(0, start), _text + end, strlen(_text) - end + 1); - - delete[] _text; - _text = str; - } - if (_parentNotify && _parent) { - _parent->applyEvent(getName()); - } - - return end - start; -} - - -////////////////////////////////////////////////////////////////////////// -int UIEdit::insertChars(int pos, const byte *chars, int num) { - if ((int)strlen(_text) + num > _maxLength) { - num -= (strlen(_text) + num - _maxLength); - } - - pos = MAX(pos, (int)0); - pos = MIN((size_t)pos, strlen(_text)); - - char *str = new char[strlen(_text) + num + 1]; - if (str) { - if (pos > 0) { - memcpy(str, _text, pos); - } - memcpy(str + pos + num, _text + pos, strlen(_text) - pos + 1); - - memcpy(str + pos, chars, num); - - delete[] _text; - _text = str; - } - if (_parentNotify && _parent) { - _parent->applyEvent(getName()); - } - - return num; -} - - - -////////////////////////////////////////////////////////////////////////// -bool UIEdit::persist(BasePersistenceManager *persistMgr) { - - UIObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_cursorBlinkRate)); - persistMgr->transfer(TMEMBER(_cursorChar)); - persistMgr->transfer(TMEMBER(_fontSelected)); - persistMgr->transfer(TMEMBER(_frameWidth)); - persistMgr->transfer(TMEMBER(_maxLength)); - persistMgr->transfer(TMEMBER(_scrollOffset)); - persistMgr->transfer(TMEMBER(_selEnd)); - persistMgr->transfer(TMEMBER(_selStart)); - - if (!persistMgr->getIsSaving()) { - _cursorVisible = false; - _lastBlinkTime = 0; - } - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ui/ui_edit.h" +#include "engines/wintermute/ui/ui_object.h" +#include "engines/wintermute/ui/ui_tiled_image.h" +#include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/base/base_active_rect.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/base_keyboard_state.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/utils/utils.h" +#include "common/util.h" +#include "common/keyboard.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(UIEdit, false) + +////////////////////////////////////////////////////////////////////////// +UIEdit::UIEdit(BaseGame *inGame) : UIObject(inGame) { + _type = UI_EDIT; + + _fontSelected = NULL; + + _selStart = _selEnd = 10000; + _scrollOffset = 0; + + _cursorChar = NULL; + setCursorChar("|"); + + _cursorBlinkRate = 600; + + _frameWidth = 0; + + setText(""); + + _lastBlinkTime = 0; + _cursorVisible = true; + + _maxLength = -1; + + _canFocus = true; +} + + +////////////////////////////////////////////////////////////////////////// +UIEdit::~UIEdit() { + if (!_sharedFonts) { + if (_fontSelected) { + _gameRef->_fontStorage->removeFont(_fontSelected); + } + } + + delete[] _cursorChar; + _cursorChar = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UIEdit::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 EDIT file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(DISABLED) +TOKEN_DEF(VISIBLE) +TOKEN_DEF(BACK) +TOKEN_DEF(IMAGE) +TOKEN_DEF(FONT_SELECTED) +TOKEN_DEF(FONT) +TOKEN_DEF(TEXT) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(WIDTH) +TOKEN_DEF(HEIGHT) +TOKEN_DEF(CURSOR_BLINK_RATE) +TOKEN_DEF(CURSOR) +TOKEN_DEF(FRAME_WIDTH) +TOKEN_DEF(NAME) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(PARENT_NOTIFY) +TOKEN_DEF(MAX_LENGTH) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(EDIT) +TOKEN_DEF(CAPTION) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UIEdit::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(DISABLED) + TOKEN_TABLE(VISIBLE) + TOKEN_TABLE(BACK) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(FONT_SELECTED) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TEXT) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(WIDTH) + TOKEN_TABLE(HEIGHT) + TOKEN_TABLE(CURSOR_BLINK_RATE) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(FRAME_WIDTH) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(PARENT_NOTIFY) + TOKEN_TABLE(MAX_LENGTH) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(EDIT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_EDIT) { + _gameRef->LOG(0, "'EDIT' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: + delete _back; + _back = new UITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new BaseSprite(_gameRef); + if (!_image || DID_FAIL(_image->loadFile((char *)params))) { + delete _image; + _image = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT: + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont((char *)params); + if (!_font) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_SELECTED: + if (_fontSelected) { + _gameRef->_fontStorage->removeFont(_fontSelected); + } + _fontSelected = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontSelected) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_TEXT: + setText((char *)params); + _gameRef->_stringTable->expand(&_text); + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_WIDTH: + parser.scanStr((char *)params, "%d", &_width); + break; + + case TOKEN_HEIGHT: + parser.scanStr((char *)params, "%d", &_height); + break; + + case TOKEN_MAX_LENGTH: + parser.scanStr((char *)params, "%d", &_maxLength); + break; + + case TOKEN_CAPTION: + setCaption((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_CURSOR_BLINK_RATE: + parser.scanStr((char *)params, "%d", &_cursorBlinkRate); + break; + + case TOKEN_FRAME_WIDTH: + parser.scanStr((char *)params, "%d", &_frameWidth); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PARENT_NOTIFY: + parser.scanStr((char *)params, "%b", &_parentNotify); + break; + + case TOKEN_DISABLED: + parser.scanStr((char *)params, "%b", &_disable); + break; + + case TOKEN_VISIBLE: + parser.scanStr((char *)params, "%b", &_visible); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in EDIT definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading EDIT definition"); + return STATUS_FAILED; + } + + correctSize(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "EDIT\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); + } + + if (_image && _image->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); + } + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + if (_fontSelected && _fontSelected->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_SELECTED=\"%s\"\n", _fontSelected->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + buffer->putTextIndent(indent + 2, "\n"); + + if (_text) { + buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); + } + + buffer->putTextIndent(indent + 2, "\n"); + + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); + buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); + buffer->putTextIndent(indent + 2, "MAX_LENGTH=%d\n", _maxLength); + buffer->putTextIndent(indent + 2, "CURSOR_BLINK_RATE=%d\n", _cursorBlinkRate); + buffer->putTextIndent(indent + 2, "FRAME_WIDTH=%d\n", _frameWidth); + + buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIEdit::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetSelectedFont + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetSelectedFont") == 0) { + stack->correctParams(1); + + if (_fontSelected) { + _gameRef->_fontStorage->removeFont(_fontSelected); + } + _fontSelected = _gameRef->_fontStorage->addFont(stack->pop()->getString()); + stack->pushBool(_fontSelected != NULL); + + return STATUS_OK; + } else { + return UIObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIEdit::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("editor"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SelStart + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SelStart") == 0) { + _scValue->setInt(_selStart); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SelEnd + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SelEnd") == 0) { + _scValue->setInt(_selEnd); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorBlinkRate + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorBlinkRate") == 0) { + _scValue->setInt(_cursorBlinkRate); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorChar + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorChar") == 0) { + _scValue->setString(_cursorChar); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // FrameWidth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FrameWidth") == 0) { + _scValue->setInt(_frameWidth); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // MaxLength + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxLength") == 0) { + _scValue->setInt(_maxLength); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Text + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Text") == 0) { + if (_gameRef->_textEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::ansiToWide(_text); + _scValue->setString(StringUtil::wideToUtf8(wstr).c_str()); + } else { + _scValue->setString(_text); + } + return _scValue; + } else { + return UIObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // SelStart + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SelStart") == 0) { + _selStart = value->getInt(); + _selStart = MAX(_selStart, 0); + _selStart = (int)MIN((size_t)_selStart, strlen(_text)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SelEnd + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SelEnd") == 0) { + _selEnd = value->getInt(); + _selEnd = MAX(_selEnd, 0); + _selEnd = (int)MIN((size_t)_selEnd, strlen(_text)); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorBlinkRate + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorBlinkRate") == 0) { + _cursorBlinkRate = (uint32)value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CursorChar + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CursorChar") == 0) { + setCursorChar(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FrameWidth + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FrameWidth") == 0) { + _frameWidth = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MaxLength + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MaxLength") == 0) { + _maxLength = value->getInt(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Text + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Text") == 0) { + if (_gameRef->_textEncoding == TEXT_UTF8) { + WideString wstr = StringUtil::utf8ToWide(value->getString()); + setText(StringUtil::wideToAnsi(wstr).c_str()); + } else { + setText(value->getString()); + } + return STATUS_OK; + } else { + return UIObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIEdit::scToString() { + return "[edit]"; +} + + +////////////////////////////////////////////////////////////////////////// +void UIEdit::setCursorChar(const char *character) { + if (!character) { + return; + } + delete[] _cursorChar; + _cursorChar = new char [strlen(character) + 1]; + if (_cursorChar) { + strcpy(_cursorChar, character); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::display(int offsetX, int offsetY) { + if (!_visible) { + return STATUS_OK; + } + + + // hack! + TTextEncoding OrigEncoding = _gameRef->_textEncoding; + _gameRef->_textEncoding = TEXT_ANSI; + + if (_back) { + _back->display(offsetX + _posX, offsetY + _posY, _width, _height); + } + if (_image) { + _image->draw(offsetX + _posX, offsetY + _posY, NULL); + } + + // prepare fonts + BaseFont *font; + BaseFont *sfont; + + if (_font) { + font = _font; + } else { + font = _gameRef->_systemFont; + } + + if (_fontSelected) { + sfont = _fontSelected; + } else { + sfont = font; + } + + bool focused = isFocused(); + + _selStart = MAX(_selStart, 0); + _selEnd = MAX(_selEnd, 0); + + _selStart = (int)MIN((size_t)_selStart, strlen(_text)); + _selEnd = (int)MIN((size_t)_selEnd, strlen(_text)); + + //int CursorWidth = font->GetCharWidth(_cursorChar[0]); + int cursorWidth = font->getTextWidth((byte *)_cursorChar); + + int s1, s2; + bool curFirst; + // modify scroll offset + if (_selStart >= _selEnd) { + while (font->getTextWidth((byte *)_text + _scrollOffset, MAX(0, _selEnd - _scrollOffset)) > _width - cursorWidth - 2 * _frameWidth) { + _scrollOffset++; + if (_scrollOffset >= (int)strlen(_text)) { + break; + } + } + + _scrollOffset = MIN(_scrollOffset, _selEnd); + + s1 = _selEnd; + s2 = _selStart; + curFirst = true; + } else { + while (font->getTextWidth((byte *)_text + _scrollOffset, MAX(0, _selStart - _scrollOffset)) + + sfont->getTextWidth((byte *)(_text + MAX(_scrollOffset, _selStart)), _selEnd - MAX(_scrollOffset, _selStart)) + + > _width - cursorWidth - 2 * _frameWidth) { + _scrollOffset++; + if (_scrollOffset >= (int)strlen(_text)) { + break; + } + } + + _scrollOffset = MIN(_scrollOffset, _selEnd); + + s1 = _selStart; + s2 = _selEnd; + curFirst = false; + } + + + int alignOffset = 0; + + for (int count = 0; count < 2; count++) { + // draw text + int xxx, yyy, width, height; + + xxx = _posX + _frameWidth + offsetX; + yyy = _posY + _frameWidth + offsetY; + + width = _posX + _width + offsetX - _frameWidth; + height = MAX(font->getLetterHeight(), sfont->getLetterHeight()); + + if (_gameRef->_textRTL) { + xxx += alignOffset; + } + + TTextAlign align = TAL_LEFT; + + + // unselected 1 + if (s1 > _scrollOffset) { + if (count) { + font->drawText((byte *)_text + _scrollOffset, xxx, yyy, width - xxx, align, height, s1 - _scrollOffset); + } + xxx += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset); + alignOffset += font->getTextWidth((byte *)_text + _scrollOffset, s1 - _scrollOffset); + } + + // cursor + if (focused && curFirst) { + if (count) { + if (g_system->getMillis() - _lastBlinkTime >= _cursorBlinkRate) { + _lastBlinkTime = g_system->getMillis(); + _cursorVisible = !_cursorVisible; + } + if (_cursorVisible) { + font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1); + } + } + xxx += cursorWidth; + alignOffset += cursorWidth; + } + + // selected + int s3 = MAX(s1, _scrollOffset); + + if (s2 - s3 > 0) { + if (count) { + sfont->drawText((byte *)_text + s3, xxx, yyy, width - xxx, align, height, s2 - s3); + } + xxx += sfont->getTextWidth((byte *)_text + s3, s2 - s3); + alignOffset += sfont->getTextWidth((byte *)_text + s3, s2 - s3); + } + + // cursor + if (focused && !curFirst) { + if (count) { + if (g_system->getMillis() - _lastBlinkTime >= _cursorBlinkRate) { + _lastBlinkTime = g_system->getMillis(); + _cursorVisible = !_cursorVisible; + } + if (_cursorVisible) { + font->drawText((byte *)_cursorChar, xxx, yyy, width - xxx, align, height, 1); + } + } + xxx += cursorWidth; + alignOffset += cursorWidth; + } + + // unselected 2 + if (count) { + font->drawText((byte *)_text + s2, xxx, yyy, width - xxx, align, height); + } + alignOffset += font->getTextWidth((byte *)_text + s2); + + alignOffset = (_width - 2 * _frameWidth) - alignOffset; + if (alignOffset < 0) { + alignOffset = 0; + } + } + + + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, offsetX + _posX, offsetY + _posY, _width, _height, 100, 100, false)); + + + _gameRef->_textEncoding = OrigEncoding; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::handleKeypress(Common::Event *event, bool printable) { + bool handled = false; + + if (event->type == Common::EVENT_KEYDOWN && !printable) { + switch (event->kbd.keycode) { + case Common::KEYCODE_ESCAPE: + case Common::KEYCODE_TAB: + case Common::KEYCODE_RETURN: + return false; + + // ctrl+A + case Common::KEYCODE_a: + if (BaseKeyboardState::isControlDown()) { + _selStart = 0; + _selEnd = strlen(_text); + handled = true; + } + break; + + case Common::KEYCODE_BACKSPACE: + if (_selStart == _selEnd) { + if (_gameRef->_textRTL) { + deleteChars(_selStart, _selStart + 1); + } else { + deleteChars(_selStart - 1, _selStart); + } + } else { + deleteChars(_selStart, _selEnd); + } + if (_selEnd >= _selStart) { + _selEnd -= MAX(1, _selEnd - _selStart); + } + _selStart = _selEnd; + + handled = true; + break; + + case Common::KEYCODE_LEFT: + case Common::KEYCODE_UP: + _selEnd--; + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + handled = true; + break; + + case Common::KEYCODE_RIGHT: + case Common::KEYCODE_DOWN: + _selEnd++; + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + handled = true; + break; + + case Common::KEYCODE_HOME: + if (_gameRef->_textRTL) { + _selEnd = strlen(_text); + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + } else { + _selEnd = 0; + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + } + handled = true; + break; + + case Common::KEYCODE_END: + if (_gameRef->_textRTL) { + _selEnd = 0; + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + } else { + _selEnd = strlen(_text); + if (!BaseKeyboardState::isShiftDown()) { + _selStart = _selEnd; + } + } + handled = true; + break; + + case Common::KEYCODE_DELETE: + if (_selStart == _selEnd) { + if (_gameRef->_textRTL) { + deleteChars(_selStart - 1, _selStart); + _selEnd--; + if (_selEnd < 0) { + _selEnd = 0; + } + } else { + deleteChars(_selStart, _selStart + 1); + } + } else { + deleteChars(_selStart, _selEnd); + } + if (_selEnd > _selStart) { + _selEnd -= (_selEnd - _selStart); + } + + _selStart = _selEnd; + handled = true; + break; + default: + break; + } + return handled; + } else if (event->type == Common::EVENT_KEYDOWN && printable) { + if (_selStart != _selEnd) { + deleteChars(_selStart, _selEnd); + } + + //WideString wstr = StringUtil::Utf8ToWide(event->kbd.ascii); + WideString wstr; + wstr += (char)event->kbd.ascii; + _selEnd += insertChars(_selEnd, (const byte *)StringUtil::wideToAnsi(wstr).c_str(), 1); + + if (_gameRef->_textRTL) { + _selEnd = _selStart; + } else { + _selStart = _selEnd; + } + + return true; + } + + return false; +} + + + +////////////////////////////////////////////////////////////////////////// +int UIEdit::deleteChars(int start, int end) { + if (start > end) { + BaseUtils::swap(&start, &end); + } + + start = MAX(start, (int)0); + end = MIN((size_t)end, strlen(_text)); + + char *str = new char[strlen(_text) - (end - start) + 1]; + if (str) { + if (start > 0) { + memcpy(str, _text, start); + } + memcpy(str + MAX(0, start), _text + end, strlen(_text) - end + 1); + + delete[] _text; + _text = str; + } + if (_parentNotify && _parent) { + _parent->applyEvent(getName()); + } + + return end - start; +} + + +////////////////////////////////////////////////////////////////////////// +int UIEdit::insertChars(int pos, const byte *chars, int num) { + if ((int)strlen(_text) + num > _maxLength) { + num -= (strlen(_text) + num - _maxLength); + } + + pos = MAX(pos, (int)0); + pos = MIN((size_t)pos, strlen(_text)); + + char *str = new char[strlen(_text) + num + 1]; + if (str) { + if (pos > 0) { + memcpy(str, _text, pos); + } + memcpy(str + pos + num, _text + pos, strlen(_text) - pos + 1); + + memcpy(str + pos, chars, num); + + delete[] _text; + _text = str; + } + if (_parentNotify && _parent) { + _parent->applyEvent(getName()); + } + + return num; +} + + + +////////////////////////////////////////////////////////////////////////// +bool UIEdit::persist(BasePersistenceManager *persistMgr) { + + UIObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_cursorBlinkRate)); + persistMgr->transfer(TMEMBER(_cursorChar)); + persistMgr->transfer(TMEMBER(_fontSelected)); + persistMgr->transfer(TMEMBER(_frameWidth)); + persistMgr->transfer(TMEMBER(_maxLength)); + persistMgr->transfer(TMEMBER(_scrollOffset)); + persistMgr->transfer(TMEMBER(_selEnd)); + persistMgr->transfer(TMEMBER(_selStart)); + + if (!persistMgr->getIsSaving()) { + _cursorVisible = false; + _lastBlinkTime = 0; + } + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_edit.h b/engines/wintermute/ui/ui_edit.h index fa760951b046..610629afb3d9 100644 --- a/engines/wintermute/ui/ui_edit.h +++ b/engines/wintermute/ui/ui_edit.h @@ -1,72 +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_UIEDIT_H -#define WINTERMUTE_UIEDIT_H - -#include "engines/wintermute/persistent.h" -#include "engines/wintermute/ui/ui_object.h" -#include "common/events.h" - -namespace Wintermute { -class BaseFont; -class UIEdit : public UIObject { -public: - DECLARE_PERSISTENT(UIEdit, UIObject) - int _maxLength; - int insertChars(int pos, const byte *chars, int num); - int deleteChars(int start, int end); - bool _cursorVisible; - uint32 _lastBlinkTime; - virtual bool display(int offsetX, int offsetY); - virtual bool handleKeypress(Common::Event *event, bool printable = false); - int _scrollOffset; - int _frameWidth; - uint32 _cursorBlinkRate; - void setCursorChar(const char *character); - char *_cursorChar; - int _selEnd; - int _selStart; - BaseFont *_fontSelected; - UIEdit(BaseGame *inGame); - virtual ~UIEdit(); - - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual 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 +/* 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_UIEDIT_H +#define WINTERMUTE_UIEDIT_H + +#include "engines/wintermute/persistent.h" +#include "engines/wintermute/ui/ui_object.h" +#include "common/events.h" + +namespace Wintermute { +class BaseFont; +class UIEdit : public UIObject { +public: + DECLARE_PERSISTENT(UIEdit, UIObject) + int _maxLength; + int insertChars(int pos, const byte *chars, int num); + int deleteChars(int start, int end); + bool _cursorVisible; + uint32 _lastBlinkTime; + virtual bool display(int offsetX, int offsetY); + virtual bool handleKeypress(Common::Event *event, bool printable = false); + int _scrollOffset; + int _frameWidth; + uint32 _cursorBlinkRate; + void setCursorChar(const char *character); + char *_cursorChar; + int _selEnd; + int _selStart; + BaseFont *_fontSelected; + UIEdit(BaseGame *inGame); + virtual ~UIEdit(); + + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual 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/ui/ui_entity.cpp b/engines/wintermute/ui/ui_entity.cpp index 18a4db124a04..c49cb5a24063 100644 --- a/engines/wintermute/ui/ui_entity.cpp +++ b/engines/wintermute/ui/ui_entity.cpp @@ -1,366 +1,366 @@ -/* 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_entity.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/ui/ui_entity.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_dynamic_buffer.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(UIEntity, false) - -////////////////////////////////////////////////////////////////////////// -UIEntity::UIEntity(BaseGame *inGame) : UIObject(inGame) { - _type = UI_CUSTOM; - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -UIEntity::~UIEntity() { - if (_entity) { - _gameRef->unregisterObject(_entity); - } - _entity = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UIEntity::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 ENTITY container file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(ENTITY_CONTAINER) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(DISABLED) -TOKEN_DEF(VISIBLE) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(NAME) -TOKEN_DEF(ENTITY) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UIEntity::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(ENTITY_CONTAINER) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(DISABLED) - TOKEN_TABLE(VISIBLE) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(NAME) - TOKEN_TABLE(ENTITY) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY_CONTAINER) { - _gameRef->LOG(0, "'ENTITY_CONTAINER' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_DISABLED: - parser.scanStr((char *)params, "%b", &_disable); - break; - - case TOKEN_VISIBLE: - parser.scanStr((char *)params, "%b", &_visible); - break; - - case TOKEN_ENTITY: - if (DID_FAIL(setEntity((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in ENTITY_CONTAINER definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading ENTITY_CONTAINER definition"); - return STATUS_FAILED; - } - - correctSize(); - - if (_gameRef->_editorMode) { - _width = 50; - _height = 50; - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "ENTITY_CONTAINER\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - - buffer->putTextIndent(indent + 2, "\n"); - - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - - buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - - if (_entity && _entity->getFilename()) { - buffer->putTextIndent(indent + 2, "ENTITY=\"%s\"\n", _entity->getFilename()); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::setEntity(const char *filename) { - if (_entity) { - _gameRef->unregisterObject(_entity); - } - _entity = new AdEntity(_gameRef); - if (!_entity || DID_FAIL(_entity->loadFile(filename))) { - delete _entity; - _entity = NULL; - return STATUS_FAILED; - } else { - _entity->_nonIntMouseEvents = true; - _entity->_sceneIndependent = true; - _entity->makeFreezable(false); - _gameRef->registerObject(_entity); - } - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::display(int offsetX, int offsetY) { - if (!_visible) { - return STATUS_OK; - } - - if (_entity) { - _entity->_posX = offsetX + _posX; - _entity->_posY = offsetY + _posY; - if (_entity->_scale < 0) { - _entity->_zoomable = false; - } - _entity->_shadowable = false; - - _entity->update(); - - bool origReg = _entity->_registrable; - - if (_entity->_registrable && _disable) { - _entity->_registrable = false; - } - - _entity->display(); - _entity->_registrable = origReg; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetEntity - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetEntity") == 0) { - stack->correctParams(0); - - if (_entity) { - stack->pushNative(_entity, true); - } else { - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetEntity - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetEntity") == 0) { - stack->correctParams(1); - - const char *filename = stack->pop()->getString(); - - if (DID_SUCCEED(setEntity(filename))) { - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } else { - return UIObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIEntity::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("entity container"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Freezable - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Freezable") == 0) { - if (_entity) { - _scValue->setBool(_entity->_freezable); - } else { - _scValue->setBool(false); - } - return _scValue; - } else { - return UIObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Freezable - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Freezable") == 0) { - if (_entity) { - _entity->makeFreezable(value->getBool()); - } - return STATUS_OK; - } else { - return UIObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIEntity::scToString() { - return "[entity container]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIEntity::persist(BasePersistenceManager *persistMgr) { - - UIObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_entity)); - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_entity.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/ui/ui_entity.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_dynamic_buffer.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(UIEntity, false) + +////////////////////////////////////////////////////////////////////////// +UIEntity::UIEntity(BaseGame *inGame) : UIObject(inGame) { + _type = UI_CUSTOM; + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +UIEntity::~UIEntity() { + if (_entity) { + _gameRef->unregisterObject(_entity); + } + _entity = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UIEntity::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 ENTITY container file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(ENTITY_CONTAINER) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(DISABLED) +TOKEN_DEF(VISIBLE) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(NAME) +TOKEN_DEF(ENTITY) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UIEntity::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(ENTITY_CONTAINER) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(DISABLED) + TOKEN_TABLE(VISIBLE) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(NAME) + TOKEN_TABLE(ENTITY) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_ENTITY_CONTAINER) { + _gameRef->LOG(0, "'ENTITY_CONTAINER' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_DISABLED: + parser.scanStr((char *)params, "%b", &_disable); + break; + + case TOKEN_VISIBLE: + parser.scanStr((char *)params, "%b", &_visible); + break; + + case TOKEN_ENTITY: + if (DID_FAIL(setEntity((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in ENTITY_CONTAINER definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading ENTITY_CONTAINER definition"); + return STATUS_FAILED; + } + + correctSize(); + + if (_gameRef->_editorMode) { + _width = 50; + _height = 50; + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "ENTITY_CONTAINER\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + + buffer->putTextIndent(indent + 2, "\n"); + + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + + buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + + if (_entity && _entity->getFilename()) { + buffer->putTextIndent(indent + 2, "ENTITY=\"%s\"\n", _entity->getFilename()); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::setEntity(const char *filename) { + if (_entity) { + _gameRef->unregisterObject(_entity); + } + _entity = new AdEntity(_gameRef); + if (!_entity || DID_FAIL(_entity->loadFile(filename))) { + delete _entity; + _entity = NULL; + return STATUS_FAILED; + } else { + _entity->_nonIntMouseEvents = true; + _entity->_sceneIndependent = true; + _entity->makeFreezable(false); + _gameRef->registerObject(_entity); + } + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::display(int offsetX, int offsetY) { + if (!_visible) { + return STATUS_OK; + } + + if (_entity) { + _entity->_posX = offsetX + _posX; + _entity->_posY = offsetY + _posY; + if (_entity->_scale < 0) { + _entity->_zoomable = false; + } + _entity->_shadowable = false; + + _entity->update(); + + bool origReg = _entity->_registrable; + + if (_entity->_registrable && _disable) { + _entity->_registrable = false; + } + + _entity->display(); + _entity->_registrable = origReg; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIEntity::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetEntity + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetEntity") == 0) { + stack->correctParams(0); + + if (_entity) { + stack->pushNative(_entity, true); + } else { + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetEntity + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetEntity") == 0) { + stack->correctParams(1); + + const char *filename = stack->pop()->getString(); + + if (DID_SUCCEED(setEntity(filename))) { + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } else { + return UIObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIEntity::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("entity container"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Freezable + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Freezable") == 0) { + if (_entity) { + _scValue->setBool(_entity->_freezable); + } else { + _scValue->setBool(false); + } + return _scValue; + } else { + return UIObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Freezable + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Freezable") == 0) { + if (_entity) { + _entity->makeFreezable(value->getBool()); + } + return STATUS_OK; + } else { + return UIObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIEntity::scToString() { + return "[entity container]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIEntity::persist(BasePersistenceManager *persistMgr) { + + UIObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_entity)); + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_entity.h b/engines/wintermute/ui/ui_entity.h index aeb32a6ffb74..3bf8068fd5ef 100644 --- a/engines/wintermute/ui/ui_entity.h +++ b/engines/wintermute/ui/ui_entity.h @@ -1,59 +1,59 @@ -/* 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_UIENTITY_H -#define WINTERMUTE_UIENTITY_H - -#include "engines/wintermute/ui/ui_object.h" - -namespace Wintermute { -class AdEntity; -class UIEntity : public UIObject { -public: - DECLARE_PERSISTENT(UIEntity, UIObject) - UIEntity(BaseGame *inGame); - virtual ~UIEntity(); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - - virtual bool display() { return display(0, 0); } - virtual bool display(int offsetX, int offsetY); - AdEntity *_entity; - bool setEntity(const char *filename); - - // 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 +/* 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_UIENTITY_H +#define WINTERMUTE_UIENTITY_H + +#include "engines/wintermute/ui/ui_object.h" + +namespace Wintermute { +class AdEntity; +class UIEntity : public UIObject { +public: + DECLARE_PERSISTENT(UIEntity, UIObject) + UIEntity(BaseGame *inGame); + virtual ~UIEntity(); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + + virtual bool display() { return display(0, 0); } + virtual bool display(int offsetX, int offsetY); + AdEntity *_entity; + bool setEntity(const char *filename); + + // 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/ui/ui_object.cpp b/engines/wintermute/ui/ui_object.cpp index 716570fd67a6..85e381c55b1f 100644 --- a/engines/wintermute/ui/ui_object.cpp +++ b/engines/wintermute/ui/ui_object.cpp @@ -1,650 +1,650 @@ -/* 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/base_sprite.h" -#include "engines/wintermute/ui/ui_object.h" -#include "engines/wintermute/ui/ui_tiled_image.h" -#include "engines/wintermute/ui/ui_window.h" -#include "engines/wintermute/platform_osystem.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/font/base_font_storage.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(UIObject, false) - -////////////////////////////////////////////////////////////////////////// -UIObject::UIObject(BaseGame *inGame) : BaseObject(inGame) { - _back = NULL; - _image = NULL; - _font = NULL; - _text = NULL; - _sharedFonts = _sharedImages = false; - - _width = _height = 0; - - _listenerObject = NULL; - _listenerParamObject = NULL; - _listenerParamDWORD = 0; - - _disable = false; - _visible = true; - - _type = UI_UNKNOWN; - _parent = NULL; - - _parentNotify = false; - - _focusedWidget = NULL; - - _canFocus = false; - _nonIntMouseEvents = true; -} - - -////////////////////////////////////////////////////////////////////////// -UIObject::~UIObject() { - if (!_gameRef->_loadInProgress) { - SystemClassRegistry::getInstance()->enumInstances(BaseGame::invalidateValues, "ScValue", (void *)this); - } - - if (_back) { - delete _back; - } - if (_font && !_sharedFonts) { - _gameRef->_fontStorage->removeFont(_font); - } - - if (_image && !_sharedImages) { - delete _image; - } - - if (_text) { - delete[] _text; - } - - _focusedWidget = NULL; // ref only -} - - -////////////////////////////////////////////////////////////////////////// -void UIObject::setText(const char *text) { - if (_text) { - delete[] _text; - } - _text = new char [strlen(text) + 1]; - if (_text) { - strcpy(_text, text); - for (uint32 i = 0; i < strlen(_text); i++) { - if (_text[i] == '|') { - _text[i] = '\n'; - } - } - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::display(int offsetX, int offsetY) { - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void UIObject::setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam) { - _listenerObject = object; - _listenerParamObject = listenerObject; - _listenerParamDWORD = listenerParam; -} - - -////////////////////////////////////////////////////////////////////////// -void UIObject::correctSize() { - Rect32 rect; - - if (_width <= 0) { - if (_image) { - _image->getBoundingRect(&rect, 0, 0); - _width = rect.right - rect.left; - } else { - _width = 100; - } - } - - if (_height <= 0) { - if (_image) { - _image->getBoundingRect(&rect, 0, 0); - _height = rect.bottom - rect.top; - } - } - - if (_back) { - _back->correctSize(&_width, &_height); - } -} - - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SetFont - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SetFont") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - if (val->isNULL()) { - _font = NULL; - stack->pushBool(true); - } else { - _font = _gameRef->_fontStorage->addFont(val->getString()); - stack->pushBool(_font != NULL); - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetImage") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - /* const char *filename = */ val->getString(); - - delete _image; - _image = NULL; - if (val->isNULL()) { - stack->pushBool(true); - return STATUS_OK; - } - - _image = new BaseSprite(_gameRef); - if (!_image || DID_FAIL(_image->loadFile(val->getString()))) { - delete _image; - _image = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetImage") == 0) { - stack->correctParams(0); - if (!_image || !_image->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_image->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetImageObject") == 0) { - stack->correctParams(0); - if (!_image) { - stack->pushNULL(); - } else { - stack->pushNative(_image, true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Focus - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Focus") == 0) { - stack->correctParams(0); - focus(); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MoveAfter / MoveBefore - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MoveAfter") == 0 || strcmp(name, "MoveBefore") == 0) { - stack->correctParams(1); - - if (_parent && _parent->_type == UI_WINDOW) { - UIWindow *win = (UIWindow *)_parent; - - uint32 i; - bool found = false; - ScValue *val = stack->pop(); - // find directly - if (val->isNative()) { - UIObject *widget = (UIObject *)val->getNative(); - for (i = 0; i < win->_widgets.size(); i++) { - if (win->_widgets[i] == widget) { - found = true; - break; - } - } - } - // find by name - else { - const char *findName = val->getString(); - for (i = 0; i < win->_widgets.size(); i++) { - if (scumm_stricmp(win->_widgets[i]->getName(), findName) == 0) { - found = true; - break; - } - } - } - - if (found) { - bool done = false; - for (uint32 j = 0; j < win->_widgets.size(); j++) { - if (win->_widgets[j] == this) { - if (strcmp(name, "MoveAfter") == 0) { - i++; - } - if (j >= i) { - j++; - } - - win->_widgets.insert_at(i, this); - win->_widgets.remove_at(j); - - done = true; - stack->pushBool(true); - break; - } - } - if (!done) { - stack->pushBool(false); - } - } else { - stack->pushBool(false); - } - - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MoveToBottom - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MoveToBottom") == 0) { - stack->correctParams(0); - - if (_parent && _parent->_type == UI_WINDOW) { - UIWindow *win = (UIWindow *)_parent; - for (uint32 i = 0; i < win->_widgets.size(); i++) { - if (win->_widgets[i] == this) { - win->_widgets.remove_at(i); - win->_widgets.insert_at(0, this); - break; - } - } - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // MoveToTop - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "MoveToTop") == 0) { - stack->correctParams(0); - - if (_parent && _parent->_type == UI_WINDOW) { - UIWindow *win = (UIWindow *)_parent; - for (uint32 i = 0; i < win->_widgets.size(); i++) { - if (win->_widgets[i] == this) { - win->_widgets.remove_at(i); - win->_widgets.add(this); - break; - } - } - stack->pushBool(true); - } else { - stack->pushBool(false); - } - - return STATUS_OK; - } else { - return BaseObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIObject::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("ui_object"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Name") == 0) { - _scValue->setString(getName()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Parent (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Parent") == 0) { - _scValue->setNative(_parent, true); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ParentNotify - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ParentNotify") == 0) { - _scValue->setBool(_parentNotify); - 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; - } - - ////////////////////////////////////////////////////////////////////////// - // Visible - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Visible") == 0) { - _scValue->setBool(_visible); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Disabled - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Disabled") == 0) { - _scValue->setBool(_disable); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Text - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Text") == 0) { - _scValue->setString(_text); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NextSibling (RO) / PrevSibling (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NextSibling") == 0 || strcmp(name, "PrevSibling") == 0) { - _scValue->setNULL(); - if (_parent && _parent->_type == UI_WINDOW) { - UIWindow *win = (UIWindow *)_parent; - for (uint32 i = 0; i < win->_widgets.size(); i++) { - if (win->_widgets[i] == this) { - if (strcmp(name, "NextSibling") == 0) { - if (i < win->_widgets.size() - 1) { - _scValue->setNative(win->_widgets[i + 1], true); - } - } else { - if (i > 0) { - _scValue->setNative(win->_widgets[i - 1], true); - } - } - break; - } - } - } - return _scValue; - } else { - return BaseObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ParentNotify - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ParentNotify") == 0) { - _parentNotify = value->getBool(); - 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; - } - - ////////////////////////////////////////////////////////////////////////// - // Visible - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Visible") == 0) { - _visible = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Disabled - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Disabled") == 0) { - _disable = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Text - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Text") == 0) { - setText(value->getString()); - return STATUS_OK; - } else { - return BaseObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIObject::scToString() { - return "[ui_object]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::isFocused() { - if (!_gameRef->_focusedWindow) { - return false; - } - if (_gameRef->_focusedWindow == this) { - return true; - } - - UIObject *obj = _gameRef->_focusedWindow; - while (obj) { - if (obj == this) { - return true; - } else { - obj = obj->_focusedWidget; - } - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::handleMouse(TMouseEvent event, TMouseButton button) { - // handle focus change - if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { - focus(); - } - return BaseObject::handleMouse(event, button); -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::focus() { - UIObject *obj = this; - bool disabled = false; - while (obj) { - if (obj->_disable && obj->_type == UI_WINDOW) { - disabled = true; - break; - } - obj = obj->_parent; - } - if (!disabled) { - obj = this; - while (obj) { - if (obj->_parent) { - if (!obj->_disable && obj->_canFocus) { - obj->_parent->_focusedWidget = obj; - } - } else { - if (obj->_type == UI_WINDOW) { - _gameRef->focusWindow((UIWindow *)obj); - } - } - - obj = obj->_parent; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::getTotalOffset(int *offsetX, int *offsetY) { - int offX = 0, offY = 0; - - UIObject *obj = _parent; - while (obj) { - offX += obj->_posX; - offY += obj->_posY; - - obj = obj->_parent; - } - if (offsetX) { - *offsetX = offX; - } - if (offsetY) { - *offsetY = offY; - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIObject::persist(BasePersistenceManager *persistMgr) { - - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_back)); - persistMgr->transfer(TMEMBER(_canFocus)); - persistMgr->transfer(TMEMBER(_disable)); - persistMgr->transfer(TMEMBER(_focusedWidget)); - persistMgr->transfer(TMEMBER(_font)); - persistMgr->transfer(TMEMBER(_height)); - persistMgr->transfer(TMEMBER(_image)); - persistMgr->transfer(TMEMBER(_listenerObject)); - persistMgr->transfer(TMEMBER(_listenerParamObject)); - persistMgr->transfer(TMEMBER(_listenerParamDWORD)); - persistMgr->transfer(TMEMBER(_parent)); - persistMgr->transfer(TMEMBER(_parentNotify)); - persistMgr->transfer(TMEMBER(_sharedFonts)); - persistMgr->transfer(TMEMBER(_sharedImages)); - persistMgr->transfer(TMEMBER(_text)); - persistMgr->transfer(TMEMBER_INT(_type)); - persistMgr->transfer(TMEMBER(_visible)); - persistMgr->transfer(TMEMBER(_width)); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIObject::saveAsText(BaseDynamicBuffer *buffer, int indent) { - return STATUS_FAILED; -} - -} // end of namespace Wintermute +/* 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/base_sprite.h" +#include "engines/wintermute/ui/ui_object.h" +#include "engines/wintermute/ui/ui_tiled_image.h" +#include "engines/wintermute/ui/ui_window.h" +#include "engines/wintermute/platform_osystem.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/font/base_font_storage.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(UIObject, false) + +////////////////////////////////////////////////////////////////////////// +UIObject::UIObject(BaseGame *inGame) : BaseObject(inGame) { + _back = NULL; + _image = NULL; + _font = NULL; + _text = NULL; + _sharedFonts = _sharedImages = false; + + _width = _height = 0; + + _listenerObject = NULL; + _listenerParamObject = NULL; + _listenerParamDWORD = 0; + + _disable = false; + _visible = true; + + _type = UI_UNKNOWN; + _parent = NULL; + + _parentNotify = false; + + _focusedWidget = NULL; + + _canFocus = false; + _nonIntMouseEvents = true; +} + + +////////////////////////////////////////////////////////////////////////// +UIObject::~UIObject() { + if (!_gameRef->_loadInProgress) { + SystemClassRegistry::getInstance()->enumInstances(BaseGame::invalidateValues, "ScValue", (void *)this); + } + + if (_back) { + delete _back; + } + if (_font && !_sharedFonts) { + _gameRef->_fontStorage->removeFont(_font); + } + + if (_image && !_sharedImages) { + delete _image; + } + + if (_text) { + delete[] _text; + } + + _focusedWidget = NULL; // ref only +} + + +////////////////////////////////////////////////////////////////////////// +void UIObject::setText(const char *text) { + if (_text) { + delete[] _text; + } + _text = new char [strlen(text) + 1]; + if (_text) { + strcpy(_text, text); + for (uint32 i = 0; i < strlen(_text); i++) { + if (_text[i] == '|') { + _text[i] = '\n'; + } + } + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::display(int offsetX, int offsetY) { + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void UIObject::setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam) { + _listenerObject = object; + _listenerParamObject = listenerObject; + _listenerParamDWORD = listenerParam; +} + + +////////////////////////////////////////////////////////////////////////// +void UIObject::correctSize() { + Rect32 rect; + + if (_width <= 0) { + if (_image) { + _image->getBoundingRect(&rect, 0, 0); + _width = rect.right - rect.left; + } else { + _width = 100; + } + } + + if (_height <= 0) { + if (_image) { + _image->getBoundingRect(&rect, 0, 0); + _height = rect.bottom - rect.top; + } + } + + if (_back) { + _back->correctSize(&_width, &_height); + } +} + + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIObject::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SetFont + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SetFont") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + if (val->isNULL()) { + _font = NULL; + stack->pushBool(true); + } else { + _font = _gameRef->_fontStorage->addFont(val->getString()); + stack->pushBool(_font != NULL); + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetImage") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + /* const char *filename = */ val->getString(); + + delete _image; + _image = NULL; + if (val->isNULL()) { + stack->pushBool(true); + return STATUS_OK; + } + + _image = new BaseSprite(_gameRef); + if (!_image || DID_FAIL(_image->loadFile(val->getString()))) { + delete _image; + _image = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetImage") == 0) { + stack->correctParams(0); + if (!_image || !_image->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_image->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetImageObject") == 0) { + stack->correctParams(0); + if (!_image) { + stack->pushNULL(); + } else { + stack->pushNative(_image, true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Focus + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Focus") == 0) { + stack->correctParams(0); + focus(); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveAfter / MoveBefore + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MoveAfter") == 0 || strcmp(name, "MoveBefore") == 0) { + stack->correctParams(1); + + if (_parent && _parent->_type == UI_WINDOW) { + UIWindow *win = (UIWindow *)_parent; + + uint32 i; + bool found = false; + ScValue *val = stack->pop(); + // find directly + if (val->isNative()) { + UIObject *widget = (UIObject *)val->getNative(); + for (i = 0; i < win->_widgets.size(); i++) { + if (win->_widgets[i] == widget) { + found = true; + break; + } + } + } + // find by name + else { + const char *findName = val->getString(); + for (i = 0; i < win->_widgets.size(); i++) { + if (scumm_stricmp(win->_widgets[i]->getName(), findName) == 0) { + found = true; + break; + } + } + } + + if (found) { + bool done = false; + for (uint32 j = 0; j < win->_widgets.size(); j++) { + if (win->_widgets[j] == this) { + if (strcmp(name, "MoveAfter") == 0) { + i++; + } + if (j >= i) { + j++; + } + + win->_widgets.insert_at(i, this); + win->_widgets.remove_at(j); + + done = true; + stack->pushBool(true); + break; + } + } + if (!done) { + stack->pushBool(false); + } + } else { + stack->pushBool(false); + } + + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveToBottom + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MoveToBottom") == 0) { + stack->correctParams(0); + + if (_parent && _parent->_type == UI_WINDOW) { + UIWindow *win = (UIWindow *)_parent; + for (uint32 i = 0; i < win->_widgets.size(); i++) { + if (win->_widgets[i] == this) { + win->_widgets.remove_at(i); + win->_widgets.insert_at(0, this); + break; + } + } + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // MoveToTop + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "MoveToTop") == 0) { + stack->correctParams(0); + + if (_parent && _parent->_type == UI_WINDOW) { + UIWindow *win = (UIWindow *)_parent; + for (uint32 i = 0; i < win->_widgets.size(); i++) { + if (win->_widgets[i] == this) { + win->_widgets.remove_at(i); + win->_widgets.add(this); + break; + } + } + stack->pushBool(true); + } else { + stack->pushBool(false); + } + + return STATUS_OK; + } else { + return BaseObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIObject::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("ui_object"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Name") == 0) { + _scValue->setString(getName()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Parent (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Parent") == 0) { + _scValue->setNative(_parent, true); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ParentNotify + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ParentNotify") == 0) { + _scValue->setBool(_parentNotify); + 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; + } + + ////////////////////////////////////////////////////////////////////////// + // Visible + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Visible") == 0) { + _scValue->setBool(_visible); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Disabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Disabled") == 0) { + _scValue->setBool(_disable); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Text + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Text") == 0) { + _scValue->setString(_text); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NextSibling (RO) / PrevSibling (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NextSibling") == 0 || strcmp(name, "PrevSibling") == 0) { + _scValue->setNULL(); + if (_parent && _parent->_type == UI_WINDOW) { + UIWindow *win = (UIWindow *)_parent; + for (uint32 i = 0; i < win->_widgets.size(); i++) { + if (win->_widgets[i] == this) { + if (strcmp(name, "NextSibling") == 0) { + if (i < win->_widgets.size() - 1) { + _scValue->setNative(win->_widgets[i + 1], true); + } + } else { + if (i > 0) { + _scValue->setNative(win->_widgets[i - 1], true); + } + } + break; + } + } + } + return _scValue; + } else { + return BaseObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ParentNotify + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ParentNotify") == 0) { + _parentNotify = value->getBool(); + 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; + } + + ////////////////////////////////////////////////////////////////////////// + // Visible + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Visible") == 0) { + _visible = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Disabled + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Disabled") == 0) { + _disable = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Text + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Text") == 0) { + setText(value->getString()); + return STATUS_OK; + } else { + return BaseObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIObject::scToString() { + return "[ui_object]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::isFocused() { + if (!_gameRef->_focusedWindow) { + return false; + } + if (_gameRef->_focusedWindow == this) { + return true; + } + + UIObject *obj = _gameRef->_focusedWindow; + while (obj) { + if (obj == this) { + return true; + } else { + obj = obj->_focusedWidget; + } + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::handleMouse(TMouseEvent event, TMouseButton button) { + // handle focus change + if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { + focus(); + } + return BaseObject::handleMouse(event, button); +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::focus() { + UIObject *obj = this; + bool disabled = false; + while (obj) { + if (obj->_disable && obj->_type == UI_WINDOW) { + disabled = true; + break; + } + obj = obj->_parent; + } + if (!disabled) { + obj = this; + while (obj) { + if (obj->_parent) { + if (!obj->_disable && obj->_canFocus) { + obj->_parent->_focusedWidget = obj; + } + } else { + if (obj->_type == UI_WINDOW) { + _gameRef->focusWindow((UIWindow *)obj); + } + } + + obj = obj->_parent; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::getTotalOffset(int *offsetX, int *offsetY) { + int offX = 0, offY = 0; + + UIObject *obj = _parent; + while (obj) { + offX += obj->_posX; + offY += obj->_posY; + + obj = obj->_parent; + } + if (offsetX) { + *offsetX = offX; + } + if (offsetY) { + *offsetY = offY; + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIObject::persist(BasePersistenceManager *persistMgr) { + + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_back)); + persistMgr->transfer(TMEMBER(_canFocus)); + persistMgr->transfer(TMEMBER(_disable)); + persistMgr->transfer(TMEMBER(_focusedWidget)); + persistMgr->transfer(TMEMBER(_font)); + persistMgr->transfer(TMEMBER(_height)); + persistMgr->transfer(TMEMBER(_image)); + persistMgr->transfer(TMEMBER(_listenerObject)); + persistMgr->transfer(TMEMBER(_listenerParamObject)); + persistMgr->transfer(TMEMBER(_listenerParamDWORD)); + persistMgr->transfer(TMEMBER(_parent)); + persistMgr->transfer(TMEMBER(_parentNotify)); + persistMgr->transfer(TMEMBER(_sharedFonts)); + persistMgr->transfer(TMEMBER(_sharedImages)); + persistMgr->transfer(TMEMBER(_text)); + persistMgr->transfer(TMEMBER_INT(_type)); + persistMgr->transfer(TMEMBER(_visible)); + persistMgr->transfer(TMEMBER(_width)); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIObject::saveAsText(BaseDynamicBuffer *buffer, int indent) { + return STATUS_FAILED; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_object.h b/engines/wintermute/ui/ui_object.h index b0a34fe61ed2..81c025d33b6c 100644 --- a/engines/wintermute/ui/ui_object.h +++ b/engines/wintermute/ui/ui_object.h @@ -1,85 +1,85 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_UIOBJECT_H -#define WINTERMUTE_UIOBJECT_H - - -#include "engines/wintermute/base/base_object.h" -#include "engines/wintermute/dctypes.h" // Added by ClassView - -namespace Wintermute { - -class UITiledImage; -class BaseFont; -class UIObject : public BaseObject { -public: - - bool getTotalOffset(int *offsetX, int *offsetY); - bool _canFocus; - bool focus(); - virtual bool handleMouse(TMouseEvent event, TMouseButton button); - bool isFocused(); - bool _parentNotify; - DECLARE_PERSISTENT(UIObject, BaseObject) - UIObject *_parent; - virtual bool display() { return display(0, 0); } - virtual bool display(int offsetX) { return display(offsetX, 0); } - virtual bool display(int offsetX, int offsetY); - virtual void correctSize(); - bool _sharedFonts; - bool _sharedImages; - void setText(const char *text); - char *_text; - BaseFont *_font; - bool _visible; - UITiledImage *_back; - bool _disable; - UIObject(BaseGame *inGame = NULL); - virtual ~UIObject(); - int _width; - int _height; - TUIObjectType _type; - BaseSprite *_image; - void setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam); - BaseScriptHolder *_listenerParamObject; - uint32 _listenerParamDWORD; - BaseScriptHolder *_listenerObject; - UIObject *_focusedWidget; - virtual 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 +/* 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_UIOBJECT_H +#define WINTERMUTE_UIOBJECT_H + + +#include "engines/wintermute/base/base_object.h" +#include "engines/wintermute/dctypes.h" // Added by ClassView + +namespace Wintermute { + +class UITiledImage; +class BaseFont; +class UIObject : public BaseObject { +public: + + bool getTotalOffset(int *offsetX, int *offsetY); + bool _canFocus; + bool focus(); + virtual bool handleMouse(TMouseEvent event, TMouseButton button); + bool isFocused(); + bool _parentNotify; + DECLARE_PERSISTENT(UIObject, BaseObject) + UIObject *_parent; + virtual bool display() { return display(0, 0); } + virtual bool display(int offsetX) { return display(offsetX, 0); } + virtual bool display(int offsetX, int offsetY); + virtual void correctSize(); + bool _sharedFonts; + bool _sharedImages; + void setText(const char *text); + char *_text; + BaseFont *_font; + bool _visible; + UITiledImage *_back; + bool _disable; + UIObject(BaseGame *inGame = NULL); + virtual ~UIObject(); + int _width; + int _height; + TUIObjectType _type; + BaseSprite *_image; + void setListener(BaseScriptHolder *object, BaseScriptHolder *listenerObject, uint32 listenerParam); + BaseScriptHolder *_listenerParamObject; + uint32 _listenerParamDWORD; + BaseScriptHolder *_listenerObject; + UIObject *_focusedWidget; + virtual 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/ui/ui_text.cpp b/engines/wintermute/ui/ui_text.cpp index 86d5c754f137..1844b640d05b 100644 --- a/engines/wintermute/ui/ui_text.cpp +++ b/engines/wintermute/ui/ui_text.cpp @@ -1,522 +1,522 @@ -/* 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_dynamic_buffer.h" -#include "engines/wintermute/ui/ui_text.h" -#include "engines/wintermute/ui/ui_tiled_image.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(UIText, false) - -////////////////////////////////////////////////////////////////////////// -UIText::UIText(BaseGame *inGame) : UIObject(inGame) { - _textAlign = TAL_LEFT; - _verticalAlign = VAL_CENTER; - _type = UI_STATIC; - _canFocus = false; -} - - -////////////////////////////////////////////////////////////////////////// -UIText::~UIText() { - -} - - -////////////////////////////////////////////////////////////////////////// -bool UIText::display(int offsetX, int offsetY) { - if (!_visible) { - return STATUS_OK; - } - - - BaseFont *font = _font; - if (!font) { - font = _gameRef->_systemFont; - } - - if (_back) { - _back->display(offsetX + _posX, offsetY + _posY, _width, _height); - } - if (_image) { - _image->draw(offsetX + _posX, offsetY + _posY, NULL); - } - - if (font && _text) { - int textOffset; - switch (_verticalAlign) { - case VAL_TOP: - textOffset = 0; - break; - case VAL_BOTTOM: - textOffset = _height - font->getTextHeight((byte *)_text, _width); - break; - default: - textOffset = (_height - font->getTextHeight((byte *)_text, _width)) / 2; - } - font->drawText((byte *)_text, offsetX + _posX, offsetY + _posY + textOffset, _width, _textAlign, _height); - } - - //_gameRef->_renderer->_rectList.add(new BaseActiveRect(_gameRef, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false)); - - return STATUS_OK; -} - - - -////////////////////////////////////////////////////////////////////////// -bool UIText::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UIText::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 STATIC file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(STATIC) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(DISABLED) -TOKEN_DEF(VISIBLE) -TOKEN_DEF(BACK) -TOKEN_DEF(IMAGE) -TOKEN_DEF(FONT) -TOKEN_DEF(TEXT_ALIGN) -TOKEN_DEF(VERTICAL_ALIGN) -TOKEN_DEF(TEXT) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(WIDTH) -TOKEN_DEF(HEIGHT) -TOKEN_DEF(CURSOR) -TOKEN_DEF(NAME) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PARENT_NOTIFY) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UIText::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(STATIC) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(DISABLED) - TOKEN_TABLE(VISIBLE) - TOKEN_TABLE(BACK) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TEXT_ALIGN) - TOKEN_TABLE(VERTICAL_ALIGN) - TOKEN_TABLE(TEXT) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(WIDTH) - TOKEN_TABLE(HEIGHT) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(NAME) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PARENT_NOTIFY) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_STATIC) { - _gameRef->LOG(0, "'STATIC' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: - delete _back; - _back = new UITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new BaseSprite(_gameRef); - if (!_image || DID_FAIL(_image->loadFile((char *)params))) { - delete _image; - _image = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT: - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont((char *)params); - if (!_font) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_TEXT: - setText((char *)params); - _gameRef->_stringTable->expand(&_text); - break; - - case TOKEN_TEXT_ALIGN: - if (scumm_stricmp((char *)params, "left") == 0) { - _textAlign = TAL_LEFT; - } else if (scumm_stricmp((char *)params, "right") == 0) { - _textAlign = TAL_RIGHT; - } else { - _textAlign = TAL_CENTER; - } - break; - - case TOKEN_VERTICAL_ALIGN: - if (scumm_stricmp((char *)params, "top") == 0) { - _verticalAlign = VAL_TOP; - } else if (scumm_stricmp((char *)params, "bottom") == 0) { - _verticalAlign = VAL_BOTTOM; - } else { - _verticalAlign = VAL_CENTER; - } - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_WIDTH: - parser.scanStr((char *)params, "%d", &_width); - break; - - case TOKEN_HEIGHT: - parser.scanStr((char *)params, "%d", &_height); - 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_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PARENT_NOTIFY: - parser.scanStr((char *)params, "%b", &_parentNotify); - break; - - case TOKEN_DISABLED: - parser.scanStr((char *)params, "%b", &_disable); - break; - - case TOKEN_VISIBLE: - parser.scanStr((char *)params, "%b", &_visible); - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in STATIC definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading STATIC definition"); - return STATUS_FAILED; - } - - correctSize(); - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIText::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "STATIC\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); - } - - if (_image && _image->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); - } - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - if (_text) { - buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); - } - - switch (_textAlign) { - case TAL_LEFT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); - break; - case TAL_RIGHT: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); - break; - case TAL_CENTER: - buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); - break; - default: - error("UIText::SaveAsText - Unhandled enum"); - break; - } - - switch (_verticalAlign) { - case VAL_TOP: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top"); - break; - case VAL_BOTTOM: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom"); - break; - case VAL_CENTER: - buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center"); - break; - default: - error("UIText::SaveAsText - Unhandled enum value: NUM_VERTICAL_ALIGN"); - } - - buffer->putTextIndent(indent + 2, "\n"); - - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); - buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); - - buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); - - buffer->putTextIndent(indent + 2, "\n"); - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIText::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // SizeToFit - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "SizeToFit") == 0) { - stack->correctParams(0); - sizeToFit(); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // HeightToFit - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "HeightToFit") == 0) { - stack->correctParams(0); - if (_font && _text) { - _height = _font->getTextHeight((byte *)_text, _width); - } - stack->pushNULL(); - return STATUS_OK; - } else { - return UIObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIText::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("static"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // TextAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "TextAlign") == 0) { - _scValue->setInt(_textAlign); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // VerticalAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "VerticalAlign") == 0) { - _scValue->setInt(_verticalAlign); - return _scValue; - } else { - return UIObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIText::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // TextAlign - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "TextAlign") == 0) { - int i = value->getInt(); - if (i < 0 || i >= NUM_TEXT_ALIGN) { - i = 0; - } - _textAlign = (TTextAlign)i; - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // VerticalAlign - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "VerticalAlign") == 0) { - int i = value->getInt(); - if (i < 0 || i >= NUM_VERTICAL_ALIGN) { - i = 0; - } - _verticalAlign = (TVerticalAlign)i; - return STATUS_OK; - } else { - return UIObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIText::scToString() { - return "[static]"; -} - - - -////////////////////////////////////////////////////////////////////////// -bool UIText::persist(BasePersistenceManager *persistMgr) { - - UIObject::persist(persistMgr); - persistMgr->transfer(TMEMBER_INT(_textAlign)); - persistMgr->transfer(TMEMBER_INT(_verticalAlign)); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIText::sizeToFit() { - if (_font && _text) { - _width = _font->getTextWidth((byte *)_text); - _height = _font->getTextHeight((byte *)_text, _width); - } - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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_dynamic_buffer.h" +#include "engines/wintermute/ui/ui_text.h" +#include "engines/wintermute/ui/ui_tiled_image.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(UIText, false) + +////////////////////////////////////////////////////////////////////////// +UIText::UIText(BaseGame *inGame) : UIObject(inGame) { + _textAlign = TAL_LEFT; + _verticalAlign = VAL_CENTER; + _type = UI_STATIC; + _canFocus = false; +} + + +////////////////////////////////////////////////////////////////////////// +UIText::~UIText() { + +} + + +////////////////////////////////////////////////////////////////////////// +bool UIText::display(int offsetX, int offsetY) { + if (!_visible) { + return STATUS_OK; + } + + + BaseFont *font = _font; + if (!font) { + font = _gameRef->_systemFont; + } + + if (_back) { + _back->display(offsetX + _posX, offsetY + _posY, _width, _height); + } + if (_image) { + _image->draw(offsetX + _posX, offsetY + _posY, NULL); + } + + if (font && _text) { + int textOffset; + switch (_verticalAlign) { + case VAL_TOP: + textOffset = 0; + break; + case VAL_BOTTOM: + textOffset = _height - font->getTextHeight((byte *)_text, _width); + break; + default: + textOffset = (_height - font->getTextHeight((byte *)_text, _width)) / 2; + } + font->drawText((byte *)_text, offsetX + _posX, offsetY + _posY + textOffset, _width, _textAlign, _height); + } + + //_gameRef->_renderer->_rectList.add(new BaseActiveRect(_gameRef, this, NULL, OffsetX + _posX, OffsetY + _posY, _width, _height, 100, 100, false)); + + return STATUS_OK; +} + + + +////////////////////////////////////////////////////////////////////////// +bool UIText::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UIText::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 STATIC file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(STATIC) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(DISABLED) +TOKEN_DEF(VISIBLE) +TOKEN_DEF(BACK) +TOKEN_DEF(IMAGE) +TOKEN_DEF(FONT) +TOKEN_DEF(TEXT_ALIGN) +TOKEN_DEF(VERTICAL_ALIGN) +TOKEN_DEF(TEXT) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(WIDTH) +TOKEN_DEF(HEIGHT) +TOKEN_DEF(CURSOR) +TOKEN_DEF(NAME) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PARENT_NOTIFY) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UIText::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(STATIC) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(DISABLED) + TOKEN_TABLE(VISIBLE) + TOKEN_TABLE(BACK) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TEXT_ALIGN) + TOKEN_TABLE(VERTICAL_ALIGN) + TOKEN_TABLE(TEXT) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(WIDTH) + TOKEN_TABLE(HEIGHT) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(NAME) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PARENT_NOTIFY) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_STATIC) { + _gameRef->LOG(0, "'STATIC' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd > 0 && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 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_BACK: + delete _back; + _back = new UITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new BaseSprite(_gameRef); + if (!_image || DID_FAIL(_image->loadFile((char *)params))) { + delete _image; + _image = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT: + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont((char *)params); + if (!_font) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_TEXT: + setText((char *)params); + _gameRef->_stringTable->expand(&_text); + break; + + case TOKEN_TEXT_ALIGN: + if (scumm_stricmp((char *)params, "left") == 0) { + _textAlign = TAL_LEFT; + } else if (scumm_stricmp((char *)params, "right") == 0) { + _textAlign = TAL_RIGHT; + } else { + _textAlign = TAL_CENTER; + } + break; + + case TOKEN_VERTICAL_ALIGN: + if (scumm_stricmp((char *)params, "top") == 0) { + _verticalAlign = VAL_TOP; + } else if (scumm_stricmp((char *)params, "bottom") == 0) { + _verticalAlign = VAL_BOTTOM; + } else { + _verticalAlign = VAL_CENTER; + } + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_WIDTH: + parser.scanStr((char *)params, "%d", &_width); + break; + + case TOKEN_HEIGHT: + parser.scanStr((char *)params, "%d", &_height); + 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_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PARENT_NOTIFY: + parser.scanStr((char *)params, "%b", &_parentNotify); + break; + + case TOKEN_DISABLED: + parser.scanStr((char *)params, "%b", &_disable); + break; + + case TOKEN_VISIBLE: + parser.scanStr((char *)params, "%b", &_visible); + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in STATIC definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading STATIC definition"); + return STATUS_FAILED; + } + + correctSize(); + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIText::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "STATIC\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); + } + + if (_image && _image->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); + } + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + if (_text) { + buffer->putTextIndent(indent + 2, "TEXT=\"%s\"\n", _text); + } + + switch (_textAlign) { + case TAL_LEFT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "left"); + break; + case TAL_RIGHT: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "right"); + break; + case TAL_CENTER: + buffer->putTextIndent(indent + 2, "TEXT_ALIGN=\"%s\"\n", "center"); + break; + default: + error("UIText::SaveAsText - Unhandled enum"); + break; + } + + switch (_verticalAlign) { + case VAL_TOP: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "top"); + break; + case VAL_BOTTOM: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "bottom"); + break; + case VAL_CENTER: + buffer->putTextIndent(indent + 2, "VERTICAL_ALIGN=\"%s\"\n", "center"); + break; + default: + error("UIText::SaveAsText - Unhandled enum value: NUM_VERTICAL_ALIGN"); + } + + buffer->putTextIndent(indent + 2, "\n"); + + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); + buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); + + buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); + + buffer->putTextIndent(indent + 2, "\n"); + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIText::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // SizeToFit + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "SizeToFit") == 0) { + stack->correctParams(0); + sizeToFit(); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // HeightToFit + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "HeightToFit") == 0) { + stack->correctParams(0); + if (_font && _text) { + _height = _font->getTextHeight((byte *)_text, _width); + } + stack->pushNULL(); + return STATUS_OK; + } else { + return UIObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIText::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("static"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // TextAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "TextAlign") == 0) { + _scValue->setInt(_textAlign); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // VerticalAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "VerticalAlign") == 0) { + _scValue->setInt(_verticalAlign); + return _scValue; + } else { + return UIObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIText::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // TextAlign + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "TextAlign") == 0) { + int i = value->getInt(); + if (i < 0 || i >= NUM_TEXT_ALIGN) { + i = 0; + } + _textAlign = (TTextAlign)i; + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // VerticalAlign + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "VerticalAlign") == 0) { + int i = value->getInt(); + if (i < 0 || i >= NUM_VERTICAL_ALIGN) { + i = 0; + } + _verticalAlign = (TVerticalAlign)i; + return STATUS_OK; + } else { + return UIObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIText::scToString() { + return "[static]"; +} + + + +////////////////////////////////////////////////////////////////////////// +bool UIText::persist(BasePersistenceManager *persistMgr) { + + UIObject::persist(persistMgr); + persistMgr->transfer(TMEMBER_INT(_textAlign)); + persistMgr->transfer(TMEMBER_INT(_verticalAlign)); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIText::sizeToFit() { + if (_font && _text) { + _width = _font->getTextWidth((byte *)_text); + _height = _font->getTextHeight((byte *)_text, _width); + } + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_text.h b/engines/wintermute/ui/ui_text.h index 54817ccf5214..d2f116b44bb2 100644 --- a/engines/wintermute/ui/ui_text.h +++ b/engines/wintermute/ui/ui_text.h @@ -1,60 +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_UITEXT_H -#define WINTERMUTE_UITEXT_H - - -#include "engines/wintermute/ui/ui_object.h" - -namespace Wintermute { - -class UIText : public UIObject { -private: - bool sizeToFit(); -public: - virtual bool display(int offsetX, int offsetY); - DECLARE_PERSISTENT(UIText, UIObject) - UIText(BaseGame *inGame = NULL); - virtual ~UIText(); - TTextAlign _textAlign; - TVerticalAlign _verticalAlign; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual 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 +/* 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_UITEXT_H +#define WINTERMUTE_UITEXT_H + + +#include "engines/wintermute/ui/ui_object.h" + +namespace Wintermute { + +class UIText : public UIObject { +private: + bool sizeToFit(); +public: + virtual bool display(int offsetX, int offsetY); + DECLARE_PERSISTENT(UIText, UIObject) + UIText(BaseGame *inGame = NULL); + virtual ~UIText(); + TTextAlign _textAlign; + TVerticalAlign _verticalAlign; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual 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/ui/ui_tiled_image.cpp b/engines/wintermute/ui/ui_tiled_image.cpp index 0cf28b81f543..cec23cf67e33 100644 --- a/engines/wintermute/ui/ui_tiled_image.cpp +++ b/engines/wintermute/ui/ui_tiled_image.cpp @@ -1,393 +1,393 @@ -/* 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/ui/ui_tiled_image.h" -#include "engines/wintermute/base/gfx/base_surface.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_parser.h" -#include "engines/wintermute/base/base_game.h" -#include "engines/wintermute/base/base_sub_frame.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(UITiledImage, false) - -////////////////////////////////////////////////////////////////////////// -UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) { - _image = NULL; - - BasePlatform::setRectEmpty(&_upLeft); - BasePlatform::setRectEmpty(&_upMiddle); - BasePlatform::setRectEmpty(&_upRight); - BasePlatform::setRectEmpty(&_middleLeft); - BasePlatform::setRectEmpty(&_middleMiddle); - BasePlatform::setRectEmpty(&_middleRight); - BasePlatform::setRectEmpty(&_downLeft); - BasePlatform::setRectEmpty(&_downMiddle); - BasePlatform::setRectEmpty(&_downRight); -} - - -////////////////////////////////////////////////////////////////////////// -UITiledImage::~UITiledImage() { - delete _image; - _image = NULL; -} - - -////////////////////////////////////////////////////////////////////////// -bool UITiledImage::display(int x, int y, int width, int height) { - if (!_image) { - return STATUS_FAILED; - } - - int tileWidth = _middleMiddle.right - _middleMiddle.left; - int tileHeight = _middleMiddle.bottom - _middleMiddle.top; - - int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; - int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; - - int col, row; - - _gameRef->_renderer->startSpriteBatch(); - - // top left/right - _image->_surface->displayTrans(x, y, _upLeft); - _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y, _upRight); - - // bottom left/right - _image->_surface->displayTrans(x, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downLeft); - _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downRight); - - // left/right - int yyy = y + (_upMiddle.bottom - _upMiddle.top); - for (row = 0; row < nuRows; row++) { - _image->_surface->displayTrans(x, yyy, _middleLeft); - _image->_surface->displayTrans(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight); - yyy += tileWidth; - } - - // top/bottom - int xxx = x + (_upLeft.right - _upLeft.left); - for (col = 0; col < nuColumns; col++) { - _image->_surface->displayTrans(xxx, y, _upMiddle); - _image->_surface->displayTrans(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle); - xxx += tileWidth; - } - - // tiles - yyy = y + (_upMiddle.bottom - _upMiddle.top); - for (row = 0; row < nuRows; row++) { - xxx = x + (_upLeft.right - _upLeft.left); - for (col = 0; col < nuColumns; col++) { - _image->_surface->displayTrans(xxx, yyy, _middleMiddle); - xxx += tileWidth; - } - yyy += tileWidth; - } - - _gameRef->_renderer->endSpriteBatch(); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UITiledImage::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UITiledImage::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 TILED_IMAGE file '%s'", filename); - } - - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(TILED_IMAGE) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(IMAGE) -TOKEN_DEF(UP_LEFT) -TOKEN_DEF(UP_RIGHT) -TOKEN_DEF(UP_MIDDLE) -TOKEN_DEF(DOWN_LEFT) -TOKEN_DEF(DOWN_RIGHT) -TOKEN_DEF(DOWN_MIDDLE) -TOKEN_DEF(MIDDLE_LEFT) -TOKEN_DEF(MIDDLE_RIGHT) -TOKEN_DEF(MIDDLE_MIDDLE) -TOKEN_DEF(VERTICAL_TILES) -TOKEN_DEF(HORIZONTAL_TILES) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UITiledImage::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(TILED_IMAGE) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(UP_LEFT) - TOKEN_TABLE(UP_RIGHT) - TOKEN_TABLE(UP_MIDDLE) - TOKEN_TABLE(DOWN_LEFT) - TOKEN_TABLE(DOWN_RIGHT) - TOKEN_TABLE(DOWN_MIDDLE) - TOKEN_TABLE(MIDDLE_LEFT) - TOKEN_TABLE(MIDDLE_RIGHT) - TOKEN_TABLE(MIDDLE_MIDDLE) - TOKEN_TABLE(VERTICAL_TILES) - TOKEN_TABLE(HORIZONTAL_TILES) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE_END - - byte *params; - int cmd; - BaseParser parser; - bool hTiles = false, vTiles = false; - int h1 = 0, h2 = 0, h3 = 0; - int v1 = 0, v2 = 0, v3 = 0; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TILED_IMAGE) { - _gameRef->LOG(0, "'TILED_IMAGE' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { - switch (cmd) { - case TOKEN_TEMPLATE: - if (DID_FAIL(loadFile((char *)params))) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new BaseSubFrame(_gameRef); - if (!_image || DID_FAIL(_image->setSurface((char *)params))) { - delete _image; - _image = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_UP_LEFT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom); - break; - - case TOKEN_UP_RIGHT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom); - break; - - case TOKEN_UP_MIDDLE: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom); - break; - - case TOKEN_DOWN_LEFT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom); - break; - - case TOKEN_DOWN_RIGHT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom); - break; - - case TOKEN_DOWN_MIDDLE: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom); - break; - - case TOKEN_MIDDLE_LEFT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom); - break; - - case TOKEN_MIDDLE_RIGHT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom); - break; - - case TOKEN_MIDDLE_MIDDLE: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom); - break; - - case TOKEN_HORIZONTAL_TILES: - parser.scanStr((char *)params, "%d,%d,%d", &h1, &h2, &h3); - hTiles = true; - break; - - case TOKEN_VERTICAL_TILES: - parser.scanStr((char *)params, "%d,%d,%d", &v1, &v2, &v3); - vTiles = true; - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in TILED_IMAGE definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading TILED_IMAGE definition"); - return STATUS_FAILED; - } - - if (vTiles && hTiles) { - // up row - BasePlatform::setRect(&_upLeft, 0, 0, h1, v1); - BasePlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1); - BasePlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1); - - // middle row - BasePlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2); - BasePlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2); - BasePlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2); - - // down row - BasePlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3); - BasePlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3); - BasePlatform::setRect(&_downRight, h1 + h2, v1 + v2, h1 + h2 + h3, v1 + v2 + v3); - } - - // default - if (_image && _image->_surface) { - int width = _image->_surface->getWidth() / 3; - int height = _image->_surface->getHeight() / 3; - - if (BasePlatform::isRectEmpty(&_upLeft)) { - BasePlatform::setRect(&_upLeft, 0, 0, width, height); - } - if (BasePlatform::isRectEmpty(&_upMiddle)) { - BasePlatform::setRect(&_upMiddle, width, 0, 2 * width, height); - } - if (BasePlatform::isRectEmpty(&_upRight)) { - BasePlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height); - } - - if (BasePlatform::isRectEmpty(&_middleLeft)) { - BasePlatform::setRect(&_middleLeft, 0, height, width, 2 * height); - } - if (BasePlatform::isRectEmpty(&_middleMiddle)) { - BasePlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height); - } - if (BasePlatform::isRectEmpty(&_middleRight)) { - BasePlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height); - } - - if (BasePlatform::isRectEmpty(&_downLeft)) { - BasePlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height); - } - if (BasePlatform::isRectEmpty(&_downMiddle)) { - BasePlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height); - } - if (BasePlatform::isRectEmpty(&_downRight)) { - BasePlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height); - } - } - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UITiledImage::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "TILED_IMAGE\n"); - buffer->putTextIndent(indent, "{\n"); - - if (_image && _image->_surfaceFilename) { - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_surfaceFilename); - } - - int h1, h2, h3; - int v1, v2, v3; - - h1 = _upLeft.right; - h2 = _upMiddle.right - _upMiddle.left; - h3 = _upRight.right - _upRight.left; - - v1 = _upLeft.bottom; - v2 = _middleLeft.bottom - _middleLeft.top; - v3 = _downLeft.bottom - _downLeft.top; - - - buffer->putTextIndent(indent + 2, "VERTICAL_TILES { %d, %d, %d }\n", v1, v2, v3); - buffer->putTextIndent(indent + 2, "HORIZONTAL_TILES { %d, %d, %d }\n", h1, h2, h3); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -void UITiledImage::correctSize(int *width, int *height) { - int tileWidth = _middleMiddle.right - _middleMiddle.left; - int tileHeight = _middleMiddle.bottom - _middleMiddle.top; - - int nuColumns = (*width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; - int nuRows = (*height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; - - *width = (_middleLeft.right - _middleLeft.left) + (_middleRight.right - _middleRight.left) + nuColumns * tileWidth; - *height = (_upMiddle.bottom - _upMiddle.top) + (_downMiddle.bottom - _downMiddle.top) + nuRows * tileHeight; -} - - -////////////////////////////////////////////////////////////////////////// -bool UITiledImage::persist(BasePersistenceManager *persistMgr) { - BaseObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_downLeft)); - persistMgr->transfer(TMEMBER(_downMiddle)); - persistMgr->transfer(TMEMBER(_downRight)); - persistMgr->transfer(TMEMBER(_image)); - persistMgr->transfer(TMEMBER(_middleLeft)); - persistMgr->transfer(TMEMBER(_middleMiddle)); - persistMgr->transfer(TMEMBER(_middleRight)); - persistMgr->transfer(TMEMBER(_upLeft)); - persistMgr->transfer(TMEMBER(_upMiddle)); - persistMgr->transfer(TMEMBER(_upRight)); - - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/ui/ui_tiled_image.h" +#include "engines/wintermute/base/gfx/base_surface.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_parser.h" +#include "engines/wintermute/base/base_game.h" +#include "engines/wintermute/base/base_sub_frame.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(UITiledImage, false) + +////////////////////////////////////////////////////////////////////////// +UITiledImage::UITiledImage(BaseGame *inGame) : BaseObject(inGame) { + _image = NULL; + + BasePlatform::setRectEmpty(&_upLeft); + BasePlatform::setRectEmpty(&_upMiddle); + BasePlatform::setRectEmpty(&_upRight); + BasePlatform::setRectEmpty(&_middleLeft); + BasePlatform::setRectEmpty(&_middleMiddle); + BasePlatform::setRectEmpty(&_middleRight); + BasePlatform::setRectEmpty(&_downLeft); + BasePlatform::setRectEmpty(&_downMiddle); + BasePlatform::setRectEmpty(&_downRight); +} + + +////////////////////////////////////////////////////////////////////////// +UITiledImage::~UITiledImage() { + delete _image; + _image = NULL; +} + + +////////////////////////////////////////////////////////////////////////// +bool UITiledImage::display(int x, int y, int width, int height) { + if (!_image) { + return STATUS_FAILED; + } + + int tileWidth = _middleMiddle.right - _middleMiddle.left; + int tileHeight = _middleMiddle.bottom - _middleMiddle.top; + + int nuColumns = (width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; + int nuRows = (height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; + + int col, row; + + _gameRef->_renderer->startSpriteBatch(); + + // top left/right + _image->_surface->displayTrans(x, y, _upLeft); + _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y, _upRight); + + // bottom left/right + _image->_surface->displayTrans(x, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downLeft); + _image->_surface->displayTrans(x + (_upLeft.right - _upLeft.left) + nuColumns * tileWidth, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downRight); + + // left/right + int yyy = y + (_upMiddle.bottom - _upMiddle.top); + for (row = 0; row < nuRows; row++) { + _image->_surface->displayTrans(x, yyy, _middleLeft); + _image->_surface->displayTrans(x + (_middleLeft.right - _middleLeft.left) + nuColumns * tileWidth, yyy, _middleRight); + yyy += tileWidth; + } + + // top/bottom + int xxx = x + (_upLeft.right - _upLeft.left); + for (col = 0; col < nuColumns; col++) { + _image->_surface->displayTrans(xxx, y, _upMiddle); + _image->_surface->displayTrans(xxx, y + (_upMiddle.bottom - _upMiddle.top) + nuRows * tileHeight, _downMiddle); + xxx += tileWidth; + } + + // tiles + yyy = y + (_upMiddle.bottom - _upMiddle.top); + for (row = 0; row < nuRows; row++) { + xxx = x + (_upLeft.right - _upLeft.left); + for (col = 0; col < nuColumns; col++) { + _image->_surface->displayTrans(xxx, yyy, _middleMiddle); + xxx += tileWidth; + } + yyy += tileWidth; + } + + _gameRef->_renderer->endSpriteBatch(); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UITiledImage::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UITiledImage::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 TILED_IMAGE file '%s'", filename); + } + + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(TILED_IMAGE) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(IMAGE) +TOKEN_DEF(UP_LEFT) +TOKEN_DEF(UP_RIGHT) +TOKEN_DEF(UP_MIDDLE) +TOKEN_DEF(DOWN_LEFT) +TOKEN_DEF(DOWN_RIGHT) +TOKEN_DEF(DOWN_MIDDLE) +TOKEN_DEF(MIDDLE_LEFT) +TOKEN_DEF(MIDDLE_RIGHT) +TOKEN_DEF(MIDDLE_MIDDLE) +TOKEN_DEF(VERTICAL_TILES) +TOKEN_DEF(HORIZONTAL_TILES) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UITiledImage::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(TILED_IMAGE) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(UP_LEFT) + TOKEN_TABLE(UP_RIGHT) + TOKEN_TABLE(UP_MIDDLE) + TOKEN_TABLE(DOWN_LEFT) + TOKEN_TABLE(DOWN_RIGHT) + TOKEN_TABLE(DOWN_MIDDLE) + TOKEN_TABLE(MIDDLE_LEFT) + TOKEN_TABLE(MIDDLE_RIGHT) + TOKEN_TABLE(MIDDLE_MIDDLE) + TOKEN_TABLE(VERTICAL_TILES) + TOKEN_TABLE(HORIZONTAL_TILES) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE_END + + byte *params; + int cmd; + BaseParser parser; + bool hTiles = false, vTiles = false; + int h1 = 0, h2 = 0, h3 = 0; + int v1 = 0, v2 = 0, v3 = 0; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_TILED_IMAGE) { + _gameRef->LOG(0, "'TILED_IMAGE' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while ((cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) > 0) { + switch (cmd) { + case TOKEN_TEMPLATE: + if (DID_FAIL(loadFile((char *)params))) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new BaseSubFrame(_gameRef); + if (!_image || DID_FAIL(_image->setSurface((char *)params))) { + delete _image; + _image = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_UP_LEFT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_upLeft.left, &_upLeft.top, &_upLeft.right, &_upLeft.bottom); + break; + + case TOKEN_UP_RIGHT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_upRight.left, &_upRight.top, &_upRight.right, &_upRight.bottom); + break; + + case TOKEN_UP_MIDDLE: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_upMiddle.left, &_upMiddle.top, &_upMiddle.right, &_upMiddle.bottom); + break; + + case TOKEN_DOWN_LEFT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_downLeft.left, &_downLeft.top, &_downLeft.right, &_downLeft.bottom); + break; + + case TOKEN_DOWN_RIGHT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_downRight.left, &_downRight.top, &_downRight.right, &_downRight.bottom); + break; + + case TOKEN_DOWN_MIDDLE: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_downMiddle.left, &_downMiddle.top, &_downMiddle.right, &_downMiddle.bottom); + break; + + case TOKEN_MIDDLE_LEFT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleLeft.left, &_middleLeft.top, &_middleLeft.right, &_middleLeft.bottom); + break; + + case TOKEN_MIDDLE_RIGHT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleRight.left, &_middleRight.top, &_middleRight.right, &_middleRight.bottom); + break; + + case TOKEN_MIDDLE_MIDDLE: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_middleMiddle.left, &_middleMiddle.top, &_middleMiddle.right, &_middleMiddle.bottom); + break; + + case TOKEN_HORIZONTAL_TILES: + parser.scanStr((char *)params, "%d,%d,%d", &h1, &h2, &h3); + hTiles = true; + break; + + case TOKEN_VERTICAL_TILES: + parser.scanStr((char *)params, "%d,%d,%d", &v1, &v2, &v3); + vTiles = true; + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in TILED_IMAGE definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading TILED_IMAGE definition"); + return STATUS_FAILED; + } + + if (vTiles && hTiles) { + // up row + BasePlatform::setRect(&_upLeft, 0, 0, h1, v1); + BasePlatform::setRect(&_upMiddle, h1, 0, h1 + h2, v1); + BasePlatform::setRect(&_upRight, h1 + h2, 0, h1 + h2 + h3, v1); + + // middle row + BasePlatform::setRect(&_middleLeft, 0, v1, h1, v1 + v2); + BasePlatform::setRect(&_middleMiddle, h1, v1, h1 + h2, v1 + v2); + BasePlatform::setRect(&_middleRight, h1 + h2, v1, h1 + h2 + h3, v1 + v2); + + // down row + BasePlatform::setRect(&_downLeft, 0, v1 + v2, h1, v1 + v2 + v3); + BasePlatform::setRect(&_downMiddle, h1, v1 + v2, h1 + h2, v1 + v2 + v3); + BasePlatform::setRect(&_downRight, h1 + h2, v1 + v2, h1 + h2 + h3, v1 + v2 + v3); + } + + // default + if (_image && _image->_surface) { + int width = _image->_surface->getWidth() / 3; + int height = _image->_surface->getHeight() / 3; + + if (BasePlatform::isRectEmpty(&_upLeft)) { + BasePlatform::setRect(&_upLeft, 0, 0, width, height); + } + if (BasePlatform::isRectEmpty(&_upMiddle)) { + BasePlatform::setRect(&_upMiddle, width, 0, 2 * width, height); + } + if (BasePlatform::isRectEmpty(&_upRight)) { + BasePlatform::setRect(&_upRight, 2 * width, 0, 3 * width, height); + } + + if (BasePlatform::isRectEmpty(&_middleLeft)) { + BasePlatform::setRect(&_middleLeft, 0, height, width, 2 * height); + } + if (BasePlatform::isRectEmpty(&_middleMiddle)) { + BasePlatform::setRect(&_middleMiddle, width, height, 2 * width, 2 * height); + } + if (BasePlatform::isRectEmpty(&_middleRight)) { + BasePlatform::setRect(&_middleRight, 2 * width, height, 3 * width, 2 * height); + } + + if (BasePlatform::isRectEmpty(&_downLeft)) { + BasePlatform::setRect(&_downLeft, 0, 2 * height, width, 3 * height); + } + if (BasePlatform::isRectEmpty(&_downMiddle)) { + BasePlatform::setRect(&_downMiddle, width, 2 * height, 2 * width, 3 * height); + } + if (BasePlatform::isRectEmpty(&_downRight)) { + BasePlatform::setRect(&_downRight, 2 * width, 2 * height, 3 * width, 3 * height); + } + } + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UITiledImage::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "TILED_IMAGE\n"); + buffer->putTextIndent(indent, "{\n"); + + if (_image && _image->_surfaceFilename) { + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->_surfaceFilename); + } + + int h1, h2, h3; + int v1, v2, v3; + + h1 = _upLeft.right; + h2 = _upMiddle.right - _upMiddle.left; + h3 = _upRight.right - _upRight.left; + + v1 = _upLeft.bottom; + v2 = _middleLeft.bottom - _middleLeft.top; + v3 = _downLeft.bottom - _downLeft.top; + + + buffer->putTextIndent(indent + 2, "VERTICAL_TILES { %d, %d, %d }\n", v1, v2, v3); + buffer->putTextIndent(indent + 2, "HORIZONTAL_TILES { %d, %d, %d }\n", h1, h2, h3); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +void UITiledImage::correctSize(int *width, int *height) { + int tileWidth = _middleMiddle.right - _middleMiddle.left; + int tileHeight = _middleMiddle.bottom - _middleMiddle.top; + + int nuColumns = (*width - (_middleLeft.right - _middleLeft.left) - (_middleRight.right - _middleRight.left)) / tileWidth; + int nuRows = (*height - (_upMiddle.bottom - _upMiddle.top) - (_downMiddle.bottom - _downMiddle.top)) / tileHeight; + + *width = (_middleLeft.right - _middleLeft.left) + (_middleRight.right - _middleRight.left) + nuColumns * tileWidth; + *height = (_upMiddle.bottom - _upMiddle.top) + (_downMiddle.bottom - _downMiddle.top) + nuRows * tileHeight; +} + + +////////////////////////////////////////////////////////////////////////// +bool UITiledImage::persist(BasePersistenceManager *persistMgr) { + BaseObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_downLeft)); + persistMgr->transfer(TMEMBER(_downMiddle)); + persistMgr->transfer(TMEMBER(_downRight)); + persistMgr->transfer(TMEMBER(_image)); + persistMgr->transfer(TMEMBER(_middleLeft)); + persistMgr->transfer(TMEMBER(_middleMiddle)); + persistMgr->transfer(TMEMBER(_middleRight)); + persistMgr->transfer(TMEMBER(_upLeft)); + persistMgr->transfer(TMEMBER(_upMiddle)); + persistMgr->transfer(TMEMBER(_upRight)); + + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_tiled_image.h b/engines/wintermute/ui/ui_tiled_image.h index 863bf7d1ea13..c413e7f12915 100644 --- a/engines/wintermute/ui/ui_tiled_image.h +++ b/engines/wintermute/ui/ui_tiled_image.h @@ -1,63 +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_UITILEDIMAGE_H -#define WINTERMUTE_UITILEDIMAGE_H - - -#include "engines/wintermute/ui/ui_object.h" -#include "common/rect.h" - -namespace Wintermute { -class BaseSubFrame; -class UITiledImage : public BaseObject { -public: - DECLARE_PERSISTENT(UITiledImage, BaseObject) - void correctSize(int *width, int *height); - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); - - bool display(int x, int y, int width, int height); - UITiledImage(BaseGame *inGame = NULL); - virtual ~UITiledImage(); - BaseSubFrame *_image; - Rect32 _upLeft; - Rect32 _upMiddle; - Rect32 _upRight; - Rect32 _middleLeft; - Rect32 _middleMiddle; - Rect32 _middleRight; - Rect32 _downLeft; - Rect32 _downMiddle; - Rect32 _downRight; -}; - -} // end of namespace Wintermute - -#endif +/* 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_UITILEDIMAGE_H +#define WINTERMUTE_UITILEDIMAGE_H + + +#include "engines/wintermute/ui/ui_object.h" +#include "common/rect.h" + +namespace Wintermute { +class BaseSubFrame; +class UITiledImage : public BaseObject { +public: + DECLARE_PERSISTENT(UITiledImage, BaseObject) + void correctSize(int *width, int *height); + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + virtual bool saveAsText(BaseDynamicBuffer *buffer, int indent); + + bool display(int x, int y, int width, int height); + UITiledImage(BaseGame *inGame = NULL); + virtual ~UITiledImage(); + BaseSubFrame *_image; + Rect32 _upLeft; + Rect32 _upMiddle; + Rect32 _upRight; + Rect32 _middleLeft; + Rect32 _middleMiddle; + Rect32 _middleRight; + Rect32 _downLeft; + Rect32 _downMiddle; + Rect32 _downRight; +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/ui/ui_window.cpp b/engines/wintermute/ui/ui_window.cpp index ffb7e4dbf894..65af62141da4 100644 --- a/engines/wintermute/ui/ui_window.cpp +++ b/engines/wintermute/ui/ui_window.cpp @@ -1,1444 +1,1444 @@ -/* 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/base_parser.h" -#include "engines/wintermute/base/base_active_rect.h" -#include "engines/wintermute/base/base_dynamic_buffer.h" -#include "engines/wintermute/base/base_keyboard_state.h" -#include "engines/wintermute/base/scriptables/script_value.h" -#include "engines/wintermute/ui/ui_button.h" -#include "engines/wintermute/ui/ui_edit.h" -#include "engines/wintermute/ui/ui_text.h" -#include "engines/wintermute/ui/ui_tiled_image.h" -#include "engines/wintermute/ui/ui_window.h" -#include "engines/wintermute/base/base_viewport.h" -#include "engines/wintermute/base/font/base_font_storage.h" -#include "engines/wintermute/base/font/base_font.h" -#include "engines/wintermute/base/base_string_table.h" -#include "engines/wintermute/base/scriptables/script.h" -#include "engines/wintermute/base/scriptables/script_stack.h" -#include "engines/wintermute/base/base_sprite.h" -#include "engines/wintermute/base/base_file_manager.h" -#include "engines/wintermute/platform_osystem.h" - -namespace Wintermute { - -IMPLEMENT_PERSISTENT(UIWindow, false) - -////////////////////////////////////////////////////////////////////////// -UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) { - BasePlatform::setRectEmpty(&_titleRect); - BasePlatform::setRectEmpty(&_dragRect); - _titleAlign = TAL_LEFT; - _transparent = false; - - _backInactive = NULL; - _fontInactive = NULL; - _imageInactive = NULL; - - _type = UI_WINDOW; - _canFocus = true; - - _dragging = false; - _dragFrom.x = _dragFrom.y = 0; - - _mode = WINDOW_NORMAL; - _shieldWindow = NULL; - _shieldButton = NULL; - - _fadeColor = 0x00000000; - _fadeBackground = false; - - _ready = true; - _isMenu = false; - _inGame = false; - - _clipContents = false; - _viewport = NULL; - - _pauseMusic = true; -} - - -////////////////////////////////////////////////////////////////////////// -UIWindow::~UIWindow() { - close(); - cleanup(); -} - - -////////////////////////////////////////////////////////////////////////// -void UIWindow::cleanup() { - delete _shieldWindow; - delete _shieldButton; - delete _viewport; - _shieldWindow = NULL; - _shieldButton = NULL; - _viewport = NULL; - - delete _backInactive; - if (!_sharedFonts && _fontInactive) { - _gameRef->_fontStorage->removeFont(_fontInactive); - } - if (!_sharedImages && _imageInactive) { - delete _imageInactive; - } - - for (uint32 i = 0; i < _widgets.size(); i++) { - delete _widgets[i]; - } - _widgets.clear(); -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::display(int offsetX, int offsetY) { - // go exclusive - if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) { - if (!_shieldWindow) { - _shieldWindow = new UIWindow(_gameRef); - } - if (_shieldWindow) { - _shieldWindow->_posX = _shieldWindow->_posY = 0; - _shieldWindow->_width = _gameRef->_renderer->_width; - _shieldWindow->_height = _gameRef->_renderer->_height; - - _shieldWindow->display(); - } - } else if (_isMenu) { - if (!_shieldButton) { - _shieldButton = new UIButton(_gameRef); - _shieldButton->setName("close"); - _shieldButton->setListener(this, _shieldButton, 0); - _shieldButton->_parent = this; - } - if (_shieldButton) { - _shieldButton->_posX = _shieldButton->_posY = 0; - _shieldButton->_width = _gameRef->_renderer->_width; - _shieldButton->_height = _gameRef->_renderer->_height; - - _shieldButton->display(); - } - } - - if (!_visible) { - return STATUS_OK; - } - - if (_fadeBackground) { - Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); - byte fadeR, fadeG, fadeB, fadeA; - // First convert from the internal format to the screen-format - uint32 fadeColor = format.ARGBToColor(RGBCOLGetA(_fadeColor), RGBCOLGetR(_fadeColor), RGBCOLGetG(_fadeColor), RGBCOLGetB(_fadeColor)); - // Then get components - format.colorToARGB(fadeColor, fadeA, fadeR, fadeG, fadeB); - _gameRef->_renderer->fadeToColor(fadeR, fadeG, fadeB, fadeA); - } - - if (_dragging) { - _posX += (_gameRef->_mousePos.x - _dragFrom.x); - _posY += (_gameRef->_mousePos.y - _dragFrom.y); - - _dragFrom.x = _gameRef->_mousePos.x; - _dragFrom.y = _gameRef->_mousePos.y; - } - - if (!_focusedWidget || (!_focusedWidget->_canFocus || _focusedWidget->_disable || !_focusedWidget->_visible)) { - moveFocus(); - } - - bool popViewport = false; - if (_clipContents) { - if (!_viewport) { - _viewport = new BaseViewport(_gameRef); - } - if (_viewport) { - _viewport->setRect(_posX + offsetX, _posY + offsetY, _posX + _width + offsetX, _posY + _height + offsetY); - _gameRef->pushViewport(_viewport); - popViewport = true; - } - } - - - UITiledImage *back = _back; - BaseSprite *image = _image; - BaseFont *font = _font; - - if (!isFocused()) { - if (_backInactive) { - back = _backInactive; - } - if (_imageInactive) { - image = _imageInactive; - } - if (_fontInactive) { - font = _fontInactive; - } - } - - if (_alphaColor != 0) { - _gameRef->_renderer->_forceAlphaColor = _alphaColor; - } - if (back) { - back->display(_posX + offsetX, _posY + offsetY, _width, _height); - } - if (image) { - image->draw(_posX + offsetX, _posY + offsetY, _transparent ? NULL : this); - } - - if (!BasePlatform::isRectEmpty(&_titleRect) && font && _text) { - font->drawText((byte *)_text, _posX + offsetX + _titleRect.left, _posY + offsetY + _titleRect.top, _titleRect.right - _titleRect.left, _titleAlign, _titleRect.bottom - _titleRect.top); - } - - if (!_transparent && !image) { - _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); - } - - for (uint32 i = 0; i < _widgets.size(); i++) { - _widgets[i]->display(_posX + offsetX, _posY + offsetY); - } - - if (_alphaColor != 0) { - _gameRef->_renderer->_forceAlphaColor = 0; - } - - if (popViewport) { - _gameRef->popViewport(); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::loadFile(const char *filename) { - byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); - if (buffer == NULL) { - _gameRef->LOG(0, "UIWindow::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 WINDOW file '%s'", filename); - } - - delete[] buffer; - - return ret; -} - - -TOKEN_DEF_START -TOKEN_DEF(WINDOW) -TOKEN_DEF(ALPHA_COLOR) -TOKEN_DEF(ALPHA) -TOKEN_DEF(TEMPLATE) -TOKEN_DEF(DISABLED) -TOKEN_DEF(VISIBLE) -TOKEN_DEF(BACK_INACTIVE) -TOKEN_DEF(BACK) -TOKEN_DEF(IMAGE_INACTIVE) -TOKEN_DEF(IMAGE) -TOKEN_DEF(FONT_INACTIVE) -TOKEN_DEF(FONT) -TOKEN_DEF(TITLE_ALIGN) -TOKEN_DEF(TITLE_RECT) -TOKEN_DEF(TITLE) -TOKEN_DEF(DRAG_RECT) -TOKEN_DEF(X) -TOKEN_DEF(Y) -TOKEN_DEF(WIDTH) -TOKEN_DEF(HEIGHT) -TOKEN_DEF(FADE_ALPHA) -TOKEN_DEF(FADE_COLOR) -TOKEN_DEF(CURSOR) -TOKEN_DEF(NAME) -TOKEN_DEF(BUTTON) -TOKEN_DEF(STATIC) -TOKEN_DEF(TRANSPARENT) -TOKEN_DEF(SCRIPT) -TOKEN_DEF(CAPTION) -TOKEN_DEF(PARENT_NOTIFY) -TOKEN_DEF(MENU) -TOKEN_DEF(IN_GAME) -TOKEN_DEF(CLIP_CONTENTS) -TOKEN_DEF(PAUSE_MUSIC) -TOKEN_DEF(EDITOR_PROPERTY) -TOKEN_DEF(EDIT) -TOKEN_DEF_END -////////////////////////////////////////////////////////////////////////// -bool UIWindow::loadBuffer(byte *buffer, bool complete) { - TOKEN_TABLE_START(commands) - TOKEN_TABLE(WINDOW) - TOKEN_TABLE(ALPHA_COLOR) - TOKEN_TABLE(ALPHA) - TOKEN_TABLE(TEMPLATE) - TOKEN_TABLE(DISABLED) - TOKEN_TABLE(VISIBLE) - TOKEN_TABLE(BACK_INACTIVE) - TOKEN_TABLE(BACK) - TOKEN_TABLE(IMAGE_INACTIVE) - TOKEN_TABLE(IMAGE) - TOKEN_TABLE(FONT_INACTIVE) - TOKEN_TABLE(FONT) - TOKEN_TABLE(TITLE_ALIGN) - TOKEN_TABLE(TITLE_RECT) - TOKEN_TABLE(TITLE) - TOKEN_TABLE(DRAG_RECT) - TOKEN_TABLE(X) - TOKEN_TABLE(Y) - TOKEN_TABLE(WIDTH) - TOKEN_TABLE(HEIGHT) - TOKEN_TABLE(FADE_ALPHA) - TOKEN_TABLE(FADE_COLOR) - TOKEN_TABLE(CURSOR) - TOKEN_TABLE(NAME) - TOKEN_TABLE(BUTTON) - TOKEN_TABLE(STATIC) - TOKEN_TABLE(TRANSPARENT) - TOKEN_TABLE(SCRIPT) - TOKEN_TABLE(CAPTION) - TOKEN_TABLE(PARENT_NOTIFY) - TOKEN_TABLE(MENU) - TOKEN_TABLE(IN_GAME) - TOKEN_TABLE(CLIP_CONTENTS) - TOKEN_TABLE(PAUSE_MUSIC) - TOKEN_TABLE(EDITOR_PROPERTY) - TOKEN_TABLE(EDIT) - TOKEN_TABLE_END - - byte *params; - int cmd = 2; - BaseParser parser; - - int fadeR = 0, fadeG = 0, fadeB = 0, fadeA = 0; - int ar = 0, ag = 0, ab = 0, alpha = 0; - - if (complete) { - if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_WINDOW) { - _gameRef->LOG(0, "'WINDOW' keyword expected."); - return STATUS_FAILED; - } - buffer = params; - } - - while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) >= PARSERR_TOKENNOTFOUND) { - 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_BACK: - delete _back; - _back = new UITiledImage(_gameRef); - if (!_back || DID_FAIL(_back->loadFile((char *)params))) { - delete _back; - _back = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_BACK_INACTIVE: - delete _backInactive; - _backInactive = new UITiledImage(_gameRef); - if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) { - delete _backInactive; - _backInactive = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE: - delete _image; - _image = new BaseSprite(_gameRef); - if (!_image || DID_FAIL(_image->loadFile((char *)params))) { - delete _image; - _image = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_IMAGE_INACTIVE: - delete _imageInactive, - _imageInactive = new BaseSprite(_gameRef); - if (!_imageInactive || DID_FAIL(_imageInactive->loadFile((char *)params))) { - delete _imageInactive; - _imageInactive = NULL; - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT: - if (_font) { - _gameRef->_fontStorage->removeFont(_font); - } - _font = _gameRef->_fontStorage->addFont((char *)params); - if (!_font) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_FONT_INACTIVE: - if (_fontInactive) { - _gameRef->_fontStorage->removeFont(_fontInactive); - } - _fontInactive = _gameRef->_fontStorage->addFont((char *)params); - if (!_fontInactive) { - cmd = PARSERR_GENERIC; - } - break; - - case TOKEN_TITLE: - setText((char *)params); - _gameRef->_stringTable->expand(&_text); - break; - - case TOKEN_TITLE_ALIGN: - if (scumm_stricmp((char *)params, "left") == 0) { - _titleAlign = TAL_LEFT; - } else if (scumm_stricmp((char *)params, "right") == 0) { - _titleAlign = TAL_RIGHT; - } else { - _titleAlign = TAL_CENTER; - } - break; - - case TOKEN_TITLE_RECT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_titleRect.left, &_titleRect.top, &_titleRect.right, &_titleRect.bottom); - break; - - case TOKEN_DRAG_RECT: - parser.scanStr((char *)params, "%d,%d,%d,%d", &_dragRect.left, &_dragRect.top, &_dragRect.right, &_dragRect.bottom); - break; - - case TOKEN_X: - parser.scanStr((char *)params, "%d", &_posX); - break; - - case TOKEN_Y: - parser.scanStr((char *)params, "%d", &_posY); - break; - - case TOKEN_WIDTH: - parser.scanStr((char *)params, "%d", &_width); - break; - - case TOKEN_HEIGHT: - parser.scanStr((char *)params, "%d", &_height); - 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_BUTTON: { - UIButton *btn = new UIButton(_gameRef); - if (!btn || DID_FAIL(btn->loadBuffer(params, false))) { - delete btn; - btn = NULL; - cmd = PARSERR_GENERIC; - } else { - btn->_parent = this; - _widgets.add(btn); - } - } - break; - - case TOKEN_STATIC: { - UIText *text = new UIText(_gameRef); - if (!text || DID_FAIL(text->loadBuffer(params, false))) { - delete text; - text = NULL; - cmd = PARSERR_GENERIC; - } else { - text->_parent = this; - _widgets.add(text); - } - } - break; - - case TOKEN_EDIT: { - UIEdit *edit = new UIEdit(_gameRef); - if (!edit || DID_FAIL(edit->loadBuffer(params, false))) { - delete edit; - edit = NULL; - cmd = PARSERR_GENERIC; - } else { - edit->_parent = this; - _widgets.add(edit); - } - } - break; - - case TOKEN_WINDOW: { - UIWindow *win = new UIWindow(_gameRef); - if (!win || DID_FAIL(win->loadBuffer(params, false))) { - delete win; - win = NULL; - cmd = PARSERR_GENERIC; - } else { - win->_parent = this; - _widgets.add(win); - } - } - break; - - - case TOKEN_TRANSPARENT: - parser.scanStr((char *)params, "%b", &_transparent); - break; - - case TOKEN_SCRIPT: - addScript((char *)params); - break; - - case TOKEN_PARENT_NOTIFY: - parser.scanStr((char *)params, "%b", &_parentNotify); - break; - - case TOKEN_PAUSE_MUSIC: - parser.scanStr((char *)params, "%b", &_pauseMusic); - break; - - case TOKEN_DISABLED: - parser.scanStr((char *)params, "%b", &_disable); - break; - - case TOKEN_VISIBLE: - parser.scanStr((char *)params, "%b", &_visible); - break; - - case TOKEN_MENU: - parser.scanStr((char *)params, "%b", &_isMenu); - break; - - case TOKEN_IN_GAME: - parser.scanStr((char *)params, "%b", &_inGame); - break; - - case TOKEN_CLIP_CONTENTS: - parser.scanStr((char *)params, "%b", &_clipContents); - break; - - case TOKEN_FADE_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &fadeR, &fadeG, &fadeB); - _fadeBackground = true; - break; - - case TOKEN_FADE_ALPHA: - parser.scanStr((char *)params, "%d", &fadeA); - _fadeBackground = true; - break; - - case TOKEN_EDITOR_PROPERTY: - parseEditorProperty(params, false); - break; - - case TOKEN_ALPHA_COLOR: - parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); - break; - - case TOKEN_ALPHA: - parser.scanStr((char *)params, "%d", &alpha); - break; - - - default: - if (DID_FAIL(_gameRef->windowLoadHook(this, (char **)&buffer, (char **)params))) { - cmd = PARSERR_GENERIC; - } - } - } - if (cmd == PARSERR_TOKENNOTFOUND) { - _gameRef->LOG(0, "Syntax error in WINDOW definition"); - return STATUS_FAILED; - } - if (cmd == PARSERR_GENERIC) { - _gameRef->LOG(0, "Error loading WINDOW definition"); - return STATUS_FAILED; - } - - correctSize(); - - if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { - ar = ag = ab = 255; - } - _alphaColor = BYTETORGBA(ar, ag, ab, alpha); - - if (_fadeBackground) { - _fadeColor = BYTETORGBA(fadeR, fadeG, fadeB, fadeA); - } - - _focusedWidget = NULL; - - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::saveAsText(BaseDynamicBuffer *buffer, int indent) { - buffer->putTextIndent(indent, "WINDOW\n"); - buffer->putTextIndent(indent, "{\n"); - - buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); - buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_back && _back->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); - } - if (_backInactive && _backInactive->getFilename()) { - buffer->putTextIndent(indent + 2, "BACK_INACTIVE=\"%s\"\n", _backInactive->getFilename()); - } - - if (_image && _image->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); - } - if (_imageInactive && _imageInactive->getFilename()) { - buffer->putTextIndent(indent + 2, "IMAGE_INACTIVE=\"%s\"\n", _imageInactive->getFilename()); - } - - if (_font && _font->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); - } - if (_fontInactive && _fontInactive->getFilename()) { - buffer->putTextIndent(indent + 2, "FONT_INACTIVE=\"%s\"\n", _fontInactive->getFilename()); - } - - if (_cursor && _cursor->getFilename()) { - buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); - } - - buffer->putTextIndent(indent + 2, "\n"); - - if (_text) { - buffer->putTextIndent(indent + 2, "TITLE=\"%s\"\n", _text); - } - - switch (_titleAlign) { - case TAL_LEFT: - buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "left"); - break; - case TAL_RIGHT: - buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "right"); - break; - case TAL_CENTER: - buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "center"); - break; - default: - error("UIWindow::SaveAsText - Unhandled enum-value NUM_TEXT_ALIGN"); - } - - if (!BasePlatform::isRectEmpty(&_titleRect)) { - buffer->putTextIndent(indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom); - } - - if (!BasePlatform::isRectEmpty(&_dragRect)) { - buffer->putTextIndent(indent + 2, "DRAG_RECT { %d, %d, %d, %d }\n", _dragRect.left, _dragRect.top, _dragRect.right, _dragRect.bottom); - } - - buffer->putTextIndent(indent + 2, "\n"); - - buffer->putTextIndent(indent + 2, "X=%d\n", _posX); - buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); - buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); - buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); - - buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); - - buffer->putTextIndent(indent + 2, "TRANSPARENT=%s\n", _transparent ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "PAUSE_MUSIC=%s\n", _pauseMusic ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "MENU=%s\n", _isMenu ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "IN_GAME=%s\n", _inGame ? "TRUE" : "FALSE"); - buffer->putTextIndent(indent + 2, "CLIP_CONTENTS=%s\n", _clipContents ? "TRUE" : "FALSE"); - - buffer->putTextIndent(indent + 2, "\n"); - - if (_fadeBackground) { - buffer->putTextIndent(indent + 2, "FADE_COLOR { %d, %d, %d }\n", RGBCOLGetR(_fadeColor), RGBCOLGetG(_fadeColor), RGBCOLGetB(_fadeColor)); - buffer->putTextIndent(indent + 2, "FADE_ALPHA=%d\n", RGBCOLGetA(_fadeColor)); - } - - buffer->putTextIndent(indent + 2, "ALPHA_COLOR { %d, %d, %d }\n", RGBCOLGetR(_alphaColor), RGBCOLGetG(_alphaColor), RGBCOLGetB(_alphaColor)); - buffer->putTextIndent(indent + 2, "ALPHA=%d\n", RGBCOLGetA(_alphaColor)); - - buffer->putTextIndent(indent + 2, "\n"); - - // scripts - for (uint32 i = 0; i < _scripts.size(); i++) { - buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); - } - - buffer->putTextIndent(indent + 2, "\n"); - - // editor properties - BaseClass::saveAsText(buffer, indent + 2); - - // controls - for (uint32 i = 0; i < _widgets.size(); i++) { - _widgets[i]->saveAsText(buffer, indent + 2); - } - - - buffer->putTextIndent(indent, "}\n"); - return STATUS_OK; -} - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::enableWidget(const char *name, bool enable) { - for (uint32 i = 0; i < _widgets.size(); i++) { - if (scumm_stricmp(_widgets[i]->getName(), name) == 0) { - _widgets[i]->_disable = !enable; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::showWidget(const char *name, bool visible) { - for (uint32 i = 0; i < _widgets.size(); i++) { - if (scumm_stricmp(_widgets[i]->getName(), name) == 0) { - _widgets[i]->_visible = visible; - } - } - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -// high level scripting interface -////////////////////////////////////////////////////////////////////////// -bool UIWindow::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { - ////////////////////////////////////////////////////////////////////////// - // GetWidget / GetControl - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "GetWidget") == 0 || strcmp(name, "GetControl") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - if (val->getType() == VAL_INT) { - int widget = val->getInt(); - if (widget < 0 || widget >= (int32)_widgets.size()) { - stack->pushNULL(); - } else { - stack->pushNative(_widgets[widget], true); - } - } else { - for (uint32 i = 0; i < _widgets.size(); i++) { - if (scumm_stricmp(_widgets[i]->getName(), val->getString()) == 0) { - stack->pushNative(_widgets[i], true); - return STATUS_OK; - } - } - stack->pushNULL(); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetInactiveFont - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetInactiveFont") == 0) { - stack->correctParams(1); - - if (_fontInactive) { - _gameRef->_fontStorage->removeFont(_fontInactive); - } - _fontInactive = _gameRef->_fontStorage->addFont(stack->pop()->getString()); - stack->pushBool(_fontInactive != NULL); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SetInactiveImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SetInactiveImage") == 0) { - stack->correctParams(1); - - delete _imageInactive; - _imageInactive = new BaseSprite(_gameRef); - const char *filename = stack->pop()->getString(); - if (!_imageInactive || DID_FAIL(_imageInactive->loadFile(filename))) { - delete _imageInactive; - _imageInactive = NULL; - stack->pushBool(false); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetInactiveImage - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetInactiveImage") == 0) { - stack->correctParams(0); - if (!_imageInactive || !_imageInactive->getFilename()) { - stack->pushNULL(); - } else { - stack->pushString(_imageInactive->getFilename()); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GetInactiveImageObject - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GetInactiveImageObject") == 0) { - stack->correctParams(0); - if (!_imageInactive) { - stack->pushNULL(); - } else { - stack->pushNative(_imageInactive, true); - } - - return STATUS_OK; - } - - - ////////////////////////////////////////////////////////////////////////// - // Close - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Close") == 0) { - stack->correctParams(0); - stack->pushBool(DID_SUCCEED(close())); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GoExclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GoExclusive") == 0) { - stack->correctParams(0); - goExclusive(); - script->waitFor(this); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // GoSystemExclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "GoSystemExclusive") == 0) { - stack->correctParams(0); - goSystemExclusive(); - script->waitFor(this); - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Center - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Center") == 0) { - stack->correctParams(0); - _posX = (_gameRef->_renderer->_width - _width) / 2; - _posY = (_gameRef->_renderer->_height - _height) / 2; - stack->pushNULL(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // LoadFromFile - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "LoadFromFile") == 0) { - stack->correctParams(1); - - ScValue *val = stack->pop(); - cleanup(); - if (!val->isNULL()) { - stack->pushBool(DID_SUCCEED(loadFile(val->getString()))); - } else { - stack->pushBool(true); - } - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateButton - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateButton") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - UIButton *btn = new UIButton(_gameRef); - if (!val->isNULL()) { - btn->setName(val->getString()); - } - stack->pushNative(btn, true); - - btn->_parent = this; - _widgets.add(btn); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateStatic - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateStatic") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - UIText *sta = new UIText(_gameRef); - if (!val->isNULL()) { - sta->setName(val->getString()); - } - stack->pushNative(sta, true); - - sta->_parent = this; - _widgets.add(sta); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateEditor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateEditor") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - UIEdit *edi = new UIEdit(_gameRef); - if (!val->isNULL()) { - edi->setName(val->getString()); - } - stack->pushNative(edi, true); - - edi->_parent = this; - _widgets.add(edi); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // CreateWindow - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "CreateWindow") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - - UIWindow *win = new UIWindow(_gameRef); - if (!val->isNULL()) { - win->setName(val->getString()); - } - stack->pushNative(win, true); - - win->_parent = this; - _widgets.add(win); - - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // DeleteControl / DeleteButton / DeleteStatic / DeleteEditor / DeleteWindow - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "DeleteControl") == 0 || strcmp(name, "DeleteButton") == 0 || strcmp(name, "DeleteStatic") == 0 || strcmp(name, "DeleteEditor") == 0 || strcmp(name, "DeleteWindow") == 0) { - stack->correctParams(1); - ScValue *val = stack->pop(); - UIObject *obj = (UIObject *)val->getNative(); - - for (uint32 i = 0; i < _widgets.size(); i++) { - if (_widgets[i] == obj) { - delete _widgets[i]; - _widgets.remove_at(i); - if (val->getType() == VAL_VARIABLE_REF) { - val->setNULL(); - } - } - } - stack->pushNULL(); - return STATUS_OK; - } else if DID_SUCCEED(_gameRef->windowScriptMethodHook(this, script, stack, name)) { - return STATUS_OK; - } - - else { - return UIObject::scCallMethod(script, stack, thisStack, name); - } -} - - -////////////////////////////////////////////////////////////////////////// -ScValue *UIWindow::scGetProperty(const char *name) { - _scValue->setNULL(); - - ////////////////////////////////////////////////////////////////////////// - // Type - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Type") == 0) { - _scValue->setString("window"); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // NumWidgets / NumControls (RO) - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "NumWidgets") == 0 || strcmp(name, "NumControls") == 0) { - _scValue->setInt(_widgets.size()); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Exclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Exclusive") == 0) { - _scValue->setBool(_mode == WINDOW_EXCLUSIVE); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // SystemExclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SystemExclusive") == 0) { - _scValue->setBool(_mode == WINDOW_SYSTEM_EXCLUSIVE); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Menu - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Menu") == 0) { - _scValue->setBool(_isMenu); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // InGame - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InGame") == 0) { - _scValue->setBool(_inGame); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // PauseMusic - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PauseMusic") == 0) { - _scValue->setBool(_pauseMusic); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // ClipContents - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ClipContents") == 0) { - _scValue->setBool(_clipContents); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // Transparent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Transparent") == 0) { - _scValue->setBool(_transparent); - return _scValue; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeColor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeColor") == 0) { - _scValue->setInt((int)_fadeColor); - return _scValue; - } else { - return UIObject::scGetProperty(name); - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::scSetProperty(const char *name, ScValue *value) { - ////////////////////////////////////////////////////////////////////////// - // Name - ////////////////////////////////////////////////////////////////////////// - if (strcmp(name, "Name") == 0) { - setName(value->getString()); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Menu - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Menu") == 0) { - _isMenu = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // InGame - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "InGame") == 0) { - _inGame = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // PauseMusic - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "PauseMusic") == 0) { - _pauseMusic = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // ClipContents - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "ClipContents") == 0) { - _clipContents = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Transparent - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Transparent") == 0) { - _transparent = value->getBool(); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // FadeColor - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "FadeColor") == 0) { - _fadeColor = (uint32)value->getInt(); - _fadeBackground = (_fadeColor != 0); - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // Exclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "Exclusive") == 0) { - if (value->getBool()) { - goExclusive(); - } else { - close(); - _visible = true; - } - return STATUS_OK; - } - - ////////////////////////////////////////////////////////////////////////// - // SystemExclusive - ////////////////////////////////////////////////////////////////////////// - else if (strcmp(name, "SystemExclusive") == 0) { - if (value->getBool()) { - goSystemExclusive(); - } else { - close(); - _visible = true; - } - return STATUS_OK; - } else { - return UIObject::scSetProperty(name, value); - } -} - - -////////////////////////////////////////////////////////////////////////// -const char *UIWindow::scToString() { - return "[window]"; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::handleKeypress(Common::Event *event, bool printable) { -//TODO - if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_TAB) { - return DID_SUCCEED(moveFocus(!BaseKeyboardState::isShiftDown())); - } else { - if (_focusedWidget) { - return _focusedWidget->handleKeypress(event, printable); - } else { - return false; - } - } - return false; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::handleMouseWheel(int Delta) { - if (_focusedWidget) { - return _focusedWidget->handleMouseWheel(Delta); - } else { - return false; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::handleMouse(TMouseEvent event, TMouseButton button) { - bool res = UIObject::handleMouse(event, button); - - // handle window dragging - if (!BasePlatform::isRectEmpty(&_dragRect)) { - // start drag - if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { - Rect32 dragRect = _dragRect; - int offsetX, offsetY; - getTotalOffset(&offsetX, &offsetY); - dragRect.offsetRect(_posX + offsetX, _posY + offsetY); - - if (BasePlatform::ptInRect(&dragRect, _gameRef->_mousePos)) { - _dragFrom.x = _gameRef->_mousePos.x; - _dragFrom.y = _gameRef->_mousePos.y; - _dragging = true; - } - } - // end drag - else if (_dragging && event == MOUSE_RELEASE && button == MOUSE_BUTTON_LEFT) { - _dragging = false; - } - } - - return res; -} - - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::persist(BasePersistenceManager *persistMgr) { - - UIObject::persist(persistMgr); - - persistMgr->transfer(TMEMBER(_backInactive)); - persistMgr->transfer(TMEMBER(_clipContents)); - persistMgr->transfer(TMEMBER(_dragFrom)); - persistMgr->transfer(TMEMBER(_dragging)); - persistMgr->transfer(TMEMBER(_dragRect)); - persistMgr->transfer(TMEMBER(_fadeBackground)); - persistMgr->transfer(TMEMBER(_fadeColor)); - persistMgr->transfer(TMEMBER(_fontInactive)); - persistMgr->transfer(TMEMBER(_imageInactive)); - persistMgr->transfer(TMEMBER(_inGame)); - persistMgr->transfer(TMEMBER(_isMenu)); - persistMgr->transfer(TMEMBER_INT(_mode)); - persistMgr->transfer(TMEMBER(_shieldButton)); - persistMgr->transfer(TMEMBER(_shieldWindow)); - persistMgr->transfer(TMEMBER_INT(_titleAlign)); - persistMgr->transfer(TMEMBER(_titleRect)); - persistMgr->transfer(TMEMBER(_transparent)); - persistMgr->transfer(TMEMBER(_viewport)); - persistMgr->transfer(TMEMBER(_pauseMusic)); - - _widgets.persist(persistMgr); - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::moveFocus(bool forward) { - int i; - bool found = false; - for (i = 0; i < (int32)_widgets.size(); i++) { - if (_widgets[i] == _focusedWidget) { - found = true; - break; - } - } - if (!found) { - _focusedWidget = NULL; - } - - if (!_focusedWidget) { - if (_widgets.size() > 0) { - i = 0; - } else { - return STATUS_OK; - } - } - - int numTries = 0; - bool done = false; - - while (numTries <= (int32)_widgets.size()) { - if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) { - _focusedWidget = _widgets[i]; - done = true; - break; - } - - if (forward) { - i++; - if (i >= (int32)_widgets.size()) { - i = 0; - } - } else { - i--; - if (i < 0) { - i = _widgets.size() - 1; - } - } - numTries++; - } - - return done ? STATUS_OK : STATUS_FAILED; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::goExclusive() { - if (_mode == WINDOW_EXCLUSIVE) { - return STATUS_OK; - } - - if (_mode == WINDOW_NORMAL) { - _ready = false; - _mode = WINDOW_EXCLUSIVE; - _visible = true; - _disable = false; - _gameRef->focusWindow(this); - return STATUS_OK; - } else { - return STATUS_FAILED; - } -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::goSystemExclusive() { - if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { - return STATUS_OK; - } - - makeFreezable(false); - - _mode = WINDOW_SYSTEM_EXCLUSIVE; - _ready = false; - _visible = true; - _disable = false; - _gameRef->focusWindow(this); - - _gameRef->freeze(_pauseMusic); - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::close() { - if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { - _gameRef->unfreeze(); - } - - _mode = WINDOW_NORMAL; - _visible = false; - _ready = true; - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::listen(BaseScriptHolder *param1, uint32 param2) { - UIObject *obj = (UIObject *)param1; - - switch (obj->_type) { - case UI_BUTTON: - if (scumm_stricmp(obj->getName(), "close") == 0) { - close(); - } else { - return BaseObject::listen(param1, param2); - } - break; - default: - return BaseObject::listen(param1, param2); - } - - return STATUS_OK; -} - - -////////////////////////////////////////////////////////////////////////// -void UIWindow::makeFreezable(bool freezable) { - for (uint32 i = 0; i < _widgets.size(); i++) { - _widgets[i]->makeFreezable(freezable); - } - - BaseObject::makeFreezable(freezable); -} - - -////////////////////////////////////////////////////////////////////////// -bool UIWindow::getWindowObjects(BaseArray &objects, bool interactiveOnly) { - for (uint32 i = 0; i < _widgets.size(); i++) { - UIObject *control = _widgets[i]; - if (control->_disable && interactiveOnly) { - continue; - } - - switch (control->_type) { - case UI_WINDOW: - ((UIWindow *)control)->getWindowObjects(objects, interactiveOnly); - break; - - case UI_BUTTON: - case UI_EDIT: - objects.add(control); - break; - - default: - if (!interactiveOnly) { - objects.add(control); - } - } - } - return STATUS_OK; -} - -} // end of namespace Wintermute +/* 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/base_parser.h" +#include "engines/wintermute/base/base_active_rect.h" +#include "engines/wintermute/base/base_dynamic_buffer.h" +#include "engines/wintermute/base/base_keyboard_state.h" +#include "engines/wintermute/base/scriptables/script_value.h" +#include "engines/wintermute/ui/ui_button.h" +#include "engines/wintermute/ui/ui_edit.h" +#include "engines/wintermute/ui/ui_text.h" +#include "engines/wintermute/ui/ui_tiled_image.h" +#include "engines/wintermute/ui/ui_window.h" +#include "engines/wintermute/base/base_viewport.h" +#include "engines/wintermute/base/font/base_font_storage.h" +#include "engines/wintermute/base/font/base_font.h" +#include "engines/wintermute/base/base_string_table.h" +#include "engines/wintermute/base/scriptables/script.h" +#include "engines/wintermute/base/scriptables/script_stack.h" +#include "engines/wintermute/base/base_sprite.h" +#include "engines/wintermute/base/base_file_manager.h" +#include "engines/wintermute/platform_osystem.h" + +namespace Wintermute { + +IMPLEMENT_PERSISTENT(UIWindow, false) + +////////////////////////////////////////////////////////////////////////// +UIWindow::UIWindow(BaseGame *inGame) : UIObject(inGame) { + BasePlatform::setRectEmpty(&_titleRect); + BasePlatform::setRectEmpty(&_dragRect); + _titleAlign = TAL_LEFT; + _transparent = false; + + _backInactive = NULL; + _fontInactive = NULL; + _imageInactive = NULL; + + _type = UI_WINDOW; + _canFocus = true; + + _dragging = false; + _dragFrom.x = _dragFrom.y = 0; + + _mode = WINDOW_NORMAL; + _shieldWindow = NULL; + _shieldButton = NULL; + + _fadeColor = 0x00000000; + _fadeBackground = false; + + _ready = true; + _isMenu = false; + _inGame = false; + + _clipContents = false; + _viewport = NULL; + + _pauseMusic = true; +} + + +////////////////////////////////////////////////////////////////////////// +UIWindow::~UIWindow() { + close(); + cleanup(); +} + + +////////////////////////////////////////////////////////////////////////// +void UIWindow::cleanup() { + delete _shieldWindow; + delete _shieldButton; + delete _viewport; + _shieldWindow = NULL; + _shieldButton = NULL; + _viewport = NULL; + + delete _backInactive; + if (!_sharedFonts && _fontInactive) { + _gameRef->_fontStorage->removeFont(_fontInactive); + } + if (!_sharedImages && _imageInactive) { + delete _imageInactive; + } + + for (uint32 i = 0; i < _widgets.size(); i++) { + delete _widgets[i]; + } + _widgets.clear(); +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::display(int offsetX, int offsetY) { + // go exclusive + if (_mode == WINDOW_EXCLUSIVE || _mode == WINDOW_SYSTEM_EXCLUSIVE) { + if (!_shieldWindow) { + _shieldWindow = new UIWindow(_gameRef); + } + if (_shieldWindow) { + _shieldWindow->_posX = _shieldWindow->_posY = 0; + _shieldWindow->_width = _gameRef->_renderer->_width; + _shieldWindow->_height = _gameRef->_renderer->_height; + + _shieldWindow->display(); + } + } else if (_isMenu) { + if (!_shieldButton) { + _shieldButton = new UIButton(_gameRef); + _shieldButton->setName("close"); + _shieldButton->setListener(this, _shieldButton, 0); + _shieldButton->_parent = this; + } + if (_shieldButton) { + _shieldButton->_posX = _shieldButton->_posY = 0; + _shieldButton->_width = _gameRef->_renderer->_width; + _shieldButton->_height = _gameRef->_renderer->_height; + + _shieldButton->display(); + } + } + + if (!_visible) { + return STATUS_OK; + } + + if (_fadeBackground) { + Graphics::PixelFormat format = _gameRef->_renderer->getPixelFormat(); + byte fadeR, fadeG, fadeB, fadeA; + // First convert from the internal format to the screen-format + uint32 fadeColor = format.ARGBToColor(RGBCOLGetA(_fadeColor), RGBCOLGetR(_fadeColor), RGBCOLGetG(_fadeColor), RGBCOLGetB(_fadeColor)); + // Then get components + format.colorToARGB(fadeColor, fadeA, fadeR, fadeG, fadeB); + _gameRef->_renderer->fadeToColor(fadeR, fadeG, fadeB, fadeA); + } + + if (_dragging) { + _posX += (_gameRef->_mousePos.x - _dragFrom.x); + _posY += (_gameRef->_mousePos.y - _dragFrom.y); + + _dragFrom.x = _gameRef->_mousePos.x; + _dragFrom.y = _gameRef->_mousePos.y; + } + + if (!_focusedWidget || (!_focusedWidget->_canFocus || _focusedWidget->_disable || !_focusedWidget->_visible)) { + moveFocus(); + } + + bool popViewport = false; + if (_clipContents) { + if (!_viewport) { + _viewport = new BaseViewport(_gameRef); + } + if (_viewport) { + _viewport->setRect(_posX + offsetX, _posY + offsetY, _posX + _width + offsetX, _posY + _height + offsetY); + _gameRef->pushViewport(_viewport); + popViewport = true; + } + } + + + UITiledImage *back = _back; + BaseSprite *image = _image; + BaseFont *font = _font; + + if (!isFocused()) { + if (_backInactive) { + back = _backInactive; + } + if (_imageInactive) { + image = _imageInactive; + } + if (_fontInactive) { + font = _fontInactive; + } + } + + if (_alphaColor != 0) { + _gameRef->_renderer->_forceAlphaColor = _alphaColor; + } + if (back) { + back->display(_posX + offsetX, _posY + offsetY, _width, _height); + } + if (image) { + image->draw(_posX + offsetX, _posY + offsetY, _transparent ? NULL : this); + } + + if (!BasePlatform::isRectEmpty(&_titleRect) && font && _text) { + font->drawText((byte *)_text, _posX + offsetX + _titleRect.left, _posY + offsetY + _titleRect.top, _titleRect.right - _titleRect.left, _titleAlign, _titleRect.bottom - _titleRect.top); + } + + if (!_transparent && !image) { + _gameRef->_renderer->addRectToList(new BaseActiveRect(_gameRef, this, NULL, _posX + offsetX, _posY + offsetY, _width, _height, 100, 100, false)); + } + + for (uint32 i = 0; i < _widgets.size(); i++) { + _widgets[i]->display(_posX + offsetX, _posY + offsetY); + } + + if (_alphaColor != 0) { + _gameRef->_renderer->_forceAlphaColor = 0; + } + + if (popViewport) { + _gameRef->popViewport(); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::loadFile(const char *filename) { + byte *buffer = BaseFileManager::getEngineInstance()->readWholeFile(filename); + if (buffer == NULL) { + _gameRef->LOG(0, "UIWindow::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 WINDOW file '%s'", filename); + } + + delete[] buffer; + + return ret; +} + + +TOKEN_DEF_START +TOKEN_DEF(WINDOW) +TOKEN_DEF(ALPHA_COLOR) +TOKEN_DEF(ALPHA) +TOKEN_DEF(TEMPLATE) +TOKEN_DEF(DISABLED) +TOKEN_DEF(VISIBLE) +TOKEN_DEF(BACK_INACTIVE) +TOKEN_DEF(BACK) +TOKEN_DEF(IMAGE_INACTIVE) +TOKEN_DEF(IMAGE) +TOKEN_DEF(FONT_INACTIVE) +TOKEN_DEF(FONT) +TOKEN_DEF(TITLE_ALIGN) +TOKEN_DEF(TITLE_RECT) +TOKEN_DEF(TITLE) +TOKEN_DEF(DRAG_RECT) +TOKEN_DEF(X) +TOKEN_DEF(Y) +TOKEN_DEF(WIDTH) +TOKEN_DEF(HEIGHT) +TOKEN_DEF(FADE_ALPHA) +TOKEN_DEF(FADE_COLOR) +TOKEN_DEF(CURSOR) +TOKEN_DEF(NAME) +TOKEN_DEF(BUTTON) +TOKEN_DEF(STATIC) +TOKEN_DEF(TRANSPARENT) +TOKEN_DEF(SCRIPT) +TOKEN_DEF(CAPTION) +TOKEN_DEF(PARENT_NOTIFY) +TOKEN_DEF(MENU) +TOKEN_DEF(IN_GAME) +TOKEN_DEF(CLIP_CONTENTS) +TOKEN_DEF(PAUSE_MUSIC) +TOKEN_DEF(EDITOR_PROPERTY) +TOKEN_DEF(EDIT) +TOKEN_DEF_END +////////////////////////////////////////////////////////////////////////// +bool UIWindow::loadBuffer(byte *buffer, bool complete) { + TOKEN_TABLE_START(commands) + TOKEN_TABLE(WINDOW) + TOKEN_TABLE(ALPHA_COLOR) + TOKEN_TABLE(ALPHA) + TOKEN_TABLE(TEMPLATE) + TOKEN_TABLE(DISABLED) + TOKEN_TABLE(VISIBLE) + TOKEN_TABLE(BACK_INACTIVE) + TOKEN_TABLE(BACK) + TOKEN_TABLE(IMAGE_INACTIVE) + TOKEN_TABLE(IMAGE) + TOKEN_TABLE(FONT_INACTIVE) + TOKEN_TABLE(FONT) + TOKEN_TABLE(TITLE_ALIGN) + TOKEN_TABLE(TITLE_RECT) + TOKEN_TABLE(TITLE) + TOKEN_TABLE(DRAG_RECT) + TOKEN_TABLE(X) + TOKEN_TABLE(Y) + TOKEN_TABLE(WIDTH) + TOKEN_TABLE(HEIGHT) + TOKEN_TABLE(FADE_ALPHA) + TOKEN_TABLE(FADE_COLOR) + TOKEN_TABLE(CURSOR) + TOKEN_TABLE(NAME) + TOKEN_TABLE(BUTTON) + TOKEN_TABLE(STATIC) + TOKEN_TABLE(TRANSPARENT) + TOKEN_TABLE(SCRIPT) + TOKEN_TABLE(CAPTION) + TOKEN_TABLE(PARENT_NOTIFY) + TOKEN_TABLE(MENU) + TOKEN_TABLE(IN_GAME) + TOKEN_TABLE(CLIP_CONTENTS) + TOKEN_TABLE(PAUSE_MUSIC) + TOKEN_TABLE(EDITOR_PROPERTY) + TOKEN_TABLE(EDIT) + TOKEN_TABLE_END + + byte *params; + int cmd = 2; + BaseParser parser; + + int fadeR = 0, fadeG = 0, fadeB = 0, fadeA = 0; + int ar = 0, ag = 0, ab = 0, alpha = 0; + + if (complete) { + if (parser.getCommand((char **)&buffer, commands, (char **)¶ms) != TOKEN_WINDOW) { + _gameRef->LOG(0, "'WINDOW' keyword expected."); + return STATUS_FAILED; + } + buffer = params; + } + + while (cmd >= PARSERR_TOKENNOTFOUND && (cmd = parser.getCommand((char **)&buffer, commands, (char **)¶ms)) >= PARSERR_TOKENNOTFOUND) { + 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_BACK: + delete _back; + _back = new UITiledImage(_gameRef); + if (!_back || DID_FAIL(_back->loadFile((char *)params))) { + delete _back; + _back = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_BACK_INACTIVE: + delete _backInactive; + _backInactive = new UITiledImage(_gameRef); + if (!_backInactive || DID_FAIL(_backInactive->loadFile((char *)params))) { + delete _backInactive; + _backInactive = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE: + delete _image; + _image = new BaseSprite(_gameRef); + if (!_image || DID_FAIL(_image->loadFile((char *)params))) { + delete _image; + _image = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_IMAGE_INACTIVE: + delete _imageInactive, + _imageInactive = new BaseSprite(_gameRef); + if (!_imageInactive || DID_FAIL(_imageInactive->loadFile((char *)params))) { + delete _imageInactive; + _imageInactive = NULL; + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT: + if (_font) { + _gameRef->_fontStorage->removeFont(_font); + } + _font = _gameRef->_fontStorage->addFont((char *)params); + if (!_font) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_FONT_INACTIVE: + if (_fontInactive) { + _gameRef->_fontStorage->removeFont(_fontInactive); + } + _fontInactive = _gameRef->_fontStorage->addFont((char *)params); + if (!_fontInactive) { + cmd = PARSERR_GENERIC; + } + break; + + case TOKEN_TITLE: + setText((char *)params); + _gameRef->_stringTable->expand(&_text); + break; + + case TOKEN_TITLE_ALIGN: + if (scumm_stricmp((char *)params, "left") == 0) { + _titleAlign = TAL_LEFT; + } else if (scumm_stricmp((char *)params, "right") == 0) { + _titleAlign = TAL_RIGHT; + } else { + _titleAlign = TAL_CENTER; + } + break; + + case TOKEN_TITLE_RECT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_titleRect.left, &_titleRect.top, &_titleRect.right, &_titleRect.bottom); + break; + + case TOKEN_DRAG_RECT: + parser.scanStr((char *)params, "%d,%d,%d,%d", &_dragRect.left, &_dragRect.top, &_dragRect.right, &_dragRect.bottom); + break; + + case TOKEN_X: + parser.scanStr((char *)params, "%d", &_posX); + break; + + case TOKEN_Y: + parser.scanStr((char *)params, "%d", &_posY); + break; + + case TOKEN_WIDTH: + parser.scanStr((char *)params, "%d", &_width); + break; + + case TOKEN_HEIGHT: + parser.scanStr((char *)params, "%d", &_height); + 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_BUTTON: { + UIButton *btn = new UIButton(_gameRef); + if (!btn || DID_FAIL(btn->loadBuffer(params, false))) { + delete btn; + btn = NULL; + cmd = PARSERR_GENERIC; + } else { + btn->_parent = this; + _widgets.add(btn); + } + } + break; + + case TOKEN_STATIC: { + UIText *text = new UIText(_gameRef); + if (!text || DID_FAIL(text->loadBuffer(params, false))) { + delete text; + text = NULL; + cmd = PARSERR_GENERIC; + } else { + text->_parent = this; + _widgets.add(text); + } + } + break; + + case TOKEN_EDIT: { + UIEdit *edit = new UIEdit(_gameRef); + if (!edit || DID_FAIL(edit->loadBuffer(params, false))) { + delete edit; + edit = NULL; + cmd = PARSERR_GENERIC; + } else { + edit->_parent = this; + _widgets.add(edit); + } + } + break; + + case TOKEN_WINDOW: { + UIWindow *win = new UIWindow(_gameRef); + if (!win || DID_FAIL(win->loadBuffer(params, false))) { + delete win; + win = NULL; + cmd = PARSERR_GENERIC; + } else { + win->_parent = this; + _widgets.add(win); + } + } + break; + + + case TOKEN_TRANSPARENT: + parser.scanStr((char *)params, "%b", &_transparent); + break; + + case TOKEN_SCRIPT: + addScript((char *)params); + break; + + case TOKEN_PARENT_NOTIFY: + parser.scanStr((char *)params, "%b", &_parentNotify); + break; + + case TOKEN_PAUSE_MUSIC: + parser.scanStr((char *)params, "%b", &_pauseMusic); + break; + + case TOKEN_DISABLED: + parser.scanStr((char *)params, "%b", &_disable); + break; + + case TOKEN_VISIBLE: + parser.scanStr((char *)params, "%b", &_visible); + break; + + case TOKEN_MENU: + parser.scanStr((char *)params, "%b", &_isMenu); + break; + + case TOKEN_IN_GAME: + parser.scanStr((char *)params, "%b", &_inGame); + break; + + case TOKEN_CLIP_CONTENTS: + parser.scanStr((char *)params, "%b", &_clipContents); + break; + + case TOKEN_FADE_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &fadeR, &fadeG, &fadeB); + _fadeBackground = true; + break; + + case TOKEN_FADE_ALPHA: + parser.scanStr((char *)params, "%d", &fadeA); + _fadeBackground = true; + break; + + case TOKEN_EDITOR_PROPERTY: + parseEditorProperty(params, false); + break; + + case TOKEN_ALPHA_COLOR: + parser.scanStr((char *)params, "%d,%d,%d", &ar, &ag, &ab); + break; + + case TOKEN_ALPHA: + parser.scanStr((char *)params, "%d", &alpha); + break; + + + default: + if (DID_FAIL(_gameRef->windowLoadHook(this, (char **)&buffer, (char **)params))) { + cmd = PARSERR_GENERIC; + } + } + } + if (cmd == PARSERR_TOKENNOTFOUND) { + _gameRef->LOG(0, "Syntax error in WINDOW definition"); + return STATUS_FAILED; + } + if (cmd == PARSERR_GENERIC) { + _gameRef->LOG(0, "Error loading WINDOW definition"); + return STATUS_FAILED; + } + + correctSize(); + + if (alpha != 0 && ar == 0 && ag == 0 && ab == 0) { + ar = ag = ab = 255; + } + _alphaColor = BYTETORGBA(ar, ag, ab, alpha); + + if (_fadeBackground) { + _fadeColor = BYTETORGBA(fadeR, fadeG, fadeB, fadeA); + } + + _focusedWidget = NULL; + + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::saveAsText(BaseDynamicBuffer *buffer, int indent) { + buffer->putTextIndent(indent, "WINDOW\n"); + buffer->putTextIndent(indent, "{\n"); + + buffer->putTextIndent(indent + 2, "NAME=\"%s\"\n", getName()); + buffer->putTextIndent(indent + 2, "CAPTION=\"%s\"\n", getCaption()); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_back && _back->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK=\"%s\"\n", _back->getFilename()); + } + if (_backInactive && _backInactive->getFilename()) { + buffer->putTextIndent(indent + 2, "BACK_INACTIVE=\"%s\"\n", _backInactive->getFilename()); + } + + if (_image && _image->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE=\"%s\"\n", _image->getFilename()); + } + if (_imageInactive && _imageInactive->getFilename()) { + buffer->putTextIndent(indent + 2, "IMAGE_INACTIVE=\"%s\"\n", _imageInactive->getFilename()); + } + + if (_font && _font->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT=\"%s\"\n", _font->getFilename()); + } + if (_fontInactive && _fontInactive->getFilename()) { + buffer->putTextIndent(indent + 2, "FONT_INACTIVE=\"%s\"\n", _fontInactive->getFilename()); + } + + if (_cursor && _cursor->getFilename()) { + buffer->putTextIndent(indent + 2, "CURSOR=\"%s\"\n", _cursor->getFilename()); + } + + buffer->putTextIndent(indent + 2, "\n"); + + if (_text) { + buffer->putTextIndent(indent + 2, "TITLE=\"%s\"\n", _text); + } + + switch (_titleAlign) { + case TAL_LEFT: + buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "left"); + break; + case TAL_RIGHT: + buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "right"); + break; + case TAL_CENTER: + buffer->putTextIndent(indent + 2, "TITLE_ALIGN=\"%s\"\n", "center"); + break; + default: + error("UIWindow::SaveAsText - Unhandled enum-value NUM_TEXT_ALIGN"); + } + + if (!BasePlatform::isRectEmpty(&_titleRect)) { + buffer->putTextIndent(indent + 2, "TITLE_RECT { %d, %d, %d, %d }\n", _titleRect.left, _titleRect.top, _titleRect.right, _titleRect.bottom); + } + + if (!BasePlatform::isRectEmpty(&_dragRect)) { + buffer->putTextIndent(indent + 2, "DRAG_RECT { %d, %d, %d, %d }\n", _dragRect.left, _dragRect.top, _dragRect.right, _dragRect.bottom); + } + + buffer->putTextIndent(indent + 2, "\n"); + + buffer->putTextIndent(indent + 2, "X=%d\n", _posX); + buffer->putTextIndent(indent + 2, "Y=%d\n", _posY); + buffer->putTextIndent(indent + 2, "WIDTH=%d\n", _width); + buffer->putTextIndent(indent + 2, "HEIGHT=%d\n", _height); + + buffer->putTextIndent(indent + 2, "DISABLED=%s\n", _disable ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "VISIBLE=%s\n", _visible ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PARENT_NOTIFY=%s\n", _parentNotify ? "TRUE" : "FALSE"); + + buffer->putTextIndent(indent + 2, "TRANSPARENT=%s\n", _transparent ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "PAUSE_MUSIC=%s\n", _pauseMusic ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "MENU=%s\n", _isMenu ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "IN_GAME=%s\n", _inGame ? "TRUE" : "FALSE"); + buffer->putTextIndent(indent + 2, "CLIP_CONTENTS=%s\n", _clipContents ? "TRUE" : "FALSE"); + + buffer->putTextIndent(indent + 2, "\n"); + + if (_fadeBackground) { + buffer->putTextIndent(indent + 2, "FADE_COLOR { %d, %d, %d }\n", RGBCOLGetR(_fadeColor), RGBCOLGetG(_fadeColor), RGBCOLGetB(_fadeColor)); + buffer->putTextIndent(indent + 2, "FADE_ALPHA=%d\n", RGBCOLGetA(_fadeColor)); + } + + buffer->putTextIndent(indent + 2, "ALPHA_COLOR { %d, %d, %d }\n", RGBCOLGetR(_alphaColor), RGBCOLGetG(_alphaColor), RGBCOLGetB(_alphaColor)); + buffer->putTextIndent(indent + 2, "ALPHA=%d\n", RGBCOLGetA(_alphaColor)); + + buffer->putTextIndent(indent + 2, "\n"); + + // scripts + for (uint32 i = 0; i < _scripts.size(); i++) { + buffer->putTextIndent(indent + 2, "SCRIPT=\"%s\"\n", _scripts[i]->_filename); + } + + buffer->putTextIndent(indent + 2, "\n"); + + // editor properties + BaseClass::saveAsText(buffer, indent + 2); + + // controls + for (uint32 i = 0; i < _widgets.size(); i++) { + _widgets[i]->saveAsText(buffer, indent + 2); + } + + + buffer->putTextIndent(indent, "}\n"); + return STATUS_OK; +} + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::enableWidget(const char *name, bool enable) { + for (uint32 i = 0; i < _widgets.size(); i++) { + if (scumm_stricmp(_widgets[i]->getName(), name) == 0) { + _widgets[i]->_disable = !enable; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::showWidget(const char *name, bool visible) { + for (uint32 i = 0; i < _widgets.size(); i++) { + if (scumm_stricmp(_widgets[i]->getName(), name) == 0) { + _widgets[i]->_visible = visible; + } + } + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +// high level scripting interface +////////////////////////////////////////////////////////////////////////// +bool UIWindow::scCallMethod(ScScript *script, ScStack *stack, ScStack *thisStack, const char *name) { + ////////////////////////////////////////////////////////////////////////// + // GetWidget / GetControl + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "GetWidget") == 0 || strcmp(name, "GetControl") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + if (val->getType() == VAL_INT) { + int widget = val->getInt(); + if (widget < 0 || widget >= (int32)_widgets.size()) { + stack->pushNULL(); + } else { + stack->pushNative(_widgets[widget], true); + } + } else { + for (uint32 i = 0; i < _widgets.size(); i++) { + if (scumm_stricmp(_widgets[i]->getName(), val->getString()) == 0) { + stack->pushNative(_widgets[i], true); + return STATUS_OK; + } + } + stack->pushNULL(); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetInactiveFont + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetInactiveFont") == 0) { + stack->correctParams(1); + + if (_fontInactive) { + _gameRef->_fontStorage->removeFont(_fontInactive); + } + _fontInactive = _gameRef->_fontStorage->addFont(stack->pop()->getString()); + stack->pushBool(_fontInactive != NULL); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SetInactiveImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SetInactiveImage") == 0) { + stack->correctParams(1); + + delete _imageInactive; + _imageInactive = new BaseSprite(_gameRef); + const char *filename = stack->pop()->getString(); + if (!_imageInactive || DID_FAIL(_imageInactive->loadFile(filename))) { + delete _imageInactive; + _imageInactive = NULL; + stack->pushBool(false); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetInactiveImage + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetInactiveImage") == 0) { + stack->correctParams(0); + if (!_imageInactive || !_imageInactive->getFilename()) { + stack->pushNULL(); + } else { + stack->pushString(_imageInactive->getFilename()); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GetInactiveImageObject + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GetInactiveImageObject") == 0) { + stack->correctParams(0); + if (!_imageInactive) { + stack->pushNULL(); + } else { + stack->pushNative(_imageInactive, true); + } + + return STATUS_OK; + } + + + ////////////////////////////////////////////////////////////////////////// + // Close + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Close") == 0) { + stack->correctParams(0); + stack->pushBool(DID_SUCCEED(close())); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GoExclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GoExclusive") == 0) { + stack->correctParams(0); + goExclusive(); + script->waitFor(this); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // GoSystemExclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "GoSystemExclusive") == 0) { + stack->correctParams(0); + goSystemExclusive(); + script->waitFor(this); + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Center + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Center") == 0) { + stack->correctParams(0); + _posX = (_gameRef->_renderer->_width - _width) / 2; + _posY = (_gameRef->_renderer->_height - _height) / 2; + stack->pushNULL(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // LoadFromFile + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "LoadFromFile") == 0) { + stack->correctParams(1); + + ScValue *val = stack->pop(); + cleanup(); + if (!val->isNULL()) { + stack->pushBool(DID_SUCCEED(loadFile(val->getString()))); + } else { + stack->pushBool(true); + } + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateButton + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateButton") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + UIButton *btn = new UIButton(_gameRef); + if (!val->isNULL()) { + btn->setName(val->getString()); + } + stack->pushNative(btn, true); + + btn->_parent = this; + _widgets.add(btn); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateStatic + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateStatic") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + UIText *sta = new UIText(_gameRef); + if (!val->isNULL()) { + sta->setName(val->getString()); + } + stack->pushNative(sta, true); + + sta->_parent = this; + _widgets.add(sta); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateEditor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateEditor") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + UIEdit *edi = new UIEdit(_gameRef); + if (!val->isNULL()) { + edi->setName(val->getString()); + } + stack->pushNative(edi, true); + + edi->_parent = this; + _widgets.add(edi); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // CreateWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "CreateWindow") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + + UIWindow *win = new UIWindow(_gameRef); + if (!val->isNULL()) { + win->setName(val->getString()); + } + stack->pushNative(win, true); + + win->_parent = this; + _widgets.add(win); + + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // DeleteControl / DeleteButton / DeleteStatic / DeleteEditor / DeleteWindow + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "DeleteControl") == 0 || strcmp(name, "DeleteButton") == 0 || strcmp(name, "DeleteStatic") == 0 || strcmp(name, "DeleteEditor") == 0 || strcmp(name, "DeleteWindow") == 0) { + stack->correctParams(1); + ScValue *val = stack->pop(); + UIObject *obj = (UIObject *)val->getNative(); + + for (uint32 i = 0; i < _widgets.size(); i++) { + if (_widgets[i] == obj) { + delete _widgets[i]; + _widgets.remove_at(i); + if (val->getType() == VAL_VARIABLE_REF) { + val->setNULL(); + } + } + } + stack->pushNULL(); + return STATUS_OK; + } else if DID_SUCCEED(_gameRef->windowScriptMethodHook(this, script, stack, name)) { + return STATUS_OK; + } + + else { + return UIObject::scCallMethod(script, stack, thisStack, name); + } +} + + +////////////////////////////////////////////////////////////////////////// +ScValue *UIWindow::scGetProperty(const char *name) { + _scValue->setNULL(); + + ////////////////////////////////////////////////////////////////////////// + // Type + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Type") == 0) { + _scValue->setString("window"); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // NumWidgets / NumControls (RO) + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "NumWidgets") == 0 || strcmp(name, "NumControls") == 0) { + _scValue->setInt(_widgets.size()); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Exclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Exclusive") == 0) { + _scValue->setBool(_mode == WINDOW_EXCLUSIVE); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // SystemExclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SystemExclusive") == 0) { + _scValue->setBool(_mode == WINDOW_SYSTEM_EXCLUSIVE); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Menu + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Menu") == 0) { + _scValue->setBool(_isMenu); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // InGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InGame") == 0) { + _scValue->setBool(_inGame); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // PauseMusic + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PauseMusic") == 0) { + _scValue->setBool(_pauseMusic); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // ClipContents + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ClipContents") == 0) { + _scValue->setBool(_clipContents); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // Transparent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Transparent") == 0) { + _scValue->setBool(_transparent); + return _scValue; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeColor") == 0) { + _scValue->setInt((int)_fadeColor); + return _scValue; + } else { + return UIObject::scGetProperty(name); + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::scSetProperty(const char *name, ScValue *value) { + ////////////////////////////////////////////////////////////////////////// + // Name + ////////////////////////////////////////////////////////////////////////// + if (strcmp(name, "Name") == 0) { + setName(value->getString()); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Menu + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Menu") == 0) { + _isMenu = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // InGame + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "InGame") == 0) { + _inGame = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // PauseMusic + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "PauseMusic") == 0) { + _pauseMusic = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // ClipContents + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "ClipContents") == 0) { + _clipContents = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Transparent + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Transparent") == 0) { + _transparent = value->getBool(); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // FadeColor + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "FadeColor") == 0) { + _fadeColor = (uint32)value->getInt(); + _fadeBackground = (_fadeColor != 0); + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // Exclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "Exclusive") == 0) { + if (value->getBool()) { + goExclusive(); + } else { + close(); + _visible = true; + } + return STATUS_OK; + } + + ////////////////////////////////////////////////////////////////////////// + // SystemExclusive + ////////////////////////////////////////////////////////////////////////// + else if (strcmp(name, "SystemExclusive") == 0) { + if (value->getBool()) { + goSystemExclusive(); + } else { + close(); + _visible = true; + } + return STATUS_OK; + } else { + return UIObject::scSetProperty(name, value); + } +} + + +////////////////////////////////////////////////////////////////////////// +const char *UIWindow::scToString() { + return "[window]"; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::handleKeypress(Common::Event *event, bool printable) { +//TODO + if (event->type == Common::EVENT_KEYDOWN && event->kbd.keycode == Common::KEYCODE_TAB) { + return DID_SUCCEED(moveFocus(!BaseKeyboardState::isShiftDown())); + } else { + if (_focusedWidget) { + return _focusedWidget->handleKeypress(event, printable); + } else { + return false; + } + } + return false; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::handleMouseWheel(int Delta) { + if (_focusedWidget) { + return _focusedWidget->handleMouseWheel(Delta); + } else { + return false; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::handleMouse(TMouseEvent event, TMouseButton button) { + bool res = UIObject::handleMouse(event, button); + + // handle window dragging + if (!BasePlatform::isRectEmpty(&_dragRect)) { + // start drag + if (event == MOUSE_CLICK && button == MOUSE_BUTTON_LEFT) { + Rect32 dragRect = _dragRect; + int offsetX, offsetY; + getTotalOffset(&offsetX, &offsetY); + dragRect.offsetRect(_posX + offsetX, _posY + offsetY); + + if (BasePlatform::ptInRect(&dragRect, _gameRef->_mousePos)) { + _dragFrom.x = _gameRef->_mousePos.x; + _dragFrom.y = _gameRef->_mousePos.y; + _dragging = true; + } + } + // end drag + else if (_dragging && event == MOUSE_RELEASE && button == MOUSE_BUTTON_LEFT) { + _dragging = false; + } + } + + return res; +} + + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::persist(BasePersistenceManager *persistMgr) { + + UIObject::persist(persistMgr); + + persistMgr->transfer(TMEMBER(_backInactive)); + persistMgr->transfer(TMEMBER(_clipContents)); + persistMgr->transfer(TMEMBER(_dragFrom)); + persistMgr->transfer(TMEMBER(_dragging)); + persistMgr->transfer(TMEMBER(_dragRect)); + persistMgr->transfer(TMEMBER(_fadeBackground)); + persistMgr->transfer(TMEMBER(_fadeColor)); + persistMgr->transfer(TMEMBER(_fontInactive)); + persistMgr->transfer(TMEMBER(_imageInactive)); + persistMgr->transfer(TMEMBER(_inGame)); + persistMgr->transfer(TMEMBER(_isMenu)); + persistMgr->transfer(TMEMBER_INT(_mode)); + persistMgr->transfer(TMEMBER(_shieldButton)); + persistMgr->transfer(TMEMBER(_shieldWindow)); + persistMgr->transfer(TMEMBER_INT(_titleAlign)); + persistMgr->transfer(TMEMBER(_titleRect)); + persistMgr->transfer(TMEMBER(_transparent)); + persistMgr->transfer(TMEMBER(_viewport)); + persistMgr->transfer(TMEMBER(_pauseMusic)); + + _widgets.persist(persistMgr); + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::moveFocus(bool forward) { + int i; + bool found = false; + for (i = 0; i < (int32)_widgets.size(); i++) { + if (_widgets[i] == _focusedWidget) { + found = true; + break; + } + } + if (!found) { + _focusedWidget = NULL; + } + + if (!_focusedWidget) { + if (_widgets.size() > 0) { + i = 0; + } else { + return STATUS_OK; + } + } + + int numTries = 0; + bool done = false; + + while (numTries <= (int32)_widgets.size()) { + if (_widgets[i] != _focusedWidget && _widgets[i]->_canFocus && _widgets[i]->_visible && !_widgets[i]->_disable) { + _focusedWidget = _widgets[i]; + done = true; + break; + } + + if (forward) { + i++; + if (i >= (int32)_widgets.size()) { + i = 0; + } + } else { + i--; + if (i < 0) { + i = _widgets.size() - 1; + } + } + numTries++; + } + + return done ? STATUS_OK : STATUS_FAILED; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::goExclusive() { + if (_mode == WINDOW_EXCLUSIVE) { + return STATUS_OK; + } + + if (_mode == WINDOW_NORMAL) { + _ready = false; + _mode = WINDOW_EXCLUSIVE; + _visible = true; + _disable = false; + _gameRef->focusWindow(this); + return STATUS_OK; + } else { + return STATUS_FAILED; + } +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::goSystemExclusive() { + if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { + return STATUS_OK; + } + + makeFreezable(false); + + _mode = WINDOW_SYSTEM_EXCLUSIVE; + _ready = false; + _visible = true; + _disable = false; + _gameRef->focusWindow(this); + + _gameRef->freeze(_pauseMusic); + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::close() { + if (_mode == WINDOW_SYSTEM_EXCLUSIVE) { + _gameRef->unfreeze(); + } + + _mode = WINDOW_NORMAL; + _visible = false; + _ready = true; + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::listen(BaseScriptHolder *param1, uint32 param2) { + UIObject *obj = (UIObject *)param1; + + switch (obj->_type) { + case UI_BUTTON: + if (scumm_stricmp(obj->getName(), "close") == 0) { + close(); + } else { + return BaseObject::listen(param1, param2); + } + break; + default: + return BaseObject::listen(param1, param2); + } + + return STATUS_OK; +} + + +////////////////////////////////////////////////////////////////////////// +void UIWindow::makeFreezable(bool freezable) { + for (uint32 i = 0; i < _widgets.size(); i++) { + _widgets[i]->makeFreezable(freezable); + } + + BaseObject::makeFreezable(freezable); +} + + +////////////////////////////////////////////////////////////////////////// +bool UIWindow::getWindowObjects(BaseArray &objects, bool interactiveOnly) { + for (uint32 i = 0; i < _widgets.size(); i++) { + UIObject *control = _widgets[i]; + if (control->_disable && interactiveOnly) { + continue; + } + + switch (control->_type) { + case UI_WINDOW: + ((UIWindow *)control)->getWindowObjects(objects, interactiveOnly); + break; + + case UI_BUTTON: + case UI_EDIT: + objects.add(control); + break; + + default: + if (!interactiveOnly) { + objects.add(control); + } + } + } + return STATUS_OK; +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/ui/ui_window.h b/engines/wintermute/ui/ui_window.h index 8093e2b8f407..cbd417a7d90b 100644 --- a/engines/wintermute/ui/ui_window.h +++ b/engines/wintermute/ui/ui_window.h @@ -1,94 +1,94 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_UIWINDOW_H -#define WINTERMUTE_UIWINDOW_H - - -#include "engines/wintermute/ui/ui_object.h" -#include "common/events.h" - -namespace Wintermute { - -class UIButton; -class BaseViewport; -class UIWindow : public UIObject { - uint32 _fadeColor; -public: - bool getWindowObjects(BaseArray &Objects, bool InteractiveOnly); - - bool _pauseMusic; - void cleanup(); - virtual void makeFreezable(bool freezable); - BaseViewport *_viewport; - bool _clipContents; - bool _inGame; - bool _isMenu; - bool _fadeBackground; - - virtual bool handleMouseWheel(int delta); - UIWindow *_shieldWindow; - UIButton *_shieldButton; - bool close(); - bool goSystemExclusive(); - bool goExclusive(); - TWindowMode _mode; - bool moveFocus(bool forward = true); - virtual bool handleMouse(TMouseEvent Event, TMouseButton Button); - Point32 _dragFrom; - bool _dragging; - DECLARE_PERSISTENT(UIWindow, UIObject) - bool _transparent; - bool showWidget(const char *name, bool visible = true); - bool enableWidget(const char *name, bool enable = true); - Rect32 _titleRect; - Rect32 _dragRect; - virtual bool display(int offsetX = 0, int offsetY = 0); - UIWindow(BaseGame *inGame); - virtual ~UIWindow(); - virtual bool handleKeypress(Common::Event *event, bool printable = false); - BaseArray _widgets; - TTextAlign _titleAlign; - bool loadFile(const char *filename); - bool loadBuffer(byte *buffer, bool complete = true); - UITiledImage *_backInactive; - BaseFont *_fontInactive; - BaseSprite *_imageInactive; - virtual bool listen(BaseScriptHolder *param1, uint32 param2); - virtual 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 +/* 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_UIWINDOW_H +#define WINTERMUTE_UIWINDOW_H + + +#include "engines/wintermute/ui/ui_object.h" +#include "common/events.h" + +namespace Wintermute { + +class UIButton; +class BaseViewport; +class UIWindow : public UIObject { + uint32 _fadeColor; +public: + bool getWindowObjects(BaseArray &Objects, bool InteractiveOnly); + + bool _pauseMusic; + void cleanup(); + virtual void makeFreezable(bool freezable); + BaseViewport *_viewport; + bool _clipContents; + bool _inGame; + bool _isMenu; + bool _fadeBackground; + + virtual bool handleMouseWheel(int delta); + UIWindow *_shieldWindow; + UIButton *_shieldButton; + bool close(); + bool goSystemExclusive(); + bool goExclusive(); + TWindowMode _mode; + bool moveFocus(bool forward = true); + virtual bool handleMouse(TMouseEvent Event, TMouseButton Button); + Point32 _dragFrom; + bool _dragging; + DECLARE_PERSISTENT(UIWindow, UIObject) + bool _transparent; + bool showWidget(const char *name, bool visible = true); + bool enableWidget(const char *name, bool enable = true); + Rect32 _titleRect; + Rect32 _dragRect; + virtual bool display(int offsetX = 0, int offsetY = 0); + UIWindow(BaseGame *inGame); + virtual ~UIWindow(); + virtual bool handleKeypress(Common::Event *event, bool printable = false); + BaseArray _widgets; + TTextAlign _titleAlign; + bool loadFile(const char *filename); + bool loadBuffer(byte *buffer, bool complete = true); + UITiledImage *_backInactive; + BaseFont *_fontInactive; + BaseSprite *_imageInactive; + virtual bool listen(BaseScriptHolder *param1, uint32 param2); + virtual 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/utils/crc.cpp b/engines/wintermute/utils/crc.cpp index 8f608600f30c..e7ec45511b95 100644 --- a/engines/wintermute/utils/crc.cpp +++ b/engines/wintermute/utils/crc.cpp @@ -1,237 +1,237 @@ -/********************************************************************** - * - * Filename: crc.c - * - * Description: Slow and fast implementations of the CRC standards. - * - * Notes: The parameters for each supported CRC standard are - * defined in the header file crc.h. The implementations - * here should stand up to further additions to that list. - * - * - * Copyright (c) 2000 by Michael Barr. This software is placed into - * the public domain and may be used for any purpose. However, this - * notice must not be changed or removed and no warranty is either - * expressed or implied by its publication or distribution. - **********************************************************************/ - -#include "engines/wintermute/utils/crc.h" - -namespace Wintermute { - -/* - * Derive parameters from the standard-specific parameters in crc.h. - */ -#define WIDTH (8 * sizeof(crc)) -#define TOPBIT (1 << (WIDTH - 1)) - -#if (REFLECT_DATA == TRUE) -#undef REFLECT_DATA -#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) -#else -#undef REFLECT_DATA -#define REFLECT_DATA(X) (X) -#endif - -#if (REFLECT_REMAINDER == TRUE) -#undef REFLECT_REMAINDER -#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) -#else -#undef REFLECT_REMAINDER -#define REFLECT_REMAINDER(X) (X) -#endif - - -/********************************************************************* - * - * Function: reflect() - * - * Description: Reorder the bits of a binary sequence, by reflecting - * them about the middle position. - * - * Notes: No checking is done that nBits <= 32. - * - * Returns: The reflection of the original data. - * - *********************************************************************/ -static unsigned long -reflect(unsigned long data, unsigned char nBits) { - unsigned long reflection = 0x00000000; - unsigned char bit; - - /* - * Reflect the data about the center bit. - */ - for (bit = 0; bit < nBits; ++bit) { - /* - * If the LSB bit is set, set the reflection of it. - */ - if (data & 0x01) { - reflection |= (1 << ((nBits - 1) - bit)); - } - - data = (data >> 1); - } - - return (reflection); - -} /* reflect() */ - - -/********************************************************************* - * - * Function: crcSlow() - * - * Description: Compute the CRC of a given message. - * - * Notes: - * - * Returns: The CRC of the message. - * - *********************************************************************/ -crc -crcSlow(unsigned char const message[], int nBytes) { - crc remainder = INITIAL_REMAINDER; - int byte; - unsigned char bit; - - - /* - * Perform modulo-2 division, a byte at a time. - */ - for (byte = 0; byte < nBytes; ++byte) { - /* - * Bring the next byte into the remainder. - */ - remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); - - /* - * Perform modulo-2 division, a bit at a time. - */ - for (bit = 8; bit > 0; --bit) { - /* - * Try to divide the current data bit. - */ - if (remainder & TOPBIT) { - remainder = (remainder << 1) ^ POLYNOMIAL; - } else { - remainder = (remainder << 1); - } - } - } - - /* - * The final remainder is the CRC result. - */ - return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); - -} /* crcSlow() */ - - -crc crcTable[256]; - - -/********************************************************************* - * - * Function: crcInit() - * - * Description: Populate the partial CRC lookup table. - * - * Notes: This function must be rerun any time the CRC standard - * is changed. If desired, it can be run "offline" and - * the table results stored in an embedded system's ROM. - * - * Returns: None defined. - * - *********************************************************************/ -void -crcInit(void) { - crc remainder; - int dividend; - unsigned char bit; - - - /* - * Compute the remainder of each possible dividend. - */ - for (dividend = 0; dividend < 256; ++dividend) { - /* - * Start with the dividend followed by zeros. - */ - remainder = dividend << (WIDTH - 8); - - /* - * Perform modulo-2 division, a bit at a time. - */ - for (bit = 8; bit > 0; --bit) { - /* - * Try to divide the current data bit. - */ - if (remainder & TOPBIT) { - remainder = (remainder << 1) ^ POLYNOMIAL; - } else { - remainder = (remainder << 1); - } - } - - /* - * Store the result into the table. - */ - crcTable[dividend] = remainder; - } - -} /* crcInit() */ - - -/********************************************************************* - * - * Function: crcFast() - * - * Description: Compute the CRC of a given message. - * - * Notes: crcInit() must be called first. - * - * Returns: The CRC of the message. - * - *********************************************************************/ -crc -crcFast(unsigned char const message[], int nBytes) { - crc remainder = INITIAL_REMAINDER; - unsigned char data; - int byte; - - - /* - * Divide the message by the polynomial, a byte at a time. - */ - for (byte = 0; byte < nBytes; ++byte) { - data = (unsigned char)(REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8))); - remainder = crcTable[data] ^ (remainder << 8); - } - - /* - * The final remainder is the CRC. - */ - return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); - -} /* crcFast() */ - - - -crc crc_initialize(void) { - crcInit(); - return INITIAL_REMAINDER; -} - -crc crc_process_byte(unsigned char byteVal, crc remainder) { - unsigned char data; - data = (unsigned char)(REFLECT_DATA(byteVal) ^ (remainder >> (WIDTH - 8))); - remainder = crcTable[data] ^ (remainder << 8); - return remainder; -} - -crc crc_finalize(crc remainder) { - return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); -} - -} // end of namespace Wintermute +/********************************************************************** + * + * Filename: crc.c + * + * Description: Slow and fast implementations of the CRC standards. + * + * Notes: The parameters for each supported CRC standard are + * defined in the header file crc.h. The implementations + * here should stand up to further additions to that list. + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#include "engines/wintermute/utils/crc.h" + +namespace Wintermute { + +/* + * Derive parameters from the standard-specific parameters in crc.h. + */ +#define WIDTH (8 * sizeof(crc)) +#define TOPBIT (1 << (WIDTH - 1)) + +#if (REFLECT_DATA == TRUE) +#undef REFLECT_DATA +#define REFLECT_DATA(X) ((unsigned char) reflect((X), 8)) +#else +#undef REFLECT_DATA +#define REFLECT_DATA(X) (X) +#endif + +#if (REFLECT_REMAINDER == TRUE) +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) ((crc) reflect((X), WIDTH)) +#else +#undef REFLECT_REMAINDER +#define REFLECT_REMAINDER(X) (X) +#endif + + +/********************************************************************* + * + * Function: reflect() + * + * Description: Reorder the bits of a binary sequence, by reflecting + * them about the middle position. + * + * Notes: No checking is done that nBits <= 32. + * + * Returns: The reflection of the original data. + * + *********************************************************************/ +static unsigned long +reflect(unsigned long data, unsigned char nBits) { + unsigned long reflection = 0x00000000; + unsigned char bit; + + /* + * Reflect the data about the center bit. + */ + for (bit = 0; bit < nBits; ++bit) { + /* + * If the LSB bit is set, set the reflection of it. + */ + if (data & 0x01) { + reflection |= (1 << ((nBits - 1) - bit)); + } + + data = (data >> 1); + } + + return (reflection); + +} /* reflect() */ + + +/********************************************************************* + * + * Function: crcSlow() + * + * Description: Compute the CRC of a given message. + * + * Notes: + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcSlow(unsigned char const message[], int nBytes) { + crc remainder = INITIAL_REMAINDER; + int byte; + unsigned char bit; + + + /* + * Perform modulo-2 division, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) { + /* + * Bring the next byte into the remainder. + */ + remainder ^= (REFLECT_DATA(message[byte]) << (WIDTH - 8)); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) { + remainder = (remainder << 1) ^ POLYNOMIAL; + } else { + remainder = (remainder << 1); + } + } + } + + /* + * The final remainder is the CRC result. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcSlow() */ + + +crc crcTable[256]; + + +/********************************************************************* + * + * Function: crcInit() + * + * Description: Populate the partial CRC lookup table. + * + * Notes: This function must be rerun any time the CRC standard + * is changed. If desired, it can be run "offline" and + * the table results stored in an embedded system's ROM. + * + * Returns: None defined. + * + *********************************************************************/ +void +crcInit(void) { + crc remainder; + int dividend; + unsigned char bit; + + + /* + * Compute the remainder of each possible dividend. + */ + for (dividend = 0; dividend < 256; ++dividend) { + /* + * Start with the dividend followed by zeros. + */ + remainder = dividend << (WIDTH - 8); + + /* + * Perform modulo-2 division, a bit at a time. + */ + for (bit = 8; bit > 0; --bit) { + /* + * Try to divide the current data bit. + */ + if (remainder & TOPBIT) { + remainder = (remainder << 1) ^ POLYNOMIAL; + } else { + remainder = (remainder << 1); + } + } + + /* + * Store the result into the table. + */ + crcTable[dividend] = remainder; + } + +} /* crcInit() */ + + +/********************************************************************* + * + * Function: crcFast() + * + * Description: Compute the CRC of a given message. + * + * Notes: crcInit() must be called first. + * + * Returns: The CRC of the message. + * + *********************************************************************/ +crc +crcFast(unsigned char const message[], int nBytes) { + crc remainder = INITIAL_REMAINDER; + unsigned char data; + int byte; + + + /* + * Divide the message by the polynomial, a byte at a time. + */ + for (byte = 0; byte < nBytes; ++byte) { + data = (unsigned char)(REFLECT_DATA(message[byte]) ^ (remainder >> (WIDTH - 8))); + remainder = crcTable[data] ^ (remainder << 8); + } + + /* + * The final remainder is the CRC. + */ + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); + +} /* crcFast() */ + + + +crc crc_initialize(void) { + crcInit(); + return INITIAL_REMAINDER; +} + +crc crc_process_byte(unsigned char byteVal, crc remainder) { + unsigned char data; + data = (unsigned char)(REFLECT_DATA(byteVal) ^ (remainder >> (WIDTH - 8))); + remainder = crcTable[data] ^ (remainder << 8); + return remainder; +} + +crc crc_finalize(crc remainder) { + return (REFLECT_REMAINDER(remainder) ^ FINAL_XOR_VALUE); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/crc.h b/engines/wintermute/utils/crc.h index 9b9446ce571b..77c2ea267f15 100644 --- a/engines/wintermute/utils/crc.h +++ b/engines/wintermute/utils/crc.h @@ -1,85 +1,85 @@ -/********************************************************************** - * - * Filename: crc.h - * - * Description: A header file describing the various CRC standards. - * - * Notes: - * - * - * Copyright (c) 2000 by Michael Barr. This software is placed into - * the public domain and may be used for any purpose. However, this - * notice must not be changed or removed and no warranty is either - * expressed or implied by its publication or distribution. - **********************************************************************/ - -#ifndef _crc_h -#define _crc_h - -#include "common/system.h" // For types. - -namespace Wintermute { - -#ifndef TRUE -#define FALSE 0 -#define TRUE !FALSE -#endif - -/* - * Select the CRC standard from the list that follows. - */ -#define CRC32 - -#if defined(CRC_CCITT) - -typedef uint16 crc; - -#define CRC_NAME "CRC-CCITT" -#define POLYNOMIAL 0x1021 -#define INITIAL_REMAINDER 0xFFFF -#define FINAL_XOR_VALUE 0x0000 -#define REFLECT_DATA FALSE -#define REFLECT_REMAINDER FALSE -#define CHECK_VALUE 0x29B1 - -#elif defined(CRC16) - -typedef uint16 crc; - -#define CRC_NAME "CRC-16" -#define POLYNOMIAL 0x8005 -#define INITIAL_REMAINDER 0x0000 -#define FINAL_XOR_VALUE 0x0000 -#define REFLECT_DATA TRUE -#define REFLECT_REMAINDER TRUE -#define CHECK_VALUE 0xBB3D - -#elif defined(CRC32) - -typedef uint32 crc; - -#define CRC_NAME "CRC-32" -#define POLYNOMIAL 0x04C11DB7 -#define INITIAL_REMAINDER 0xFFFFFFFF -#define FINAL_XOR_VALUE 0xFFFFFFFF -#define REFLECT_DATA TRUE -#define REFLECT_REMAINDER TRUE -#define CHECK_VALUE 0xCBF43926 - -#else - -#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd." - -#endif - -void crcInit(void); -crc crcSlow(unsigned char const message[], int nBytes); -crc crcFast(unsigned char const message[], int nBytes); - -extern "C" crc crc_initialize(void); -extern "C" crc crc_process_byte(unsigned char byteVal, crc remainder); -extern "C" crc crc_finalize(crc remainder); - -} // End of namespace Wintermute - -#endif /* _crc_h */ +/********************************************************************** + * + * Filename: crc.h + * + * Description: A header file describing the various CRC standards. + * + * Notes: + * + * + * Copyright (c) 2000 by Michael Barr. This software is placed into + * the public domain and may be used for any purpose. However, this + * notice must not be changed or removed and no warranty is either + * expressed or implied by its publication or distribution. + **********************************************************************/ + +#ifndef _crc_h +#define _crc_h + +#include "common/system.h" // For types. + +namespace Wintermute { + +#ifndef TRUE +#define FALSE 0 +#define TRUE !FALSE +#endif + +/* + * Select the CRC standard from the list that follows. + */ +#define CRC32 + +#if defined(CRC_CCITT) + +typedef uint16 crc; + +#define CRC_NAME "CRC-CCITT" +#define POLYNOMIAL 0x1021 +#define INITIAL_REMAINDER 0xFFFF +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA FALSE +#define REFLECT_REMAINDER FALSE +#define CHECK_VALUE 0x29B1 + +#elif defined(CRC16) + +typedef uint16 crc; + +#define CRC_NAME "CRC-16" +#define POLYNOMIAL 0x8005 +#define INITIAL_REMAINDER 0x0000 +#define FINAL_XOR_VALUE 0x0000 +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xBB3D + +#elif defined(CRC32) + +typedef uint32 crc; + +#define CRC_NAME "CRC-32" +#define POLYNOMIAL 0x04C11DB7 +#define INITIAL_REMAINDER 0xFFFFFFFF +#define FINAL_XOR_VALUE 0xFFFFFFFF +#define REFLECT_DATA TRUE +#define REFLECT_REMAINDER TRUE +#define CHECK_VALUE 0xCBF43926 + +#else + +#error "One of CRC_CCITT, CRC16, or CRC32 must be #define'd." + +#endif + +void crcInit(void); +crc crcSlow(unsigned char const message[], int nBytes); +crc crcFast(unsigned char const message[], int nBytes); + +extern "C" crc crc_initialize(void); +extern "C" crc crc_process_byte(unsigned char byteVal, crc remainder); +extern "C" crc crc_finalize(crc remainder); + +} // End of namespace Wintermute + +#endif /* _crc_h */ diff --git a/engines/wintermute/utils/path_util.cpp b/engines/wintermute/utils/path_util.cpp index 55bf77684862..298f0c268f2c 100644 --- a/engines/wintermute/utils/path_util.cpp +++ b/engines/wintermute/utils/path_util.cpp @@ -1,101 +1,101 @@ -/* 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 "common/file.h" -#include "engines/wintermute/utils/path_util.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::unifySeparators(const AnsiString &path) { - AnsiString newPath = path; - - for (uint32 i = 0; i < newPath.size(); i++) { - if (newPath[i] == '\\') { - newPath.setChar('/', i); - } - } - - return newPath; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::normalizeFileName(const AnsiString &path) { - AnsiString newPath = unifySeparators(path); - newPath.toLowercase(); - return newPath; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::combine(const AnsiString &path1, const AnsiString &path2) { - AnsiString newPath1 = unifySeparators(path1); - AnsiString newPath2 = unifySeparators(path2); - - if (!newPath1.hasSuffix("/") && !newPath2.hasPrefix("/")) { - newPath1 += "/"; - } - - return newPath1 + newPath2; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getDirectoryName(const AnsiString &path) { - AnsiString newPath = unifySeparators(path); - Common::String filename = getFileName(path); - return Common::String(path.c_str(), path.size() - filename.size()); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getFileName(const AnsiString &path) { - AnsiString newPath = unifySeparators(path); - Common::String lastPart = Common::lastPathComponent(newPath, '/'); - if (lastPart[lastPart.size() - 1 ] != '/') { - return lastPart; - } else { - return path; - } -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getFileNameWithoutExtension(const AnsiString &path) { - AnsiString fileName = getFileName(path); - // TODO: Prettify this. - AnsiString extension = Common::lastPathComponent(fileName, '.'); - for (uint32 i = 0; i < extension.size() + 1; i++) { - fileName.deleteLastChar(); - } - return fileName; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString PathUtil::getExtension(const AnsiString &path) { - AnsiString fileName = getFileName(path); - return Common::lastPathComponent(path, '.'); -} - -} // end of namespace Wintermute +/* 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 "common/file.h" +#include "engines/wintermute/utils/path_util.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::unifySeparators(const AnsiString &path) { + AnsiString newPath = path; + + for (uint32 i = 0; i < newPath.size(); i++) { + if (newPath[i] == '\\') { + newPath.setChar('/', i); + } + } + + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::normalizeFileName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + newPath.toLowercase(); + return newPath; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::combine(const AnsiString &path1, const AnsiString &path2) { + AnsiString newPath1 = unifySeparators(path1); + AnsiString newPath2 = unifySeparators(path2); + + if (!newPath1.hasSuffix("/") && !newPath2.hasPrefix("/")) { + newPath1 += "/"; + } + + return newPath1 + newPath2; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getDirectoryName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + Common::String filename = getFileName(path); + return Common::String(path.c_str(), path.size() - filename.size()); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileName(const AnsiString &path) { + AnsiString newPath = unifySeparators(path); + Common::String lastPart = Common::lastPathComponent(newPath, '/'); + if (lastPart[lastPart.size() - 1 ] != '/') { + return lastPart; + } else { + return path; + } +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getFileNameWithoutExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + // TODO: Prettify this. + AnsiString extension = Common::lastPathComponent(fileName, '.'); + for (uint32 i = 0; i < extension.size() + 1; i++) { + fileName.deleteLastChar(); + } + return fileName; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString PathUtil::getExtension(const AnsiString &path) { + AnsiString fileName = getFileName(path); + return Common::lastPathComponent(path, '.'); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/path_util.h b/engines/wintermute/utils/path_util.h index 92adfd91b8a0..7358c2aba07a 100644 --- a/engines/wintermute/utils/path_util.h +++ b/engines/wintermute/utils/path_util.h @@ -1,49 +1,49 @@ -/* 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_PATHUTILS_H -#define WINTERMUTE_PATHUTILS_H - -#include "engines/wintermute/dctypes.h" - -namespace Wintermute { - -class PathUtil { -public: - static AnsiString unifySeparators(const AnsiString &path); - static AnsiString normalizeFileName(const AnsiString &path); - static AnsiString combine(const AnsiString &path1, const AnsiString &path2); - static AnsiString getDirectoryName(const AnsiString &path); - static AnsiString getFileName(const AnsiString &path); - static AnsiString getFileNameWithoutExtension(const AnsiString &path); - static AnsiString getExtension(const AnsiString &path); -}; - -} // end of namespace Wintermute - -#endif +/* 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_PATHUTILS_H +#define WINTERMUTE_PATHUTILS_H + +#include "engines/wintermute/dctypes.h" + +namespace Wintermute { + +class PathUtil { +public: + static AnsiString unifySeparators(const AnsiString &path); + static AnsiString normalizeFileName(const AnsiString &path); + static AnsiString combine(const AnsiString &path1, const AnsiString &path2); + static AnsiString getDirectoryName(const AnsiString &path); + static AnsiString getFileName(const AnsiString &path); + static AnsiString getFileNameWithoutExtension(const AnsiString &path); + static AnsiString getExtension(const AnsiString &path); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/utils/string_util.cpp b/engines/wintermute/utils/string_util.cpp index 63793f7d0b1c..2c3be8c2f5e2 100644 --- a/engines/wintermute/utils/string_util.cpp +++ b/engines/wintermute/utils/string_util.cpp @@ -1,232 +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 "common/tokenizer.h" -#include "engines/wintermute/utils/string_util.h" -#include "engines/wintermute/utils/convert_utf.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////////// -bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) { - return (str1.compareToIgnoreCase(str2) == 0); -} - -////////////////////////////////////////////////////////////////////////// -/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) { - WideString str1lc = str1; - WideString str2lc = str2; - - ToLowerCase(str1lc); - ToLowerCase(str2lc); - - return (str1lc == str2lc); -}*/ - -////////////////////////////////////////////////////////////////////////// -WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) { - error("StringUtil::Utf8ToWide - WideString not supported yet"); - /* size_t WideSize = Utf8Str.size(); - - if (sizeof(wchar_t) == 2) { - wchar_t *WideStringNative = new wchar_t[WideSize + 1]; - - const UTF8 *SourceStart = reinterpret_cast(Utf8Str.c_str()); - const UTF8 *SourceEnd = SourceStart + WideSize; - - UTF16 *TargetStart = reinterpret_cast(WideStringNative); - UTF16 *TargetEnd = TargetStart + WideSize + 1; - - ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); - if (res != conversionOK) { - delete[] WideStringNative; - return L""; - } - *TargetStart = 0; - WideString ResultString(WideStringNative); - delete[] WideStringNative; - - return ResultString; - } else if (sizeof(wchar_t) == 4) { - wchar_t *WideStringNative = new wchar_t[WideSize + 1]; - - const UTF8 *SourceStart = reinterpret_cast(Utf8Str.c_str()); - const UTF8 *SourceEnd = SourceStart + WideSize; - - UTF32 *TargetStart = reinterpret_cast(WideStringNative); - UTF32 *TargetEnd = TargetStart + WideSize; - - ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); - if (res != conversionOK) { - delete[] WideStringNative; - return L""; - } - *TargetStart = 0; - WideString ResultString(WideStringNative); - delete[] WideStringNative; - - return ResultString; - } else { - return L""; - }*/ - return ""; -} - -////////////////////////////////////////////////////////////////////////// -Utf8String StringUtil::wideToUtf8(const WideString &WideStr) { - error("StringUtil::wideToUtf8 - Widestring not supported yet"); - /* size_t WideSize = WideStr.length(); - - if (sizeof(wchar_t) == 2) { - size_t utf8Size = 3 * WideSize + 1; - char *utf8StringNative = new char[Utf8Size]; - - const UTF16 *SourceStart = reinterpret_cast(WideStr.c_str()); - const UTF16 *SourceEnd = SourceStart + WideSize; - - UTF8 *TargetStart = reinterpret_cast(Utf8StringNative); - UTF8 *TargetEnd = TargetStart + Utf8Size; - - ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); - if (res != conversionOK) { - delete[] Utf8StringNative; - return (Utf8String)""; - } - *TargetStart = 0; - Utf8String ResultString(Utf8StringNative); - delete[] Utf8StringNative; - return ResultString; - } else if (sizeof(wchar_t) == 4) { - size_t utf8Size = 4 * WideSize + 1; - char *utf8StringNative = new char[Utf8Size]; - - const UTF32 *SourceStart = reinterpret_cast(WideStr.c_str()); - const UTF32 *SourceEnd = SourceStart + WideSize; - - UTF8 *TargetStart = reinterpret_cast(Utf8StringNative); - UTF8 *TargetEnd = TargetStart + Utf8Size; - - ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); - if (res != conversionOK) { - delete[] Utf8StringNative; - return (Utf8String)""; - } - *TargetStart = 0; - Utf8String ResultString(Utf8StringNative); - delete[] Utf8StringNative; - return ResultString; - } else { - return (Utf8String)""; - }*/ - return ""; -} - -// Currently this only does Ansi->ISO 8859, and only for carets. -char simpleAnsiToWide(const AnsiString &str, uint32 &offset) { - char c = str[offset]; - - if (c == 92) { - offset++; - return '\''; - } else { - offset++; - return c; - } -} - -////////////////////////////////////////////////////////////////////////// -WideString StringUtil::ansiToWide(const AnsiString &str) { - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - /*Common::String converted = ""; - uint32 index = 0; - while (index != str.size()) { - converted += simpleAnsiToWide(str, index); - }*/ - // using default os locale! - - /* setlocale(LC_CTYPE, ""); - size_t wideSize = mbstowcs(NULL, str.c_str(), 0) + 1; - wchar_t *wstr = new wchar_t[WideSize]; - mbstowcs(wstr, str.c_str(), WideSize); - WideString ResultString(wstr); - delete[] wstr; - return ResultString;*/ - return WideString(str); -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::wideToAnsi(const WideString &wstr) { - // using default os locale! - // TODO: This function gets called a lot, so warnings like these drown out the usefull information - /* setlocale(LC_CTYPE, ""); - size_t wideSize = wcstombs(NULL, wstr.c_str(), 0) + 1; - char *str = new char[WideSize]; - wcstombs(str, wstr.c_str(), WideSize); - AnsiString ResultString(str); - delete[] str; - return ResultString;*/ - return AnsiString(wstr); -} - -////////////////////////////////////////////////////////////////////////// -bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) { - if (bufferSize > 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) { - return true; - } else { - return false; - } -} - -////////////////////////////////////////////////////////////////////////// -int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { - const char *index = strstr(str.c_str(), toFind.c_str()); - if (index == NULL) { - return -1; - } else { - return index - str.c_str(); - } -} - -Common::String StringUtil::encodeSetting(const Common::String &str) { - if (str.contains('=')) { - error("Setting contains '='"); - } - return str; -} - -Common::String StringUtil::decodeSetting(const Common::String &str) { - return str; -} - -////////////////////////////////////////////////////////////////////////// -AnsiString StringUtil::toString(int val) { - return Common::String::format("%d", val); -} - - -} // end of namespace Wintermute +/* 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 "common/tokenizer.h" +#include "engines/wintermute/utils/string_util.h" +#include "engines/wintermute/utils/convert_utf.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////////// +bool StringUtil::compareNoCase(const AnsiString &str1, const AnsiString &str2) { + return (str1.compareToIgnoreCase(str2) == 0); +} + +////////////////////////////////////////////////////////////////////////// +/*bool StringUtil::CompareNoCase(const WideString &str1, const WideString &str2) { + WideString str1lc = str1; + WideString str2lc = str2; + + ToLowerCase(str1lc); + ToLowerCase(str2lc); + + return (str1lc == str2lc); +}*/ + +////////////////////////////////////////////////////////////////////////// +WideString StringUtil::utf8ToWide(const Utf8String &Utf8Str) { + error("StringUtil::Utf8ToWide - WideString not supported yet"); + /* size_t WideSize = Utf8Str.size(); + + if (sizeof(wchar_t) == 2) { + wchar_t *WideStringNative = new wchar_t[WideSize + 1]; + + const UTF8 *SourceStart = reinterpret_cast(Utf8Str.c_str()); + const UTF8 *SourceEnd = SourceStart + WideSize; + + UTF16 *TargetStart = reinterpret_cast(WideStringNative); + UTF16 *TargetEnd = TargetStart + WideSize + 1; + + ConversionResult res = ConvertUTF8toUTF16(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] WideStringNative; + return L""; + } + *TargetStart = 0; + WideString ResultString(WideStringNative); + delete[] WideStringNative; + + return ResultString; + } else if (sizeof(wchar_t) == 4) { + wchar_t *WideStringNative = new wchar_t[WideSize + 1]; + + const UTF8 *SourceStart = reinterpret_cast(Utf8Str.c_str()); + const UTF8 *SourceEnd = SourceStart + WideSize; + + UTF32 *TargetStart = reinterpret_cast(WideStringNative); + UTF32 *TargetEnd = TargetStart + WideSize; + + ConversionResult res = ConvertUTF8toUTF32(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] WideStringNative; + return L""; + } + *TargetStart = 0; + WideString ResultString(WideStringNative); + delete[] WideStringNative; + + return ResultString; + } else { + return L""; + }*/ + return ""; +} + +////////////////////////////////////////////////////////////////////////// +Utf8String StringUtil::wideToUtf8(const WideString &WideStr) { + error("StringUtil::wideToUtf8 - Widestring not supported yet"); + /* size_t WideSize = WideStr.length(); + + if (sizeof(wchar_t) == 2) { + size_t utf8Size = 3 * WideSize + 1; + char *utf8StringNative = new char[Utf8Size]; + + const UTF16 *SourceStart = reinterpret_cast(WideStr.c_str()); + const UTF16 *SourceEnd = SourceStart + WideSize; + + UTF8 *TargetStart = reinterpret_cast(Utf8StringNative); + UTF8 *TargetEnd = TargetStart + Utf8Size; + + ConversionResult res = ConvertUTF16toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] Utf8StringNative; + return (Utf8String)""; + } + *TargetStart = 0; + Utf8String ResultString(Utf8StringNative); + delete[] Utf8StringNative; + return ResultString; + } else if (sizeof(wchar_t) == 4) { + size_t utf8Size = 4 * WideSize + 1; + char *utf8StringNative = new char[Utf8Size]; + + const UTF32 *SourceStart = reinterpret_cast(WideStr.c_str()); + const UTF32 *SourceEnd = SourceStart + WideSize; + + UTF8 *TargetStart = reinterpret_cast(Utf8StringNative); + UTF8 *TargetEnd = TargetStart + Utf8Size; + + ConversionResult res = ConvertUTF32toUTF8(&SourceStart, SourceEnd, &TargetStart, TargetEnd, strictConversion); + if (res != conversionOK) { + delete[] Utf8StringNative; + return (Utf8String)""; + } + *TargetStart = 0; + Utf8String ResultString(Utf8StringNative); + delete[] Utf8StringNative; + return ResultString; + } else { + return (Utf8String)""; + }*/ + return ""; +} + +// Currently this only does Ansi->ISO 8859, and only for carets. +char simpleAnsiToWide(const AnsiString &str, uint32 &offset) { + char c = str[offset]; + + if (c == 92) { + offset++; + return '\''; + } else { + offset++; + return c; + } +} + +////////////////////////////////////////////////////////////////////////// +WideString StringUtil::ansiToWide(const AnsiString &str) { + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + /*Common::String converted = ""; + uint32 index = 0; + while (index != str.size()) { + converted += simpleAnsiToWide(str, index); + }*/ + // using default os locale! + + /* setlocale(LC_CTYPE, ""); + size_t wideSize = mbstowcs(NULL, str.c_str(), 0) + 1; + wchar_t *wstr = new wchar_t[WideSize]; + mbstowcs(wstr, str.c_str(), WideSize); + WideString ResultString(wstr); + delete[] wstr; + return ResultString;*/ + return WideString(str); +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::wideToAnsi(const WideString &wstr) { + // using default os locale! + // TODO: This function gets called a lot, so warnings like these drown out the usefull information + /* setlocale(LC_CTYPE, ""); + size_t wideSize = wcstombs(NULL, wstr.c_str(), 0) + 1; + char *str = new char[WideSize]; + wcstombs(str, wstr.c_str(), WideSize); + AnsiString ResultString(str); + delete[] str; + return ResultString;*/ + return AnsiString(wstr); +} + +////////////////////////////////////////////////////////////////////////// +bool StringUtil::isUtf8BOM(const byte *buffer, uint32 bufferSize) { + if (bufferSize > 3 && buffer[0] == 0xEF && buffer[1] == 0xBB && buffer[2] == 0xBF) { + return true; + } else { + return false; + } +} + +////////////////////////////////////////////////////////////////////////// +int StringUtil::indexOf(const WideString &str, const WideString &toFind, size_t startFrom) { + const char *index = strstr(str.c_str(), toFind.c_str()); + if (index == NULL) { + return -1; + } else { + return index - str.c_str(); + } +} + +Common::String StringUtil::encodeSetting(const Common::String &str) { + if (str.contains('=')) { + error("Setting contains '='"); + } + return str; +} + +Common::String StringUtil::decodeSetting(const Common::String &str) { + return str; +} + +////////////////////////////////////////////////////////////////////////// +AnsiString StringUtil::toString(int val) { + return Common::String::format("%d", val); +} + + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/string_util.h b/engines/wintermute/utils/string_util.h index 87760971a87b..e419e2bca866 100644 --- a/engines/wintermute/utils/string_util.h +++ b/engines/wintermute/utils/string_util.h @@ -1,56 +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_STRINGUTIL_H -#define WINTERMUTE_STRINGUTIL_H - -#include "engines/wintermute/dctypes.h" - -namespace Wintermute { - -class StringUtil { -public: - static bool compareNoCase(const AnsiString &str1, const AnsiString &str2); - //static bool compareNoCase(const WideString &str1, const WideString &str2); - static WideString utf8ToWide(const Utf8String &Utf8Str); - static Utf8String wideToUtf8(const WideString &WideStr); - static WideString ansiToWide(const AnsiString &str); - static AnsiString wideToAnsi(const WideString &str); - - static bool isUtf8BOM(const byte *buffer, uint32 bufferSize); - static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom); - - static Common::String encodeSetting(const Common::String &str); - static Common::String decodeSetting(const Common::String &str); - - static AnsiString toString(int val); -}; - -} // end of namespace Wintermute - -#endif +/* 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_STRINGUTIL_H +#define WINTERMUTE_STRINGUTIL_H + +#include "engines/wintermute/dctypes.h" + +namespace Wintermute { + +class StringUtil { +public: + static bool compareNoCase(const AnsiString &str1, const AnsiString &str2); + //static bool compareNoCase(const WideString &str1, const WideString &str2); + static WideString utf8ToWide(const Utf8String &Utf8Str); + static Utf8String wideToUtf8(const WideString &WideStr); + static WideString ansiToWide(const AnsiString &str); + static AnsiString wideToAnsi(const WideString &str); + + static bool isUtf8BOM(const byte *buffer, uint32 bufferSize); + static int indexOf(const WideString &str, const WideString &toFind, size_t startFrom); + + static Common::String encodeSetting(const Common::String &str); + static Common::String decodeSetting(const Common::String &str); + + static AnsiString toString(int val); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/utils/utils.cpp b/engines/wintermute/utils/utils.cpp index f26d60b7cf49..824b16ccdb4e 100644 --- a/engines/wintermute/utils/utils.cpp +++ b/engines/wintermute/utils/utils.cpp @@ -1,261 +1,261 @@ -/* 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/utils/utils.h" -#include "engines/wintermute/wintermute.h" -#include "engines/wintermute/base/base_engine.h" - -namespace Wintermute { - -////////////////////////////////////////////////////////////////////// -static inline unsigned Sqr(int x) { - return (x * x); -} - -////////////////////////////////////////////////////////////////////////////////// -// Swap - swaps two integers -////////////////////////////////////////////////////////////////////////////////// -void BaseUtils::swap(int *a, int *b) { - int temp = *a; - *a = *b; - *b = temp; -} - - -////////////////////////////////////////////////////////////////////////// -float BaseUtils::normalizeAngle(float angle) { - while (angle > 360) { - angle -= 360; - } - while (angle < 0) { - angle += 360; - } - - return angle; -} - - -//////////////////////////////////////////////////////////////////////////////// -void BaseUtils::createPath(const char *path, bool pathOnly) { - /* AnsiString pathStr; - - if (!pathOnly) pathStr = PathUtil::getDirectoryName(path); - else pathStr = path; - */ -// try { - warning("BaseUtils::CreatePath - not implemented: %s", path); -// boost::filesystem::create_directories(path); -// } catch (...) { - return; -// } -} - - -////////////////////////////////////////////////////////////////////////// -void BaseUtils::debugMessage(const char *text) { - //MessageBox(hWnd, Text, "WME", MB_OK|MB_ICONINFORMATION); -} - - -////////////////////////////////////////////////////////////////////////// -char *BaseUtils::setString(char **string, const char *value) { - delete[] *string; - *string = new char[strlen(value) + 1]; - if (*string) { - strcpy(*string, value); - } - return *string; -} - -////////////////////////////////////////////////////////////////////////// -char *BaseUtils::strEntry(int entry, const char *str, const char delim) { - int numEntries = 0; - - const char *start = NULL; - int len = 0; - - for (uint32 i = 0; i <= strlen(str); i++) { - if (numEntries == entry) { - if (!start) { - start = str + i; - } else { - len++; - } - } - if (str[i] == delim || str[i] == '\0') { - numEntries++; - if (start) { - char *ret = new char[len + 1]; - memset(ret, 0, len + 1); - Common::strlcpy(ret, start, len + 1); - return ret; - } - } - } - return NULL; -} - -////////////////////////////////////////////////////////////////////////// -int BaseUtils::randomInt(int from, int to) { - if (to < from) { - int i = to; - to = from; - from = i; - } - return BaseEngine::instance().randInt(from, to); -// return (rand() % (to - from + 1)) + from; -} - -////////////////////////////////////////////////////////////////////////// -float BaseUtils::randomFloat(float from, float to) { - const uint32 randMax = RAND_MAX; - float randNum = (float)BaseEngine::instance().randInt(0, randMax) / (float)randMax; - return from + (to - from) * randNum; -} - -////////////////////////////////////////////////////////////////////////// -float BaseUtils::randomAngle(float from, float to) { - while (to < from) { - to += 360; - } - return normalizeAngle(randomFloat(from, to)); -} - -////////////////////////////////////////////////////////////////////////// -void BaseUtils::RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL) { - float varR = (RGBCOLGetR(rgbColor) / 255.0f); - float varG = (RGBCOLGetG(rgbColor) / 255.0f); - float varB = (RGBCOLGetB(rgbColor) / 255.0f); - - //Min. value of RGB - float varMin = MIN(varR, varG); - varMin = MIN(varMin, varB); - - //Max. value of RGB - float varMax = MAX(varR, varG); - varMax = MAX(varMax, varB); - - //Delta RGB value - float delMax = varMax - varMin; - - float H = 0.0f, S = 0.0f, L = 0.0f; - - L = (varMax + varMin) / 2.0f; - - //This is a gray, no chroma... - if (delMax == 0) { - H = 0; - S = 0; - } - //Chromatic data... - else { - if (L < 0.5f) { - S = delMax / (varMax + varMin); - } else { - S = delMax / (2.0f - varMax - varMin); - } - - float delR = (((varMax - varR) / 6.0f) + (delMax / 2.0f)) / delMax; - float delG = (((varMax - varG) / 6.0f) + (delMax / 2.0f)) / delMax; - float delB = (((varMax - varB) / 6.0f) + (delMax / 2.0f)) / delMax; - - if (varR == varMax) { - H = delB - delG; - } else if (varG == varMax) { - H = (1.0f / 3.0f) + delR - delB; - } else if (varB == varMax) { - H = (2.0f / 3.0f) + delG - delR; - } - - if (H < 0) { - H += 1; - } - if (H > 1) { - H -= 1; - } - } - - *outH = (byte)(H * 255); - *outS = (byte)(S * 255); - *outL = (byte)(L * 255); -} - - -////////////////////////////////////////////////////////////////////////// -uint32 BaseUtils::HSLtoRGB(byte InH, byte InS, byte InL) { - float H = InH / 255.0f; - float S = InS / 255.0f; - float L = InL / 255.0f; - - byte R, G, B; - - - if (S == 0) { - R = (byte)(L * 255); - G = (byte)(L * 255); - B = (byte)(L * 255); - } else { - float var1, var2; - - if (L < 0.5) { - var2 = L * (1.0 + S); - } else { - var2 = (L + S) - (S * L); - } - - var1 = 2.0f * L - var2; - - R = (byte)(255 * Hue2RGB(var1, var2, H + (1.0f / 3.0f))); - G = (byte)(255 * Hue2RGB(var1, var2, H)); - B = (byte)(255 * Hue2RGB(var1, var2, H - (1.0f / 3.0f))); - } - return BYTETORGBA(255, R, G, B); -} - - -////////////////////////////////////////////////////////////////////////// -float BaseUtils::Hue2RGB(float v1, float v2, float vH) { - if (vH < 0.0f) { - vH += 1.0f; - } - if (vH > 1.0f) { - vH -= 1.0f; - } - if ((6.0f * vH) < 1.0f) { - return (v1 + (v2 - v1) * 6.0f * vH); - } - if ((2.0f * vH) < 1.0f) { - return (v2); - } - if ((3.0f * vH) < 2.0f) { - return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f); - } - return (v1); -} - -} // end of namespace Wintermute +/* 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/utils/utils.h" +#include "engines/wintermute/wintermute.h" +#include "engines/wintermute/base/base_engine.h" + +namespace Wintermute { + +////////////////////////////////////////////////////////////////////// +static inline unsigned Sqr(int x) { + return (x * x); +} + +////////////////////////////////////////////////////////////////////////////////// +// Swap - swaps two integers +////////////////////////////////////////////////////////////////////////////////// +void BaseUtils::swap(int *a, int *b) { + int temp = *a; + *a = *b; + *b = temp; +} + + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::normalizeAngle(float angle) { + while (angle > 360) { + angle -= 360; + } + while (angle < 0) { + angle += 360; + } + + return angle; +} + + +//////////////////////////////////////////////////////////////////////////////// +void BaseUtils::createPath(const char *path, bool pathOnly) { + /* AnsiString pathStr; + + if (!pathOnly) pathStr = PathUtil::getDirectoryName(path); + else pathStr = path; + */ +// try { + warning("BaseUtils::CreatePath - not implemented: %s", path); +// boost::filesystem::create_directories(path); +// } catch (...) { + return; +// } +} + + +////////////////////////////////////////////////////////////////////////// +void BaseUtils::debugMessage(const char *text) { + //MessageBox(hWnd, Text, "WME", MB_OK|MB_ICONINFORMATION); +} + + +////////////////////////////////////////////////////////////////////////// +char *BaseUtils::setString(char **string, const char *value) { + delete[] *string; + *string = new char[strlen(value) + 1]; + if (*string) { + strcpy(*string, value); + } + return *string; +} + +////////////////////////////////////////////////////////////////////////// +char *BaseUtils::strEntry(int entry, const char *str, const char delim) { + int numEntries = 0; + + const char *start = NULL; + int len = 0; + + for (uint32 i = 0; i <= strlen(str); i++) { + if (numEntries == entry) { + if (!start) { + start = str + i; + } else { + len++; + } + } + if (str[i] == delim || str[i] == '\0') { + numEntries++; + if (start) { + char *ret = new char[len + 1]; + memset(ret, 0, len + 1); + Common::strlcpy(ret, start, len + 1); + return ret; + } + } + } + return NULL; +} + +////////////////////////////////////////////////////////////////////////// +int BaseUtils::randomInt(int from, int to) { + if (to < from) { + int i = to; + to = from; + from = i; + } + return BaseEngine::instance().randInt(from, to); +// return (rand() % (to - from + 1)) + from; +} + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::randomFloat(float from, float to) { + const uint32 randMax = RAND_MAX; + float randNum = (float)BaseEngine::instance().randInt(0, randMax) / (float)randMax; + return from + (to - from) * randNum; +} + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::randomAngle(float from, float to) { + while (to < from) { + to += 360; + } + return normalizeAngle(randomFloat(from, to)); +} + +////////////////////////////////////////////////////////////////////////// +void BaseUtils::RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL) { + float varR = (RGBCOLGetR(rgbColor) / 255.0f); + float varG = (RGBCOLGetG(rgbColor) / 255.0f); + float varB = (RGBCOLGetB(rgbColor) / 255.0f); + + //Min. value of RGB + float varMin = MIN(varR, varG); + varMin = MIN(varMin, varB); + + //Max. value of RGB + float varMax = MAX(varR, varG); + varMax = MAX(varMax, varB); + + //Delta RGB value + float delMax = varMax - varMin; + + float H = 0.0f, S = 0.0f, L = 0.0f; + + L = (varMax + varMin) / 2.0f; + + //This is a gray, no chroma... + if (delMax == 0) { + H = 0; + S = 0; + } + //Chromatic data... + else { + if (L < 0.5f) { + S = delMax / (varMax + varMin); + } else { + S = delMax / (2.0f - varMax - varMin); + } + + float delR = (((varMax - varR) / 6.0f) + (delMax / 2.0f)) / delMax; + float delG = (((varMax - varG) / 6.0f) + (delMax / 2.0f)) / delMax; + float delB = (((varMax - varB) / 6.0f) + (delMax / 2.0f)) / delMax; + + if (varR == varMax) { + H = delB - delG; + } else if (varG == varMax) { + H = (1.0f / 3.0f) + delR - delB; + } else if (varB == varMax) { + H = (2.0f / 3.0f) + delG - delR; + } + + if (H < 0) { + H += 1; + } + if (H > 1) { + H -= 1; + } + } + + *outH = (byte)(H * 255); + *outS = (byte)(S * 255); + *outL = (byte)(L * 255); +} + + +////////////////////////////////////////////////////////////////////////// +uint32 BaseUtils::HSLtoRGB(byte InH, byte InS, byte InL) { + float H = InH / 255.0f; + float S = InS / 255.0f; + float L = InL / 255.0f; + + byte R, G, B; + + + if (S == 0) { + R = (byte)(L * 255); + G = (byte)(L * 255); + B = (byte)(L * 255); + } else { + float var1, var2; + + if (L < 0.5) { + var2 = L * (1.0 + S); + } else { + var2 = (L + S) - (S * L); + } + + var1 = 2.0f * L - var2; + + R = (byte)(255 * Hue2RGB(var1, var2, H + (1.0f / 3.0f))); + G = (byte)(255 * Hue2RGB(var1, var2, H)); + B = (byte)(255 * Hue2RGB(var1, var2, H - (1.0f / 3.0f))); + } + return BYTETORGBA(255, R, G, B); +} + + +////////////////////////////////////////////////////////////////////////// +float BaseUtils::Hue2RGB(float v1, float v2, float vH) { + if (vH < 0.0f) { + vH += 1.0f; + } + if (vH > 1.0f) { + vH -= 1.0f; + } + if ((6.0f * vH) < 1.0f) { + return (v1 + (v2 - v1) * 6.0f * vH); + } + if ((2.0f * vH) < 1.0f) { + return (v2); + } + if ((3.0f * vH) < 2.0f) { + return (v1 + (v2 - v1) * ((2.0f / 3.0f) - vH) * 6.0f); + } + return (v1); +} + +} // end of namespace Wintermute diff --git a/engines/wintermute/utils/utils.h b/engines/wintermute/utils/utils.h index af69bd4523e3..d6a603ec7269 100644 --- a/engines/wintermute/utils/utils.h +++ b/engines/wintermute/utils/utils.h @@ -1,64 +1,64 @@ -/* ScummVM - Graphic Adventure Engine - * - * ScummVM is the legal property of its developers, whose names - * are too numerous to list here. Please refer to the COPYRIGHT - * file distributed with this source distribution. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License - * as published by the Free Software Foundation; either version 2 - * of the License, or (at your option) any later version. - - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - * - */ - -/* - * This file is based on WME Lite. - * http://dead-code.org/redir.php?target=wmelite - * Copyright (c) 2011 Jan Nedoma - */ - -#ifndef WINTERMUTE_UTILS_H -#define WINTERMUTE_UTILS_H - -#include "engines/wintermute/wintypes.h" -#include "engines/wintermute/math/rect32.h" - -namespace Wintermute { - -class BaseGame; - -class BaseUtils { -public: - static void swap(int *a, int *b); - static float normalizeAngle(float angle); - - static void createPath(const char *path, bool pathOnly = false); - - static void debugMessage(const char *text); - static char *setString(char **string, const char *value); - - static char *strEntry(int entry, const char *str, const char delim = ','); - - static int randomInt(int from, int to); - static float randomFloat(float from, float to); - static float randomAngle(float from, float to); - - static void RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL); - static uint32 HSLtoRGB(byte H, byte S, byte L); - -private: - static float Hue2RGB(float v1, float v2, float vH); -}; - -} // end of namespace Wintermute - -#endif +/* 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_UTILS_H +#define WINTERMUTE_UTILS_H + +#include "engines/wintermute/wintypes.h" +#include "engines/wintermute/math/rect32.h" + +namespace Wintermute { + +class BaseGame; + +class BaseUtils { +public: + static void swap(int *a, int *b); + static float normalizeAngle(float angle); + + static void createPath(const char *path, bool pathOnly = false); + + static void debugMessage(const char *text); + static char *setString(char **string, const char *value); + + static char *strEntry(int entry, const char *str, const char delim = ','); + + static int randomInt(int from, int to); + static float randomFloat(float from, float to); + static float randomAngle(float from, float to); + + static void RGBtoHSL(uint32 rgbColor, byte *outH, byte *outS, byte *outL); + static uint32 HSLtoRGB(byte H, byte S, byte L); + +private: + static float Hue2RGB(float v1, float v2, float vH); +}; + +} // end of namespace Wintermute + +#endif diff --git a/engines/wintermute/wintypes.h b/engines/wintermute/wintypes.h index a83a31f2ea18..c7723808ea9f 100644 --- a/engines/wintermute/wintypes.h +++ b/engines/wintermute/wintypes.h @@ -1,53 +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_WINTYPES_H -#define WINTERMUTE_WINTYPES_H - -#include "common/scummsys.h" - -namespace Wintermute { - -#define BYTETORGBA(r,g,b,a) ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) - -#define RGBCOLGetB(rgb) ((byte )(rgb)) -#define RGBCOLGetG(rgb) ((byte )(((uint16)(rgb)) >> 8)) -#define RGBCOLGetR(rgb) ((byte )((rgb)>>16)) -#define RGBCOLGetA(rgb) ((byte )((rgb)>>24)) - -#define DID_SUCCEED(hr) ((bool)(hr)) -#define DID_FAIL(hr) (!((bool)(hr))) - -#define STATUS_OK (true) -#define STATUS_FAILED (false) - -#define MAX_PATH_LENGTH 512 - -} // end of namespace Wintermute - -#endif +/* 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_WINTYPES_H +#define WINTERMUTE_WINTYPES_H + +#include "common/scummsys.h" + +namespace Wintermute { + +#define BYTETORGBA(r,g,b,a) ((uint32)((((a)&0xff)<<24)|(((r)&0xff)<<16)|(((g)&0xff)<<8)|((b)&0xff))) + +#define RGBCOLGetB(rgb) ((byte )(rgb)) +#define RGBCOLGetG(rgb) ((byte )(((uint16)(rgb)) >> 8)) +#define RGBCOLGetR(rgb) ((byte )((rgb)>>16)) +#define RGBCOLGetA(rgb) ((byte )((rgb)>>24)) + +#define DID_SUCCEED(hr) ((bool)(hr)) +#define DID_FAIL(hr) (!((bool)(hr))) + +#define STATUS_OK (true) +#define STATUS_FAILED (false) + +#define MAX_PATH_LENGTH 512 + +} // end of namespace Wintermute + +#endif